// threat brief

Roo Code auto-approve bypass: the ${ command; } form lets denied shell commands slip past the check

CVSS
7.7 HIGH
CISA KEV
Not listed
Weakness
CWE-436

PlainCVE Team · Published 2026-10-18 · AI-assisted · Press brief ↓

AI review 2026-10-18 (not human-reviewed)Command tests: none yetReproduced: not yetVerification record ↓

Roo Code ≤3.54.0 misreads ${ cmd; } syntax; with auto-approve on and bash 5.3+/ksh93, prompt-injected agents can run denied commands unapproved. No known fix.

Who is affectedPeople using Roo Code 3.54.0 or earlier with auto-approve for command execution turned on (the CVE record's title says Auto-Approve; the setting name "always approve execute" comes from the researcher's write-up). Per the CVE record, two more things must also hold - the agent reads attacker-controlled content (indirect prompt injection), and the allowlist contains an outer command, such as echo, that the denied command can be wrapped in. The hidden command only actually runs if the shell is bash 5.3 or later, or ksh93.
What happensIf the AI agent reads a file, web page, repository or MCP result containing malicious instructions, it may propose a harmless-looking command that hides a command you put on your denylist. That command then runs with the agent's auto-execute privileges, without asking you.
What to do nowNo fixed version is known and the project is archived. Our analysis: turning off "always approve execute" would likely avoid the automatic execution; longer term, consider moving to a tool that is still maintained.
Affected versionsAll versions through 3.54.0 (the researcher tested main-branch commit b867ec9, which the researcher labels v3.53.0; per the repository history, that commit comes after the v3.54.0 release)
Fixed versionsNo known fixed version; the project is archived and v3.54.0 is the last extension release
CVSS vector
Show full vectorCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Timeline
  • First public 2026-10-13

Blue team playbook

Check, fix / mitigate, respond, harden. Matching the affected versions does not mean you were compromised, and a check that finds nothing does not prove you are safe; each item says what it can and cannot show. Tagged steps point to where the attack flow below can be stopped.

DETECTCheckAm I affected? Any signs of compromise?
  1. 01Check whether you use Roo Code 3.54.0 or earlier

    Where to run it: in a terminal (bash or zsh) on the computer where VS Code is installed; it only lists the extensions and versions installed in that computer's VS Code. Everything through 3.54.0 is affected. The releases page lists v3.54.0 as the latest extension release, so our analysis is that any installed version is likely in the affected range. Whether you are actually exposed depends on the auto-approve setting and your shell. Limitation: this only works with VS Code's `code` CLI; if you use Roo Code in another VS Code-compatible editor, this command won't find it, so use that editor's own CLI or extensions view instead.

    Read-only check
    code --list-extensions --show-versions | grep -i roo
  2. 02Check the auto-approve setting and your shell version

    The hidden command only runs automatically if "always approve execute" is on and the agent's shell is bash 5.3+ or ksh93. Where to run it: in VS Code's integrated terminal on the computer where Roo Code actually runs commands; it only reads a version and changes nothing. Limitation: this shows the bash found on your PATH, which isn't necessarily the shell the agent uses; it can't detect ksh93 and can't check the auto-approve setting. Roo Code's documentation labels "Use Inline Terminal" as recommended; two places in the source code set its default differently, so we can't confirm whether it is on by default. Per the documentation, when it is on it runs commands through a background execa provider, bypassing shell profiles and VS Code shell integration, and the documentation doesn't say which shell is used then. Only with Inline Terminal turned off does Roo Code use VS Code's integrated terminal and your shell profile (you can see the default profile with "Terminal: Select Default Profile" in the Command Palette). So the shell the agent actually uses needs to be confirmed separately, not just from the default profile; whether auto-approve is on has to be checked in Roo Code's auto-approve settings.

    Read-only check
    bash --version | head -n 1
  3. 03Review the terminal commands the agent ran

    Our suggestion: look back at commands the agent auto-ran, watching for allowlisted commands that contain a ${ construct wrapping another command. The sources give no detection guidance.

MITIGATEFix / mitigatePatch; block it if you cannot patch yet
  1. 01Turn off "always approve execute"

    This is our analysis, not vendor guidance: the bypass needs auto-approve, and with it off every command asks you first.

  2. 02Don't combine auto-approve with bash 5.3+ or ksh93

    Our analysis: the researcher says shells without this syntax won't run the hidden command, but the parser flaw remains, so this lowers risk rather than fixing it.

RESPONDRespondIf you find signs of compromise
  1. 01Assume anything the agent could reach may have been touched

    Our suggestion: if you find a denied command ran, review the files and credentials within the agent's reach and rotate credentials where needed. The sources give no incident-response guidance.

HARDENHardenPrevent the next one
  1. 01Move to a tool that is still maintained

    The product was tagged unsupported when the CVE was assigned and the project is archived; we think a fixed release is unlikely.

  2. 02Don't treat allow and deny lists as your only defense

    Our suggestion: lists depend on the parser understanding shell syntax correctly and fail when it doesn't; pair them with least privilege and isolated environments.

Full remediation steps and notes

No source names a fixed version, fix commit or vendor advisory. The vendor’s releases page shows v3.54.0 as the last extension release and the repository is archived, so our analysis is that a fixed release is unlikely. Everything below is our analysis, not vendor guidance:

  1. Check your shell first. On the computer where Roo Code runs commands, open VS Code’s integrated terminal and run bash --version (this only shows the bash on your PATH. Roo Code’s documentation labels “Use Inline Terminal” as recommended; two places in the source code set its default differently, so we can’t confirm whether it is on by default. Per the documentation, with it on Roo Code runs commands through a background execa provider that bypasses shell profiles, and the documentation doesn’t say which shell it uses then; only with Inline Terminal off does it use VS Code’s integrated terminal default profile. Confirm separately which shell the agent actually uses; a zsh default profile doesn’t by itself mean the command won’t run); if it’s 5.3 or later, or the agent uses ksh93, and auto-approve is on, you’re in the scenario where the command actually runs.
  2. Turning off auto-approve is the most direct step. The bypass needs “always approve execute”; with it off, every command needs your approval. Switching to zsh or an older bash only stops the command from running; the parser flaw remains, so it isn’t a fix.
  3. Plan a migration. The product is unsupported; longer term, move to a tool that is still maintained.

Attack flow

Read left to right: this is the order the attack happens in. A blue shield means the step can be stopped; the earlier, the better. Click an icon for details.

Read top to bottom: this is the order the attack happens in. A blue shield means the step can be stopped; the earlier, the better. Tap an icon for details.

Roo Code auto-approve bypass: the ${ command; } form lets denied shell commands slip past the check: 1. Plants malicious instructions in content the agent will read → 2. The agent proposes an allowlisted command with a denied command hidden inside → 3. parseCommandLine() treats it as a harmless parameter expansion and never checks the inner command → 4. The command is auto-approved and the shell runs the hidden commandCVE-2026-110204 · Roo Code auto-approve bypass: the ${ command; } form lets denied shellcommands slip past the checkAttackerYour systemPlants malicious instructions in content the agent will read — This is called indirect prompt injection: the attacker doesn't touch your machine, they just put instructions into a file, web page, repository or MCP result the agent will read. 1Plants maliciousinstructions incontent the agentwill readThe agent proposes an allowlisted command with a denied command hidden inside — The outer command is something on the allowlist, such as echo, and the denied command is wrapped in the ${ ...; } form. 2The agent proposesan allowlistedcommand with adenied comman…parseCommandLine() treats it as a harmless parameter expansion and never checks the inner command — The parser swaps every ${...} for a placeholder with a single rule, so the command inside is never compared to the allow and deny lists. 3parseCommandLine()treats it as aharmless parameterexpansion an…The command is auto-approved and the shell runs the hidden command — Only bash 5.3+ or ksh93 run it, with the agent's auto-execute privileges. The researcher notes zsh and bash 5.2 or earlier do not run it, though the parser flaw is still there. 4The command isauto-approved andthe shell runs thehidden commandAttack pathCan be stopped herePlainCVE · plaincve.date/en/vulns/cve-2026-110204-roo-code-funsub-approval-bypass · CC BY 4.0
Roo Code auto-approve bypass: the ${ command; } form lets denied shell commands slip past the check: 1. Plants malicious instructions in content the agent will read → 2. The agent proposes an allowlisted command with a denied command hidden inside → 3. parseCommandLine() treats it as a harmless parameter expansion and never checks the inner command → 4. The command is auto-approved and the shell runs the hidden commandCVE-2026-110204 · Roo Code auto-approvebypass: the ${ command; } form letsdenied shell commands slip past the checkPlants malicious instructions in content the agent will read — This is called indirect prompt injection: the attacker doesn't touch your machine, they just put instructions into a file, web page, repository or MCP result the agent will read. 1AttackerPlants malicious instructionsin content the agent will readThe agent proposes an allowlisted command with a denied command hidden inside — The outer command is something on the allowlist, such as echo, and the denied command is wrapped in the ${ ...; } form. 2Your systemThe agent proposes anallowlisted command with adenied command hidden insideparseCommandLine() treats it as a harmless parameter expansion and never checks the inner command — The parser swaps every ${...} for a placeholder with a single rule, so the command inside is never compared to the allow and deny lists. 3Your systemparseCommandLine() treats it asa harmless parameter expansionand never checks the innercommandThe command is auto-approved and the shell runs the hidden command — Only bash 5.3+ or ksh93 run it, with the agent's auto-execute privileges. The researcher notes zsh and bash 5.2 or earlier do not run it, though the parser flaw is still there. 4Your systemThe command is auto-approvedand the shell runs the hiddencommandAttack pathCan be stopped herePlainCVE · CC BY 4.0plaincve.date/en/vulns/cve-2026-110204-roo-code-funsub-approval-bypass
Free to use in reporting and teaching under CC BY 4.0. Attribution is already on the image.
  1. Attacker

    Plants malicious instructions in content the agent will read

    This is called indirect prompt injection: the attacker doesn't touch your machine, they just put instructions into a file, web page, repository or MCP result the agent will read.

    Defense: Don't let an agent with auto-execute enabled work on untrusted content.

  2. Your system

    The agent proposes an allowlisted command with a denied command hidden inside

    The outer command is something on the allowlist, such as echo, and the denied command is wrapped in the ${ ...; } form.

  3. Your system

    parseCommandLine() treats it as a harmless parameter expansion and never checks the inner command

    The parser swaps every ${...} for a placeholder with a single rule, so the command inside is never compared to the allow and deny lists.

    Defense: Our analysis: turn off "always approve execute" so every command needs your approval.

  4. Your system

    The command is auto-approved and the shell runs the hidden command

    Only bash 5.3+ or ksh93 run it, with the agent's auto-execute privileges. The researcher notes zsh and bash 5.2 or earlier do not run it, though the parser flaw is still there.

    Defense: Run the agent in a least-privilege environment that limits the files and credentials it can reach.

Who is affected

ConditionAffected?
Roo Code through 3.54.0 + auto-approve on (called “always approve execute” in the researcher’s write-up) + shell is bash 5.3+ or ksh93 + an outer command such as echo on the allowlist that can wrap the denied command + the agent reads attacker-controlled content (indirect prompt injection)Affected; denied commands can run automatically without approval (per the CVE record)
Roo Code through 3.54.0 + auto-approve on + shell is zsh or bash 5.2 or earlierThe researcher says the command doesn’t run, but the parser flaw is still present
Roo Code through 3.54.0 + auto-approve offCommands ask you first; our analysis is they won’t run automatically
A fixed versionNo source mentions one

“The researcher’s write-up” on this page is the vulnerability write-up the finders, Minqiang Gui and Siyu Lou, published on GitHub (listed as the Researcher Disclosure in the CVE record); that page contains exploit code, so we don’t link to it. The researcher tested main-branch commit b867ec9 and labels it v3.53.0; however, per the repository history, b867ec9 is not the v3.53.0 release commit but a May 15, 2026 commit that comes two commits after the v3.54.0 release commit (f49f0ce). VulnCheck, which assigned the CVE, tagged it unsupported-when-assigned, meaning the product was no longer supported when the CVE ID was assigned. The vendor’s GitHub repository is archived (read-only), and sources disagree on the date: the repository banner says May 15, 2026, while the researcher’s write-up quotes May 16. A third-party news tracker also reports that the whole Roo Code suite (Extension, Cloud and Router) shut down on May 15, 2026.

How it works

Roo Code is an AI coding assistant (an “agent”) that can run shell commands in your terminal. With auto-approve on (the researcher’s write-up calls the setting “always approve execute”, and this page uses that name; the CVE record only says auto-approve), it stops asking you and instead checks each command against an allowlist and a denylist to decide on its own.

To do that check, it first has to split the command line apart and find every command that will actually run. That’s the job of parseCommandLine(). The problem is how it handles ${...}:

  • In older shells, forms like ${NAME} are “parameter expansions”: they just read a variable’s value and run nothing.
  • bash 5.3 (2025) added a ${ command; } form (called funsub command substitution), which does run the command inside.

Roo Code’s parser uses one regular expression to treat every ${...} as a parameter expansion and hide it behind a placeholder, so the command inside is never compared to the lists. All that’s left is an outer command on the allowlist, such as echo, which gets auto-approved. The parser and the shell read the same text differently, which is what CWE-436 (Interpretation Conflict) describes.

The realistic trigger usually isn’t the user but indirect prompt injection: a file, web page, repository or MCP result the agent reads contains instructions that steer it into proposing such a command. The command runs with the agent’s auto-execute privileges.

The flawed approach (conceptual illustration, not the original source code):

Show code example(ts)
// Treat every ${...} as "just a variable" and hide it behind a placeholder
cmd = cmd.replace(/\$\{[^}]+\}/g, () => PLACEHOLDER)
// Then only the outer command is checked → it's on the allowlist → auto-approved

The approach the researcher recommends (per the researcher’s write-up, which contains exploit code, so we don’t link to it; conceptual illustration, not a vendor fix):

Show code example(ts)
// The ${ ...; } funsub form is not a parameter expansion:
// pull out the inner command and check it against the lists like any other substitution
if (isFunsub(segment)) {
  checkAgainstLists(innerCommand(segment))
}

Timeline

DateEvent
2025 (per the researcher’s write-up)bash 5.3 adds the ${ command; } form; the bash release notes confirm the new syntax
2026-05-15A third-party news tracker reports the Roo Code suite shut down
2026-05-15 or 05-16Repository archived (the banner says the 15th; the researcher’s write-up quotes the 16th)
2026-10-13CVE published; NVD entry published; GitHub advisory GHSA-mfc9-vhw7-f5w9 published (not reviewed by GitHub)
2026-10-14Not listed in CISA KEV as of this date
2026-10-15NVD finished its analysis (status “Analyzed”) but gave no score of its own; it only lists the scores from VulnCheck, the assigner

Further reading

  • Scoring: NVD finished its analysis on 2026-10-15 but gave no score of its own; it only lists the scores from VulnCheck, the assigner (CVSS 4.0 7.7, CVSS 3.1 8.8). The CVE record lists CVSS 3.1 8.8 (supplied by VulnCheck, the assigner) and CVSS 4.0 7.7; this page uses the 4.0 score. Both say the attacker needs no privileges; 3.1 says user interaction is required, while 4.0 rates it as passive.
  • Exploitation: CISA’s SSVC rating marks it poc, meaning a public proof of concept exists. That does not mean it has been exploited in the wild. No source reports in-the-wild or zero-day exploitation.
  • Credited to Minqiang Gui and Siyu Lou. Their write-up contains exploit code, so we don’t link to it; see the CVE record, NVD and the VulnCheck advisory for the vulnerability details.
  • Related: CVE-2026-63108 is a separate Roo Code (≤3.54.0) auto-approve bypass that also involves how the parser handles parameter expansions, but it is a different CVE.
  • Related weakness type: CWE-436.

Verification Checked item by item against sources by AI under our review rules, all passed; not human-reviewed and not yet reproduced in our lab

AI review2026-10-18 · review rules

Verification records describe the environment and the result only, never reproduction steps or code that could attack other people’s systems. See our policy.

Sources

  1. CVE / NVD / OSVCVE-2026-110204 Record (CVE API) · CVE Program / VulnCheck (CNA), 2026-10-13 · accessed 2026-10-14
  2. CVE / NVD / OSVNVD - CVE-2026-110204 · NIST, 2026-10-13 · accessed 2026-10-14
  3. AdvisoryRoo Code through 3.54.0 Auto-Approve Bypass via Funsub Command Substitution · VulnCheck · accessed 2026-10-14
  4. AdvisoryGitHub Advisory Database: GHSA-mfc9-vhw7-f5w9 · GitHub, 2026-10-13 · accessed 2026-10-14
  5. VendorRoo-Code v3.54.0 src/shared/parse-command.ts · RooCodeInc (GitHub) · accessed 2026-10-14
  6. VendorRoo-Code releases · RooCodeInc (GitHub) · accessed 2026-10-14
  7. VendorRoo Code docs - Shell Integration (Use Inline Terminal) · RooCodeInc · accessed 2026-10-14
  8. VendorGitHub compare: Roo-Code v3.54.0...b867ec9 · GitHub · accessed 2026-10-14
  9. OtherBash NEWS (bash 5.3 changes) · Chet Ramey / Case Western Reserve University · accessed 2026-10-14
  10. NewsRoomote / Roo Code sunset · Distill Intelligence · accessed 2026-10-14
  11. AdvisoryRoo Code command injection via parameter expansion parsing (CVE-2026-63108) · VulnCheck · accessed 2026-10-14

Press brief

In one sentence

Roo Code is an AI coding assistant that can run shell commands for developers automatically. The parser it uses to decide whether a command is allowed mistakes the ${ command; } form added in bash 5.3 for harmless content, so, when the "always approve execute" setting is on and the shell is bash 5.3+ or ksh93, denied commands that a prompt-injected agent proposes can run without the user's approval. The CVE went public on October 13, 2026, and affects versions through 3.54.0; the project was archived in May 2026 and no fix is known. As of October 14 it is not on CISA's Known Exploited Vulnerabilities catalog.

Key facts

Severity
CVSS 4.0 7.7; CVSS 3.1 8.8 (VulnCheck) cveawg.mitre.org
Affected versions
Through 3.54.0 cveawg.mitre.org
Disclosed
2026-10-13 cveawg.mitre.org
GitHub advisory ID
GHSA-mfc9-vhw7-f5w9 (not reviewed by GitHub) api.github.com
Credited to
Minqiang Gui, Siyu Lou vulncheck.com

Confirmed

  • In Roo Code through 3.54.0, parseCommandLine() treats ${ command; } as a parameter expansion, so the command inside is never checked.
  • With 'always approve execute' on, denied commands hidden inside an allowlisted command can run without user approval on bash 5.3+ or ksh93.
  • CISA's SSVC rating marks a public proof of concept (poc); as of 2026-10-14 it is not in KEV.

Unconfirmed / disputed

  • The archive date differs: the repository banner says 2026-05-15, while the researcher's write-up quotes 2026-05-16.
  • No source names a fixed version, fix commit or vendor advisory.
  • No source reports exploitation in the wild, or exploitation as a zero-day.

Quotable line

A denylist only blocks the commands it can read; the shell learned a new trick, and the gatekeeper never did.

Images

Download the share image (PNG) · Attack flow diagram (downloadable)

Please credit "PlainCVE" and link to this page. Full citation format is under "How to cite" below. Found a factual error? Report it.

How to cite this page

This article is CC BY 4.0. Please keep the attribution and link when republishing.

PlainCVE Team (2026). "Roo Code auto-approve bypass: the ${ command; } form lets denied shell commands slip past the check". PlainCVE. https://plaincve.date/en/vulns/cve-2026-110204-roo-code-funsub-approval-bypass (accessed YYYY-MM-DD)
BibTeX
@misc{cve2026110204roocodefunsubapprovalbypass2026,
  title  = {Roo Code auto-approve bypass: the ${ command; } form lets denied shell commands slip past the check},
  author = {PlainCVE Team},
  year   = {2026},
  howpublished = {PlainCVE},
  url    = {https://plaincve.date/en/vulns/cve-2026-110204-roo-code-funsub-approval-bypass},
  note   = {Updated 2026-10-18}
}