GHSA-G3XQ-3GMV-QQ8G

Vulnerability from github – Published: 2026-05-13 15:31 – Updated: 2026-06-08 23:54
VLAI
Summary
claude-code-cache-fix vulnerable to local code execution via Python triple-quote injection in tools/quota-statusline.sh
Details

Summary

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.

  1. A hostile directory name containing '''+payload+''' lands on disk via any normal vector — git clone, archive extraction, npm package, downloaded zip, etc.
  2. The victim has the recommended tools/quota-statusline.sh wired into their CC statusLine config.
  3. The victim cds anywhere a hostile path is reachable.
  4. 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 statusLine entry from ~/.claude/settings.json, or
  • Replace tools/quota-statusline.sh with a script that does NOT pass stdin through python3 -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
Show details on source website

{
  "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"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

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.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…