Skip to content

feat: AVE-2026-00089, Model-Supplied Sandbox Boundary - #336

Open
chaksaray wants to merge 1 commit into
developfrom
feat/ave-model-supplied-sandbox-boundary
Open

chaksaray wants to merge 1 commit into
developfrom
feat/ave-model-supplied-sandbox-boundary

Conversation

@chaksaray

Copy link
Copy Markdown
Contributor

Closes #335.

Adds AVE-2026-00089, Model-supplied sandbox boundary: a coding agent's sandbox computes its writable scope from a value the model supplies in a tool call (a terminal command's working directory) instead of from the session's own root. Content the model reads can therefore widen the sandbox to any location the process can write, such as the sandbox's own helper binary or the user's shell startup files. MEDIUM, AIVSS 6.6.

One commit, following the 00087 precedent (4f3173b): the record, both fixtures, CHANGELOG, README and the dist pair.

Sources read (all opened directly)

Source Date Credit as stated What it establishes
OpenAI GHSA-w5fx-fh39-j5rw (CVE-2025-59532) 2025-09-19 (NVD 2025-09-22) "Tzanko Matev (Codetracer)" "Codex CLI could treat a model-generated cwd as the sandbox's writable root, including paths outside of the folder where the user started their session." High, CVSS 4.0 8.6, CWE-20, affected 0.2.0 to 0.38.0, fixed 0.39.0 (IDE extension 0.4.12).
Codex fix commit 8595237 2025-09-18 Before: ExecParams.cwd fed both the spawn and get_writable_roots_with_cwd(cwd) in seatbelt.rs and landlock.rs. After: policy from sandbox_cwd: &turn_context.cwd, model value only as command_cwd. Test sandbox_distinguishes_command_and_policy_cwds().
Cursor GHSA-3p48-7v9f-v5cw (CVE-2026-50548) 2026-06-05 "Cato AI Labs" "the agent could modify the working_directory parameter, which could cause the sandbox to include writable paths outside the intended workspace." Critical, fixed in 3.0.
Cato AI Labs: DuneSlide 2026-07-01 Itay Ravia (author) "the sandbox constructs its security boundaries based on tool parameters ... that path is blindly added to the sandbox's allowed write list"; the PoC overwrites cursorsandbox.
Pillar: GitPwned 2026-07-20 Ariel Fogel Corroboration for CVE-2025-59532: "the CLI used a model-generated working directory to define its own security boundaries".

The vendor dispute, from Cato's timeline: reported February 19; rejected February 23 because "Cursor's threat model does not account for MCP server misuse"; reopened after escalation on February 26; fixed in Cursor 3.0 (April 2); CVEs assigned June 5.

Gate A: what is in the class and what is not

The class is the model supplying the value that defines or widens the policy boundary. Codex CVE-2025-59532 and Cursor CVE-2026-50548 are instances, each with a vendor advisory and a first-party source.

Kept out of the fingerprint and cited as related, because in both the boundary is fixed and a path check against it fails, which makes them path-validation failures rather than a boundary the model sets:

Distinctness (Gate C)

Compared field by field (fingerprint, provenance_vector, security_boundary where present) with 00053, 00054, 00052, 00011, 00068, 00048 and 00088 (PR #331), plus the token-overlap top five (00052, 00053, 00068, 00048, 00022).

  • 00053: a handler fails to contain a path against its fixed scope; that is an implementation bug, class E in the audit. Here the value is honored exactly and the policy layer derives the boundary from it.
  • 00054: a payload breaks the runtime's isolation. Here the isolation works as configured, and the model chose the configuration.
  • 00011: describes the injected tool-call directive, which is this class's delivery step.
  • 00088: the boundary stays intact and a later consumer abuses what was written inside it. Here the boundary moves.

Q6, including the doubt

Replace the LLM with a deterministic program and the flaw, in the form that matters, does not survive. A conventional program does not take its sandbox boundary from the output of the component the sandbox constrains; in Cato's words, "Traditionally, a remote attacker cannot control the working directory of a sandboxed operation."

The strongest counterargument is that this is an ordinary input-validation bug: the Advisory Database files it as CWE-20, and a deterministic sandbox that took its root from an untrusted request would share the flaw. My answer: the structural error can exist without a model, but the input becomes attacker-reachable only because a model generates it, so the party being constrained chooses the boundary. Both fixes separate model-supplied execution parameters from user-established policy, which supports the agentic framing.

Classified A, not E. Discussion #234 has no recorded decision, and its proposed test ("no model reasoning in the trigger") would not exclude this class.

Scoring

cvss_base 8.6 from the Codex advisory's own vector, CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N. That is the most conservative vendor reading: Cato scores 9.8 under CVSS 3.1, and Cursor rates its instance Critical.

AARF factor Value Rationale
autonomy 1 Once the model sets the parameter, the sandbox grants the scope and writes proceed with no approval in auto-run mode.
tool_use 1 The mechanism is a tool-call parameter.
non_determinism 0.5 Exploitation depends on the model following injected content.
self_modification 0.5 The demonstrated chain overwrites the agent's own sandbox helper, but the class itself is the widened scope.
dynamic_identity 0.5 The policy layer gives a model-supplied value the authority of the user-established session root, as 00088 and 00084 scored their trust-anchor confusion.
persistent_memory 0.5 The escape happens in-session, but its payloads persist (helper binary, ~/.zshrc, LaunchAgents).
data_access 1 Arbitrary writes as the user, then host execution.
external_dependencies 1 Severity depends entirely on whether a given harness derives its policy from the parameter.
multi_agent, natural_language_input 0 Single agent; the boundary step is a structured parameter value.

aars 6.0, thm 0.90, mitigation_factor 1: ((8.6 + 6.0) / 2) x 0.9 x 1 = 6.57, so 6.6 MEDIUM, confirmed by validate_records.py.

Framework mappings (each read from its primary source)

  • owasp_mcp MCP05 at commit 165fe0f: "Agent outputs are not constrained to allowlists of permitted commands, arguments, or file paths". MCP02 and MCP07 were read and rejected.
  • owasp_asi ASI05: names "sandbox escape". ASI02 was read and rejected by its own scope ("operates within its authorized privileges"; code execution is routed to ASI05).
  • mitre_atlas AML.T0105 (Escape to Host), live ATLAS.yaml v5.6.0. AML.T0053 was considered and left out as the generic delivery step.
  • nist_ai_rmf []: checked, no fit.

Verified

  • validate_records.py passes (88 valid), pytest 523 passed, and check_fixtures.py, check_framework_sources.py --strict --only, check_vulnerability_taxonomy.py --strict --only, the confidence ratchet (1 record changed, passes) and check_terms_sync.py all pass.
  • dist/ave-records-latest.json equals records/ for all 88 records.
  • All 11 URLs in the record return 200. The em-dash count in the diff is 0.
  • verification_basis was stamped by the script (artifact_reconstructed). The 8 unrelated canonical records it also stamps were reverted, as in feat: AVE-2026-00088, Sandbox Side-Effect Trust Handoff #331.

Could not verify

  • Cato's live page sits behind a bot challenge, so I read the Wayback Machine snapshot of 2026-10-06 of that same first-party URL. The URL returns 200, but automated link checks only see the challenge page.
  • I found no first-party write-up from Tzanko Matev. He is credited from the advisory alone, and researcher_url points at Cato's post as the lead credit's write-up.
  • The lead's CWE-275 is not in the Advisory Database record today, which lists only CWE-20.

Judgment calls for the maintainer

  1. Severity and thm. As in feat: AVE-2026-00088, Sandbox Side-Effect Trust Handoff #331, 0.90 follows CONTRIBUTING's scale ("PoC exists"). At thm 1 this record would be 7.3 HIGH.
  2. cvss_base 8.6 uses the Codex vector, including the vendor's PR:L, which is arguably generous to the defender for an indirect-injection attacker. With PR:N the score would rise.
  3. entry_class model_generated, reused as in 00056 and 00088 because the payload is a value the model produces.
  4. Keeping CVE-2026-50549 out of the fingerprint, even though it is in the same DuneSlide research and has the same impact. If you read it as "a model-chosen path decides what the sandbox allows", it could be argued in.
  5. Credit order. Cato is listed first as the lead with the first-party write-up, although Tzanko Matev's CVE is earlier.
  6. Merge order with feat: AVE-2026-00088, Sandbox Side-Effect Trust Handoff #331 and docs: correct AVE-2026-00044's README row and the Stats counts, and check the README against records/ #332. This branch, feat: AVE-2026-00088, Sandbox Side-Effect Trust Handoff #331 and docs: correct AVE-2026-00044's README row and the Stats counts, and check the README against records/ #332 each set the README Stats from develop's base. Whichever merges second needs a small rebase: the total goes to 89, MEDIUM to 66 once both records land, and docs: correct AVE-2026-00044's README row and the Stats counts, and check the README against records/ #332's 64 MEDIUM becomes 65 or 66. CHANGELOG entries also stack at the top of ### Added, and dist/ needs rebuilding after a rebase.

🤖 Generated with Claude Code

Signed-off-by: chaksaray <chaksaray@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant