Skip to content

v3.5.2 — security hotfix #108

Choose a tag to compare

@vsits-proxy-builder vsits-proxy-builder released this 07 May 22:05
· 99 commits to main since this release
613e4df

Security hotfix

This release fixes a local code execution vulnerability in tools/quota-statusline.sh reported in #108.

Affected versions: v3.5.0 and v3.5.1.
Affected configurations: users who wired tools/quota-statusline.sh into their CC statusLine (a setup the README explicitly recommends in v3.5.0+).
Severity: local code execution at user privilege, persistent re-fire on every CC statusline redraw, no user interaction beyond cd-ing into a hostile path on disk.

What was wrong

tools/quota-statusline.sh interpolated CC's hook stdin payload directly into a Python triple-quoted string literal:

input=$(cat)
result=$(python3 -c "
    stdin_data = json.loads('''$input''') if '''$input''' else {}
")

A ''' byte sequence anywhere in the payload closes the literal early and lets following bytes execute as Python in the user's CC process. CC's hook payload reflects user-controlled paths (cwd, workspace.current_dir, workspace.project_dir, transcript_path), and apostrophes are legal in filesystem paths. The realistic chain:

  1. Hostile directory name with '''+payload+''' lands on disk (git clone, archive extract, npm package, etc.)
  2. Victim has the recommended statusline wired up
  3. Victim cds into a path matching the hostile name
  4. CC fires the statusline hook on every redraw → arbitrary Python runs as the user

Fix

Capture stdin in bash, export CC_INPUT, and feed the Python source through a single-quoted heredoc (<<'PYEOF'). Single-quoting disables ALL bash interpolation inside the body. Python now reads the JSON via os.environ.get('CC_INPUT'), where the bytes are inert at every layer.

Two regression tests (T6, T7) drive the exact '''+__import__('os').system(...)+''' payload through the production script under a tmpdir-rooted HOME and assert the sentinel file is never created.

Upgrade

npm install -g claude-code-cache-fix@3.5.2

If you've copied quota-statusline.sh into ~/.claude/hooks/ (per the README setup instructions), re-copy it from the upgraded package:

cp "$(npm root -g)/claude-code-cache-fix/tools/quota-statusline.sh" ~/.claude/hooks/

If you wrote your own statusline based on the v3.5.0/v3.5.1 example, audit it for the json.loads('''$input''') pattern and replace with the heredoc + env var pattern. The fixed script in tools/quota-statusline.sh is the reference.

Credit

Reported responsibly by @schuay (Jakob Linke). Thank you.

Links