{"record":{"id":"9fdc27a22e2dc63f","repo":"charmbracelet/crush","slug":"command-is-not-allowed-for-security-reasons-q","errorCode":null,"errorMessage":"command is not allowed for security reasons: %q","messagePattern":"command is not allowed for security reasons: %q","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/shell/run.go","lineNumber":343,"sourceCode":"\t\t\t\treturn h(ctx, args, hc.Stdin, hc.Stdout, hc.Stderr)\n\t\t\t}\n\t\t\treturn next(ctx, args)\n\t\t}\n\t}\n}\n\n// blockHandler returns middleware that rejects commands matched by any of\n// the provided [BlockFunc]s before they reach the underlying exec path.\n// A nil or empty blockFuncs slice is a no-op.\nfunc blockHandler(blockFuncs []BlockFunc) execMiddleware {\n\treturn func(next interp.ExecHandlerFunc) interp.ExecHandlerFunc {\n\t\treturn func(ctx context.Context, args []string) error {\n\t\t\tif len(args) == 0 {\n\t\t\t\treturn next(ctx, args)\n\t\t\t}\n\t\t\tfor _, blockFunc := range blockFuncs {\n\t\t\t\tif blockFunc(args) {\n\t\t\t\t\treturn fmt.Errorf(\"command is not allowed for security reasons: %q\", args[0])\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn next(ctx, args)\n\t\t}\n\t}\n}\n","sourceCodeStart":325,"sourceCodeEnd":350,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/shell/run.go#L325-L350","documentation":"This is the command-blocking middleware built from blockFuncs in run.go. For each executed command it checks the argument list against every registered block function; if any returns true, the command is refused with \"command is not allowed for security reasons: %q\" before reaching the interpreter. It is an intentional policy denial, not an internal failure.","triggerScenarios":"Calling shell.Run with RunOpts.BlockFuncs containing a predicate that matches the command (e.g. blocking 'rm', 'curl', or commands whose first arg is on a deny list). Empty argument lists fall through to next, so only non-empty commands can be blocked.","commonSituations":"Users of Crush running a command the project's permission policy disallows; tests (TestCommandBlocking, TestArgumentsBlocker, TestCommandsBlocker) verifying deny lists; misconfigured allow-lists that accidentally match benign commands like 'git push'.","solutions":["Use a command permitted by the project's security policy instead of the blocked one.","If the block is too broad, adjust the BlockFuncs predicates to match only genuinely dangerous argument patterns.","If the command is safe and required, add it to the allow-list/configure permissions so the blocking predicate no longer matches.","Check args[0] in the message: it names the exact blocked command token."],"exampleFix":"// before\nblock := func(args []string) bool { return args[0] == \"rm\" }\n// after — allow safe variants\nblock := func(args []string) bool {\n\treturn args[0] == \"rm\" && !slices.Contains(args, \"-rf\")\n}","handlingStrategy":"try-catch","validationCode":"func isBlocked(cmd string, blockFuncs []func([]string) bool) bool {\n\targs := strings.Fields(cmd)\n\tif len(args) == 0 { return false }\n\tfor _, bf := range blockFuncs { if bf(args) { return true } }\n\treturn false\n}","typeGuard":null,"tryCatchPattern":"err := shell.Run(ctx, opts)\nif err != nil && strings.Contains(err.Error(), \"not allowed for security reasons\") {\n\t// treat as user-facing policy denial: show message, do not retry\n}","preventionTips":["Pre-check commands against your block predicates before submitting them to the agent.","Keep deny lists narrow (match exact args[0] plus dangerous flags) to avoid false positives.","Document permitted commands for users so denied commands are expected.","Log blocked attempts with the full args for auditing."],"tags":["security","policy","command-blocking"],"backgroundTag":"command-blocked-by-policy","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}