google-gemini/gemini-cli · error · Error

${this.commandName} cannot be run. Blocked command: "${comma

Error message

${this.commandName} cannot be run. Blocked command: "${command}". Reason: Blocked by policy.

What it means

Thrown by ShellProcessor when config.getPolicyEngine().check() returns PolicyDecision.DENY for a resolved shell command. The command matched a deny rule in the security policy and is blocked outright (distinct from ASK_USER, which requests confirmation).

Source

Thrown at packages/cli/src/services/prompt-processors/shellProcessor.ts:136

      const command = injection.resolvedCommand;

      if (!command) continue;

      if (context.session.sessionShellAllowlist?.has(command)) {
        continue;
      }

      // Security check on the final, escaped command string.
      const { decision } = await config.getPolicyEngine().check(
        {
          name: 'run_shell_command',
          args: { command },
        },
        undefined,
      );

      if (decision === PolicyDecision.DENY) {
        throw new Error(
          `${this.commandName} cannot be run. Blocked command: "${command}". Reason: Blocked by policy.`,
        );
      } else if (decision === PolicyDecision.ASK_USER) {
        commandsToConfirm.add(command);
      }
    }

    // Handle confirmation requirements.
    if (commandsToConfirm.size > 0) {
      throw new ConfirmationRequiredError(
        'Shell command confirmation required',
        Array.from(commandsToConfirm),
      );
    }

    let processedPrompt = '';
    let lastIndex = 0;

View on GitHub (pinned to 5024443c72)

Solutions

  1. Inspect the denied command in the message and reword the injection so it does not match a deny rule.
  2. Add the exact command to the session shell allowlist (session.sessionShellAllowlist) if it is safe and intended.
  3. Review the security policy in settings.json and adjust deny rules if the block is overly broad.
  4. Avoid passing {{args}} that expand the command into a denied form.

Example fix

// before — policy denies rm
cleanup !{rm -rf ./build}
// after — allowlisted safe alternative
cleanup !{./scripts/clean-build.sh}
Defensive patterns

Strategy: try-catch

Validate before calling

async function isAllowed(command: string, config: Config): Promise<boolean> {
  const { decision } = await config.getPolicyEngine().check(
    { name: 'run_shell_command', args: { command } }, undefined);
  return decision !== PolicyDecision.DENY;
}

Type guard

function isDenied(decision: PolicyDecision): boolean {
  return decision === PolicyDecision.DENY;
}

Try / catch

try {
  await shellProcessor.process(prompt, ctx);
} catch (e) {
  if (e instanceof Error && /Blocked by policy/.test(e.message)) {
    // reword the command or add it to the allowlist/policy
  }
  throw e;
}

Prevention

When it happens

Trigger: A '!{...}' injection resolves to a command that the policy engine denies (e.g. matches a blocked command pattern / denylist) and is not on the session shell allowlist.

Common situations: The resolved command matches a deny entry in settings security rules; a corporate/managed policy blocks the command; the command string after {{args}} substitution fell into a denied pattern.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/0cb6aefce3392c0f. Report an issue: GitHub.