continuedev / continuedev/continue
Incomplete destructive-command blocklist allows auto-execution of filesystem-destroying commands in headless/auto mode
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 36k
- Forks
- 5.4k
- PR merge metrics
- No merged PRs in 30d
Description
Before submitting your bug report
- I've tried finding an answer on the Continue docs site
- I'm not able to find an open issue that reports the same bug
- I've seen the troubleshooting guide on the Continue Docs
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-
rmcheck (~411-439) requires bothhasRfandhasDangerousPath, wherehasDangerousPathonly matches/,/*,~,~/*,/usr,/etc,/bin,/sbinand those prefixes./home,/root,/var,/opt,/srvare absent. - shell-quote (~70/93) parses
$HOMEto an empty-string token, sorm -rf $HOMEbecomes["rm","-rf",""]->hasDangerousPath=false-> not disabled. The shell re-expands$HOMEat execution (spawn,extensions/cli/src/tools/runTerminalCommand.ts:144-152) and wipes the home directory. find ... -deleteis only "high-risk" (-> allowedWithPermission), never disabled.shred,wipefs,truncate, andpkexecare 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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/terminal-security/src/evaluateTerminalCommandSecurity.ts, especially evaluateSingleCommand and isCriticalCommand, then trace permission handling in extensions/cli/src/permissions/permissionChecker.ts and the Bash policies in defaultPolicies.ts. Reproduce the listed commands using scripts/poc_continue_terminal_blocklist.md; done means dangerous filesystem and device-destruction commands receive a disabled verdict and cannot execute under auto/headless policy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- shell, typescript
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100