Skip to content

Incomplete destructive-command blocklist allows auto-execution of filesystem-destroying commands in headless/auto mode #13001

Description

@geo-chen

Before submitting your bug report

Relevant environment info

commit eaa23c5

Description

reported on 13 June 2026 via email - no response, trying here:

Summary

In the Continue CLI's headless (cn -p) and auto modes, the default policy sets Bash to allow, so the only backstop against a malicious LLM-emitted terminal command is the terminal-security evaluator returning a "disabled" verdict. That denylist is incomplete: it fails to flag rm -rf of /home, /root, /var, /opt, /srv, fails to flag rm -rf $HOME (shell-quote drops the $HOME token, which the shell re-expands at execution), and never disables find -delete, shred, wipefs, truncate, or pkexec. Because the agent autonomously ingests untrusted content (web pages via the Fetch tool, repo files, issue/PR text, MCP output) that is allow-by-default, indirect prompt injection can drive an unattended, irreversible wipe of the user's home directory or data partitions. Confirmed against the compiled evaluator and a shell.

Details

In headless/auto mode the default permission policy sets Bash -> allow (extensions/cli/src/permissions/defaultPolicies.ts:31-33, AUTO_MODE_POLICIES ~69-71), and the Fetch tool is allow-by-default (~21). Per extensions/cli/src/permissions/permissionChecker.ts:161-174, a disabled verdict forces exclude (hard block), but any other verdict lets the user's allow preference win and the command executes with no prompt. So isCriticalCommand is the sole guard.

packages/terminal-security/src/evaluateTerminalCommandSecurity.ts (evaluateSingleCommand -> isCriticalCommand, ~402-560):

  • The dangerous-rm check (~411-439) requires both hasRf and hasDangerousPath, where hasDangerousPath only matches /, /*, ~, ~/*, /usr, /etc, /bin, /sbin and those prefixes. /home, /root, /var, /opt, /srv are absent.
  • shell-quote (~70/93) parses $HOME to an empty-string token, so rm -rf $HOME becomes ["rm","-rf",""] -> hasDangerousPath=false -> not disabled. The shell re-expands $HOME at execution (spawn, extensions/cli/src/tools/runTerminalCommand.ts:144-152) and wipes the home directory.
  • find ... -delete is only "high-risk" (-> allowedWithPermission), never disabled. shred, wipefs, truncate, and pkexec are unhandled.

The untrusted input is the allow-by-default content the agent ingests (web/Fetch, repo files, issue/PR text, MCP tool output); indirect prompt injection in any of it steers the model to emit a command that survives the denylist.

To reproduce

PoC

scripts/poc_continue_terminal_blocklist.md.

A malicious web page / repo file / issue body the agent reads contains instructions that lead the model to emit, in cn -p/auto mode, rm -rf $HOME (or rm -rf /home, find / -delete, shred -u ...).

Validated by building the package and calling the actual exported evaluateTerminalCommandSecurity, plus a faithful reproduction of checkToolPermission under AUTO_MODE_POLICIES:

MODE: auto/headless (AUTO_MODE_POLICIES = [{tool:'*',permission:'allow'}])
EXECUTES WITHOUT PROMPT  <- rm -rf $HOME
EXECUTES WITHOUT PROMPT  <- rm -rf /home
EXECUTES WITHOUT PROMPT  <- rm -rf /root
EXECUTES WITHOUT PROMPT  <- rm -rf /var
EXECUTES WITHOUT PROMPT  <- find / -delete
EXECUTES WITHOUT PROMPT  <- shred -u /dev/sda
BLOCKED (exclude)        <- rm -rf /            (evaluator DOES block these - the blocklist is the intended control)
BLOCKED (exclude)        <- sudo rm -rf /etc

shell proof that $HOME re-expands at execution despite the policy pass:

BEFORE: .../fakehome/Documents/thesis.txt exists
$ bash -c 'rm -rf $HOME'
AFTER:  ls: cannot access '.../fakehome': No such file or directory   (thesis -> NO_DELETED)

Impact

In unattended Continue CLI runs (CI/scripts via cn -p, or --auto), a single prompt-injection payload in content the agent reads triggers irreversible deletion of the user's home directory or /var//root//opt//srv, or device wipe via shred/wipefs, with no prompt. The blocklist gap is also a defense-in-depth failure in interactive mode.

Remediation

Make the rm critical check trigger on -rf regardless of path (or treat any recursive-force rm of an absolute/$VAR/~-derived path as disabled), and expand hasDangerousPath to include /home, /root, /var, /opt, /srv and bare home/$HOME. Resolve env-var/~ tokens (or treat an empty-string token produced from a $-expansion as a wildcard dangerous path) before the dangerous-path test rather than letting shell-quote drop them. Add find with -delete/-exec rm, shred, wipefs, truncate -s 0, and pkexec to the disabled set. Strategically, for unattended execution prefer an explicit per-command allowlist over a denylist, or never let auto mode downgrade Bash below allowedWithPermission.

Log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:bugIndicates an unexpected problem or unintended behavior

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions