Executive summary
We identified and disclosed a High-severity (fourth High-severity finding in Claude Code this year) sandbox escape, CVSS 4.0 score 7.7, caused by a path-parsing ambiguity in how Claude Code's macOS sandbox scopes filesystem writes.
A literal folder name containing glob metacharacters (*) is silently reinterpreted as a wildcard pattern during policy generation.
This reinterpretation broadens an allow rule to cover sibling directories without applying the same broadening to the corresponding deny rule, producing a write primitive into a protected configuration file outside the intended project boundary.
That primitive is sufficient to achieve pre-authentication, unsandboxed command execution via Claude Code's SessionStart hook mechanism.
This writeup covers the mechanism, our differential testing methodology, and mitigation guidance. This research is drawn from the two disciplines behind the failures we find: reviewing code before it ships, and attacking systems after.
Background: how the sandbox scopes writes
Claude Code's macOS sandbox auto-approves writes inside the current project directory.
To determine scope, the policy generator inspects the project's folder path for glob syntax — characters like * and ? that conventionally mean "match any of these" rather than "this literal string."
The flaw: this check has no mechanism to distinguish a path that is intentionally a glob pattern from a literal folder name that merely contains glob metacharacters.
There is no escaping, quoting, or type distinction applied before the path is compiled into a matching rule.
Root cause: literal-to-pattern reinterpretation
Renaming a project folder to include two asterisks — for example, review-bundle**.claude** — causes the policy generator to compile that string as a wildcard pattern rather than treat it as a single literal directory.
Conceptually, the generated allow rule collapses from "this one directory" to a pattern resembling:
allow_write: /parent/review-bundle*/.claude*
That pattern now matches any sibling directory whose name starts with review-bundle, not just the original folder.
The asymmetry: allow rules widen, deny rules don't
Claude Code separately generates a deny rule to protect .claude/settings.local.json — the local configuration file capable of defining auto-run hooks.
Critically, this deny rule was implemented to expect two .claude path segments before it triggers. When the allow rule was reinterpreted as a broader pattern, the deny rule's stricter literal-matching logic did not widen in the same way — leaving a class of sibling paths that were allow-matched but deny-missed.
Differential test results
Folder name Allow rule Deny rule Outcome
review-bundle No match N/A Blocked
review-bundle** Match Match Blocked
review-bundle**.claude** Match MISS Settings file created, hook executes
**.claude** Match MISS Settings file created, hook executes
The control case (review-bundle**, no .claude substring) confirms the flaw is specific to the .claude token appearing inside the reinterpreted pattern — ruling out a broader, unrelated permissions bug and isolating the exact mechanism.
This kind of differential comparison is the same full methodology, phase by phase we apply across engagements.
Exploitation chain: from write primitive to pre-auth execution
With a write primitive into a sibling project's .claude/settings.local.json established, the remaining step used Claude Code's SessionStart hook — automation designed to run a command the moment a new session opens.
This isn't a hypothetical chaining exercise; it reflects the defensive side of the same platform discipline applied to every codebase tested.
Steps to reproduce (validated):
Create a project folder with a name containing
.claudeinside a reinterpretable glob pattern (e.g.,review-bundle**.claude**).From inside that sandboxed session, write a
SessionStarthook into a sibling project's.claude/settings.local.json.Close the session. Open the sibling project as a fresh session, with Bash access disabled and no API key configured.
Observe: the hook executes before authentication, before the model produces any output, and before the Bash tool is available to the session.
Severity assessment
- Severity: CVSS 4.0, 7.7 (High)
- Affected versions confirmed: Claude Code 2.1.214, 2.1.215 (macOS arm64)
- Test cases: 4 differential cases, identical payload and target
- Full bypass rate: 2 of 4 cases
- Prerequisites: none — no symlinks, race conditions, or leaked credentials required
Disclosure timeline
Date Event
July 18 Report submitted
July 20 Validated by Anthropic (2 days)
August 4 Bounty awarded (17 days from report)
Broader pattern: type confusion via string inference
This finding fits a pattern we've documented before, one level down the stack from where it usually surfaces.
Edition 3 covered AI code reviewers inferring correctness from surface-level textual similarity rather than resolving what code actually calls or connects to.
We've written before about why that pattern keeps breaking down. Here, a security policy compiler inferred a path's type (literal vs. pattern) from its characters, rather than preserving the path's actual provenance as a resolved filesystem object.
Note also that certain compliance frameworks ask for exactly that kind of external assessment as a baseline — this finding is a supplement to, not a replacement for, that layer.
Mitigation recommendations
For teams running Claude Code or comparable AI coding agents on machines adjacent to production code:
Audit whether your sandbox/policy layer resolves paths as validated, canonical filesystem objects, or infers type from raw string content.
Verify that allow and deny rule generation use identical path-normalization logic — any asymmetry between the two is the exploitable surface, independent of the specific trigger.
Treat any character-based heuristic for distinguishing "pattern" from "literal" as a parser bug waiting to be found, not a config edge case.
Conclusion
This is our fourth validated High-severity vulnerability in Claude Code this year.
Starting from what's already known, rather than a blank test surface, is what let this be found and fully characterized in a single research session rather than an extended engagement.
*Research conducted by CodeAnt AI. Originally published as Edition 04 of "The Last Line."*



Top comments (0)