<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CodeAnt AI</title>
    <description>The latest articles on DEV Community by CodeAnt AI (codeant).</description>
    <link>https://dev.to/codeant</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14435%2F778cf53b-5258-4ba0-abc5-d0dfad9d950d.png</url>
      <title>DEV Community: CodeAnt AI</title>
      <link>https://dev.to/codeant</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codeant"/>
    <language>en</language>
    <item>
      <title>Root Cause Analysis: Glob-Pattern Confusion in Claude Code's macOS Sandbox (CVSS 7.7)"</title>
      <dc:creator>CodeAnt AI</dc:creator>
      <pubDate>Wed, 19 Aug 2026 10:58:55 +0000</pubDate>
      <link>https://dev.to/codeant/root-cause-analysis-glob-pattern-confusion-in-claude-codes-macos-sandbox-cvss-77-3ael</link>
      <guid>https://dev.to/codeant/root-cause-analysis-glob-pattern-confusion-in-claude-codes-macos-sandbox-cvss-77-3ael</guid>
      <description>&lt;h2&gt;
  
  
  Executive summary
&lt;/h2&gt;

&lt;p&gt;We identified and disclosed a High-severity (&lt;a href="https://codeant.ai/blogs/claude-code-macos-sandbox-escape" rel="noopener noreferrer"&gt;fourth High-severity finding&lt;/a&gt; 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. &lt;/p&gt;

&lt;p&gt;A literal folder name containing glob metacharacters (&lt;code&gt;*&lt;/code&gt;) is silently reinterpreted as a wildcard pattern during policy generation. &lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;That primitive is sufficient to achieve pre-authentication, unsandboxed command execution via Claude Code's &lt;code&gt;SessionStart&lt;/code&gt; hook mechanism.&lt;/p&gt;

&lt;p&gt;This writeup covers the mechanism, our differential testing methodology, and mitigation guidance. This research is drawn from the two disciplines behind &lt;a href="https://codeant.ai/pentesting" rel="noopener noreferrer"&gt;the failures we find&lt;/a&gt;: reviewing code before it ships, and attacking systems after.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background: how the sandbox scopes writes
&lt;/h2&gt;

&lt;p&gt;Claude Code's macOS sandbox auto-approves writes inside the current project directory. &lt;/p&gt;

&lt;p&gt;To determine scope, the policy generator inspects the project's folder path for glob syntax — characters like &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt; that conventionally mean "match any of these" rather than "this literal string."&lt;/p&gt;

&lt;p&gt;The flaw: this check has no mechanism to distinguish a path that is &lt;em&gt;intentionally&lt;/em&gt; a glob pattern from a literal folder name that merely &lt;em&gt;contains&lt;/em&gt; glob metacharacters. &lt;/p&gt;

&lt;p&gt;There is no escaping, quoting, or type distinction applied before the path is compiled into a matching rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root cause: literal-to-pattern reinterpretation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw8jusv3jf8r7kkhvjhy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw8jusv3jf8r7kkhvjhy5.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Renaming a project folder to include two asterisks — for example, &lt;code&gt;review-bundle**.claude**&lt;/code&gt; — causes the policy generator to compile that string as a wildcard pattern rather than treat it as a single literal directory. &lt;/p&gt;

&lt;p&gt;Conceptually, the generated allow rule collapses from "this one directory" to a pattern resembling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;allow_write: /parent/review-bundle*/.claude*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That pattern now matches any sibling directory whose name starts with &lt;code&gt;review-bundle&lt;/code&gt;, not just the original folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  The asymmetry: allow rules widen, deny rules don't
&lt;/h2&gt;

&lt;p&gt;Claude Code separately generates a deny rule to protect &lt;code&gt;.claude/settings.local.json&lt;/code&gt; — the local configuration file capable of defining auto-run hooks. &lt;/p&gt;

&lt;p&gt;Critically, this deny rule was implemented to expect &lt;strong&gt;two&lt;/strong&gt; &lt;code&gt;.claude&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Differential test results
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The control case (&lt;code&gt;review-bundle**&lt;/code&gt;, no &lt;code&gt;.claude&lt;/code&gt; substring) confirms the flaw is specific to the &lt;code&gt;.claude&lt;/code&gt; token appearing inside the reinterpreted pattern — ruling out a broader, unrelated permissions bug and isolating the exact mechanism. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft14rwgegn4htbqc7dfmv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft14rwgegn4htbqc7dfmv.png" alt=" " width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This kind of differential comparison is the same &lt;a href="https://www.codeant.ai/blogs/ai-penetration-testing-methodology" rel="noopener noreferrer"&gt;full methodology, phase by phase&lt;/a&gt; we apply across engagements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploitation chain: from write primitive to pre-auth execution
&lt;/h2&gt;

&lt;p&gt;With a write primitive into a sibling project's &lt;code&gt;.claude/settings.local.json&lt;/code&gt; established, the remaining step used Claude Code's &lt;code&gt;SessionStart&lt;/code&gt; hook — automation designed to run a command the moment a new session opens. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frrdpgpwhdswar0gk9dhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frrdpgpwhdswar0gk9dhf.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This isn't a hypothetical chaining exercise; it reflects the &lt;a href="https://www.codeant.ai/blogs/ai-penetration-testing-guide" rel="noopener noreferrer"&gt;defensive side of the same platform&lt;/a&gt; discipline applied to every codebase tested.&lt;/p&gt;

&lt;p&gt;Steps to reproduce (validated):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a project folder with a name containing &lt;code&gt;.claude&lt;/code&gt; inside a reinterpretable glob pattern (e.g., &lt;code&gt;review-bundle**.claude**&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From inside that sandboxed session, write a &lt;code&gt;SessionStart&lt;/code&gt; hook into a sibling project's &lt;code&gt;.claude/settings.local.json&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Close the session. Open the sibling project as a fresh session, with Bash access disabled and no API key configured.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observe: the hook executes before authentication, before the model produces any output, and before the Bash tool is available to the session.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Severity assessment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Severity:&lt;/strong&gt; CVSS 4.0, 7.7 (High)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Affected versions confirmed:&lt;/strong&gt; Claude Code 2.1.214, 2.1.215 (macOS arm64)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test cases:&lt;/strong&gt; 4 differential cases, identical payload and target&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full bypass rate:&lt;/strong&gt; 2 of 4 cases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prerequisites:&lt;/strong&gt; none — no symlinks, race conditions, or leaked credentials required&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disclosure timeline
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Date        Event
July 18     Report submitted
July 20     Validated by Anthropic (2 days)
August 4    Bounty awarded (17 days from report)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Broader pattern: type confusion via string inference
&lt;/h2&gt;

&lt;p&gt;This finding fits a pattern we've documented before, one level down the stack from where it usually surfaces. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/pulse/why-ai-code-review-misses-bug-breaks-production-codeant-ai-thw0c/" rel="noopener noreferrer"&gt;Edition 3&lt;/a&gt; covered AI code reviewers inferring correctness from surface-level textual similarity rather than resolving what code actually calls or connects to. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.codeant.ai/blogs/rag-fails-autonomous-dev-agents" rel="noopener noreferrer"&gt;We've written before about why that pattern keeps breaking down.&lt;/a&gt; Here, a security policy compiler inferred a path's &lt;em&gt;type&lt;/em&gt; (literal vs. pattern) from its &lt;em&gt;characters&lt;/em&gt;, rather than preserving the path's actual provenance as a resolved filesystem object. &lt;/p&gt;

&lt;p&gt;Note also that &lt;a href="https://www.codeant.ai/blogs/ai-pentesting-compliance" rel="noopener noreferrer"&gt;certain compliance frameworks ask for exactly that&lt;/a&gt; kind of external assessment as a baseline — this finding is a supplement to, not a replacement for, that layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mitigation recommendations
&lt;/h2&gt;

&lt;p&gt;For teams running Claude Code or comparable AI coding agents on machines adjacent to production code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Audit whether your sandbox/policy layer resolves paths as validated, canonical filesystem objects, or infers type from raw string content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Treat any character-based heuristic for distinguishing "pattern" from "literal" as a parser bug waiting to be found, not a config edge case.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is our fourth validated High-severity vulnerability in Claude Code this year. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://codeant.ai/pentesting" rel="noopener noreferrer"&gt;Starting from what's already known&lt;/a&gt;, 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.&lt;/p&gt;

&lt;p&gt;*Research conducted by CodeAnt AI. &lt;a href="https://www.linkedin.com/pulse/folder-name-broke-out-its-own-sandbox-codeant-ai-gs9tf" rel="noopener noreferrer"&gt;Originally published as Edition 04 of "The Last Line."*&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>devsecops</category>
      <category>penetrationtesting</category>
    </item>
  </channel>
</rss>
