GHSA-G3XQ-3GMV-QQ8G
Vulnerability from github – Published: 2026-05-13 15:31 – Updated: 2026-06-08 23:54Summary
tools/quota-statusline.sh (introduced in v3.5.0) interpolates Claude Code's hook stdin payload directly into a Python triple-quoted string literal. A ''' byte sequence in any user-controlled field of the payload closes the literal early and lets following bytes execute as Python in the user's Claude Code process.
Affected versions
- v3.5.0
- v3.5.1
Patched versions
- v3.5.2
Affected configurations
Users who wired tools/quota-statusline.sh into Claude Code's statusLine configuration. The v3.5.0 README explicitly recommends this setup, so most users on v3.5.0/v3.5.1 with the recommended setup are affected.
Attack chain
Claude Code's statusline hook payload reflects user-controlled paths (cwd, workspace.current_dir, workspace.project_dir, transcript_path). Apostrophes are legal in POSIX filesystem paths.
- A hostile directory name containing
'''+payload+'''lands on disk via any normal vector —git clone, archive extraction, npm package, downloaded zip, etc. - The victim has the recommended
tools/quota-statusline.shwired into their CCstatusLineconfig. - The victim
cds anywhere a hostile path is reachable. - CC fires the statusline hook on every redraw. The Python literal closes early. The injected bytes execute as Python in the user's process.
Severity
Local code execution at user privilege. Persistent re-fire on every statusline redraw. No user interaction beyond cd-ing into the hostile path. The user's shell, CC session, files, SSH keys, and any locally-accessible credentials are reachable from the executed code.
Vulnerable pattern
input=$(cat)
result=$(python3 -c "
stdin_data = json.loads('''$input''') if '''$input''' else {}
")
Fix
Capture stdin in bash, export to env, and pipe the Python source through a single-quoted heredoc (<<'PYEOF'). Single-quoting disables ALL bash interpolation inside the body. Python reads the JSON via os.environ.get('CC_INPUT'), where the bytes are inert at every layer.
CC_INPUT=$(cat)
export CC_INPUT
python3 <<'PYEOF' 2>/dev/null
import os, json
try:
cc_input = json.loads(os.environ.get('CC_INPUT') or '{}')
except Exception:
cc_input = {}
# ...
PYEOF
Workarounds
Until upgrading to v3.5.2:
- Disable the statusline by removing the
statusLineentry from~/.claude/settings.json, or - Replace
tools/quota-statusline.shwith a script that does NOT pass stdin throughpython3 -c "..."(a heredoc + env var rewrite is safe)
Credit
Reported by Jakob Linke (@schuay) via GitHub issue #108.
Timeline
- 2026-05-07 — reported (#108)
- 2026-05-07 — confirmed, fix implemented (#110)
- 2026-05-07 — v3.5.2 published
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "claude-code-cache-fix"
},
"ranges": [
{
"events": [
{
"introduced": "3.5.0"
},
{
"fixed": "3.5.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45136"
],
"database_specific": {
"cwe_ids": [
"CWE-78",
"CWE-94"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-13T15:31:41Z",
"nvd_published_at": "2026-05-27T21:16:18Z",
"severity": "HIGH"
},
"details": "## Summary\n\n`tools/quota-statusline.sh` (introduced in v3.5.0) interpolates Claude Code\u0027s hook stdin payload directly into a Python triple-quoted string literal. A `\u0027\u0027\u0027` byte sequence in any user-controlled field of the payload closes the literal early and lets following bytes execute as Python in the user\u0027s Claude Code process.\n\n## Affected versions\n\n- v3.5.0\n- v3.5.1\n\n## Patched versions\n\n- v3.5.2\n\n## Affected configurations\n\nUsers who wired `tools/quota-statusline.sh` into Claude Code\u0027s `statusLine` configuration. The v3.5.0 README explicitly recommends this setup, so most users on v3.5.0/v3.5.1 with the recommended setup are affected.\n\n## Attack chain\n\nClaude Code\u0027s statusline hook payload reflects user-controlled paths (`cwd`, `workspace.current_dir`, `workspace.project_dir`, `transcript_path`). Apostrophes are legal in POSIX filesystem paths.\n\n1. A hostile directory name containing `\u0027\u0027\u0027+payload+\u0027\u0027\u0027` lands on disk via any normal vector \u2014 `git clone`, archive extraction, npm package, downloaded zip, etc.\n2. The victim has the recommended `tools/quota-statusline.sh` wired into their CC `statusLine` config.\n3. The victim `cd`s anywhere a hostile path is reachable.\n4. CC fires the statusline hook on every redraw. The Python literal closes early. The injected bytes execute as Python in the user\u0027s process.\n\n## Severity\n\nLocal code execution at user privilege. Persistent re-fire on every statusline redraw. No user interaction beyond `cd`-ing into the hostile path. The user\u0027s shell, CC session, files, SSH keys, and any locally-accessible credentials are reachable from the executed code.\n\n## Vulnerable pattern\n\n```sh\ninput=$(cat)\nresult=$(python3 -c \"\n stdin_data = json.loads(\u0027\u0027\u0027$input\u0027\u0027\u0027) if \u0027\u0027\u0027$input\u0027\u0027\u0027 else {}\n\")\n```\n\n## Fix\n\nCapture stdin in bash, export to env, and pipe the Python source through a single-quoted heredoc (`\u003c\u003c\u0027PYEOF\u0027`). Single-quoting disables ALL bash interpolation inside the body. Python reads the JSON via `os.environ.get(\u0027CC_INPUT\u0027)`, where the bytes are inert at every layer.\n\n```sh\nCC_INPUT=$(cat)\nexport CC_INPUT\n\npython3 \u003c\u003c\u0027PYEOF\u0027 2\u003e/dev/null\nimport os, json\ntry:\n cc_input = json.loads(os.environ.get(\u0027CC_INPUT\u0027) or \u0027{}\u0027)\nexcept Exception:\n cc_input = {}\n# ...\nPYEOF\n```\n\n## Workarounds\n\nUntil upgrading to v3.5.2:\n\n- Disable the statusline by removing the `statusLine` entry from `~/.claude/settings.json`, or\n- Replace `tools/quota-statusline.sh` with a script that does NOT pass stdin through `python3 -c \"...\"` (a heredoc + env var rewrite is safe)\n\n## Credit\n\nReported by Jakob Linke (@schuay) via GitHub issue [#108](https://github.com/cnighswonger/claude-code-cache-fix/issues/108).\n\n## Timeline\n\n- 2026-05-07 \u2014 reported (#108)\n- 2026-05-07 \u2014 confirmed, fix implemented (#110)\n- 2026-05-07 \u2014 v3.5.2 published",
"id": "GHSA-g3xq-3gmv-qq8g",
"modified": "2026-06-08T23:54:32Z",
"published": "2026-05-13T15:31:41Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/cnighswonger/claude-code-cache-fix/security/advisories/GHSA-g3xq-3gmv-qq8g"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45136"
},
{
"type": "WEB",
"url": "https://github.com/cnighswonger/claude-code-cache-fix/issues/108"
},
{
"type": "WEB",
"url": "https://github.com/cnighswonger/claude-code-cache-fix/pull/110"
},
{
"type": "WEB",
"url": "https://github.com/cnighswonger/claude-code-cache-fix/commit/613e4df30547f3e6baf32d161eddc828f171da17"
},
{
"type": "PACKAGE",
"url": "https://github.com/cnighswonger/claude-code-cache-fix"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "claude-code-cache-fix vulnerable to local code execution via Python triple-quote injection in tools/quota-statusline.sh"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.