Skip to content

examples: cache-residue-detector.sh (Cluster 8 — opt-out gap detection)#453

Merged
yurukusa merged 2 commits into
mainfrom
feat/cluster-8-cache-residue-detector-2026-05-29
May 29, 2026
Merged

examples: cache-residue-detector.sh (Cluster 8 — opt-out gap detection)#453
yurukusa merged 2 commits into
mainfrom
feat/cluster-8-cache-residue-detector-2026-05-29

Conversation

@yurukusa
Copy link
Copy Markdown
Owner

Adds the second of three designed defense hooks for Cluster 8 (server-side prompt injection, v2.1.150+). Pairs with the existing server-side-prompt-injection-detector.sh (PR #383) by addressing the gap that opt-out alone does not perform: cached injection values written before the opt-out continue to register as peer-level system prompt sections until physical removal.

  • SessionStart hook, never blocks (exit 0 in all configurations, ADVISORY prefix only).
  • Default mode: only warns when at least one opt-out env var (CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_GROWTHBOOK) is set, because the primary purpose is closing the opt-out gap — not duplicating PR examples: server-side-prompt-injection-detector for v2.1.150+ (#62061) #383's role.
  • STRICT mode (CC_CACHE_RESIDUE_DETECTOR_STRICT=1) flips to forward-looking: warn even when opt-outs aren't set.
  • Inspects ~/.claude.json (Linux/CLI) for three cache keys: cachedGrowthBookFeatures, cachedExperimentFeatures, cachedStatsigGates. Reports per-key entry counts.
  • Detects macOS Desktop's cachedGrowthBookFeatures file (~/Library/Application Support/Claude/) as informational on non-macOS.
  • Emits idempotent jq-based cleanup commands the operator can run safely.
  • jq missing → grep fallback flags presence without counts, advises installing jq.
  • File missing / unreadable / malformed JSON → silent exit 0, no error leak.
  • Empty key objects/arrays → silent (no false detection of already-cleaned state).
    | Var | Effect |
    |---|---|
    | CC_CACHE_RESIDUE_DETECTOR_DISABLE=1 | disable entirely |
    | CC_CACHE_RESIDUE_DETECTOR_QUIET=1 | silence after acknowledgment |
    | CC_CACHE_RESIDUE_DETECTOR_STRICT=1 | forward-looking mode |
    | CC_CACHE_RESIDUE_CLAUDE_JSON | override default file location |
    28 cases, all pass. Coverage:
  • three cache-key detection paths (GrowthBook, Experiment, Statsig)
  • all four env var configurations
  • empty-key no-false-positive
  • missing/unreadable/malformed JSON fail-open
  • jq-fallback path
  • stdin consumption (SessionStart receives JSON)
  • ADVISORY-prefix non-blocking output
  • issue reference (#62061)
  • seven-way exit-code-zero invariant
    Verified on the author's real ~/.claude.json: 276 cachedGrowthBookFeatures entries + 12 cachedExperimentFeatures + 2 cachedStatsigGates. Advisory correctly named file, entry counts, cleanup command, and background reference.
    2 of 4 hooks shipped:
  • server-side-prompt-injection-detector.sh (PR examples: server-side-prompt-injection-detector for v2.1.150+ (#62061) #383)
  • cache-residue-detector.sh (this PR)
  • 🔜 proxy-capture-suggester.sh (operator-side HTTPS proxy capture path)
  • 🔜 system-prompt-baseline-checker.sh (diffs operator's baseline against runtime — requires proxy capture)
    Issue: [BUG] v2.1.150 adds server-side system prompt injection via tengu_heron_brook feature flag anthropics/claude-code#62061 (46+ reactions, central report of v2.1.150 server-side injection)
  • All 28 tests pass on Linux
  • Verified on real production ~/.claude.json with actual residue
  • Non-blocking (exit 0) in all 7 env configurations
  • Output goes to stderr, stdout is empty
  • Idempotent cleanup command is safe to re-run
    🤖 Generated with Claude Code

yurukusa added 2 commits May 29, 2026 16:31
…em' API 400 in v2.1.154+)

Adds a transparency-first candidate entry between the 15-cluster summary
and the detailed cluster sections. The candidate sits at the
cluster-promotion threshold with 3 filings and 7 reactions over 48
hours:
- #63366 (v2.1.154, Anthropic-compatible providers)
- #63469 (v2.1.156, 5 reactions, area:core, has-repro)
- #63473 (VS Code)
The candidate is logged publicly rather than held internally because the
threshold itself is useful information for operators currently hitting
the API Error 400. Operator-side workaround documented: pin to v2.1.153
or earlier until upstream fix lands.
Promotion criteria stated in the entry: a fourth independent filing or
cumulative reactions crossing 15. Tracking continues via
issue-tracking-poll.py registration in the next session.
Adds the second of three designed defense hooks for Cluster 8
(server-side prompt injection, v2.1.150+). Pairs with the existing
server-side-prompt-injection-detector.sh (PR #383, advises when
opt-out env vars are missing) by addressing the gap that opt-out
alone does not perform: cached injection values written before the
opt-out continue to register as peer-level system prompt sections
until cache eviction or physical removal.
Design:
- SessionStart hook, never blocks (exit 0 in all configurations).
- Default mode: only warns when at least one opt-out env var
  (CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_GROWTHBOOK)
  is set, because the primary purpose is closing the opt-out gap,
  not duplicating PR #383's role.
- STRICT mode (CC_CACHE_RESIDUE_DETECTOR_STRICT=1) flips it to
  forward-looking advisory: warn even when opt-outs are not set,
  for operators planning the opt-out and wanting an audit signal.
- Inspects ~/.claude.json (Linux/CLI) for three cache keys:
  cachedGrowthBookFeatures, cachedExperimentFeatures,
  cachedStatsigGates. Reports per-key entry counts.
- Detects macOS Desktop's cachedGrowthBookFeatures file
  (~/Library/Application Support/Claude/) as informational; the
  presence is reported without forcing failure on non-macOS.
- Emits idempotent jq-based cleanup commands the operator can run
  to remove the residue safely.
Failure modes:
- jq missing → grep fallback flags presence without counts, advises
  installing jq for exact cleanup.
- File missing / unreadable / malformed JSON → fail-open silent
  (no false positive, no error leak).
- Empty key objects/arrays → silent (no false detection of an
  already-cleaned state).
Configuration env vars:
- CC_CACHE_RESIDUE_DETECTOR_DISABLE=1 → disable entirely
- CC_CACHE_RESIDUE_DETECTOR_QUIET=1 → silence after acknowledgment
- CC_CACHE_RESIDUE_DETECTOR_STRICT=1 → forward-looking mode
- CC_CACHE_RESIDUE_CLAUDE_JSON → override default file location
Tests: 28 cases, all pass. Coverage includes the three cache-key
detection paths, all four env var configurations, empty-key
no-false-positive, missing/unreadable/malformed JSON fail-open
behavior, jq-fallback path, stdin consumption, ADVISORY-prefix
non-blocking output, issue reference (#62061), and the seven-way
exit-code-zero invariant.
Verified on the author's real ~/.claude.json (276
cachedGrowthBookFeatures entries + 12 cachedExperimentFeatures
+ 2 cachedStatsigGates). The advisory correctly named the file,
the entry counts, the cleanup command, and the background
reference.
Cluster 8 status after this PR: 2/4 hooks shipped
(server-side-prompt-injection-detector + cache-residue-detector).
Remaining in design: proxy-capture-suggester (operator-side HTTPS
proxy capture path), system-prompt-baseline-checker (diffs
operator's baseline against runtime — requires proxy capture).
Reference issue: anthropics/claude-code#62061
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yurukusa yurukusa merged commit 497fc0b into main May 29, 2026
2 checks passed
@yurukusa yurukusa deleted the feat/cluster-8-cache-residue-detector-2026-05-29 branch May 29, 2026 07:56
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5872f3a79e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


UNREADABLE_JSON="$TMPDIR_RUN/unreadable.json"
echo '{"cachedGrowthBookFeatures":{"x":1}}' > "$UNREADABLE_JSON"
chmod 000 "$UNREADABLE_JSON"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make unreadable-file fixture work under root

When this test script runs as root (common for Docker-based CI and the current repo container), chmod 000 does not make the fixture unreadable: root can still read it, so the hook reports the cached key and Test 13 fails instead of staying silent. Please make the fixture truly unreadable in root contexts (or skip/assert differently when EUID=0) so the new test suite is portable.

Useful? React with 👍 / 👎.

yurukusa added a commit that referenced this pull request May 29, 2026
…453) (#454)

Updates Cluster 8 status to reflect 2/4 defense paths shipped:
- Renames "Defense path shipped (1 of 4)" to "Defense paths shipped
  (2 of 4)" and adds the cache-residue-detector entry with full
  design articulation (default vs strict mode, three cache keys,
  failure modes, four env vars, 28 tests).
- Renames "Defense paths in design (3 of 4)" to "(2 of 4)" and
  removes cache-residue-detector from the design list.
- Updates the per-cluster summary line in the closing paragraph to
  reflect the shipped+designed split: "two shipped hooks
  (server-side-prompt-injection-detector for missing-opt-out
  detection, PR #383; cache-residue-detector for opt-out-gap
  detection, PR #453) with two audit hooks in design
  (proxy-capture-suggester, system-prompt-baseline-checker)".
The two shipped hooks form a complementary pair: PR #383 surfaces
when opt-out env vars are missing; PR #453 surfaces the residue
that opt-out alone does not delete. Together they close both sides
of the operator-side defensive surface that the runtime exposes
for this cluster.
yurukusa added a commit that referenced this pull request May 29, 2026
… shipped (PR #453) (#455)

The README had per-cluster line items for Clusters 6, 7, 9, 10, 12,
13, 14, 15 but no dedicated entry for Cluster 8 (v2.1.150 server-side
prompt injection). The cluster was only referenced indirectly in the
overall cluster-tracker description line. This PR closes that gap.
New line item articulates:
- The v2.1.150 mechanism (the `nAA` function reading client_data
  and tengu_heron_brook into peer system-prompt sections).
- The documented opt-out env vars and the audit-paths writeup.
- Both shipped defense hooks as a complementary pair:
  - PR #383 server-side-prompt-injection-detector — when opt-outs
    are missing.
  - PR #453 cache-residue-detector — when opt-outs are set but
    pre-opt-out cache values still register.
- The cache-residue hook's three cache keys, the macOS file
  detection path, the idempotent jq cleanup commands, and the
  default-vs-STRICT mode distinction.
- The two remaining audit hooks in design.
- The 2026-11 Safety Lab issue connection (preview material).
Position: between Cluster 9 and the preceding entry so Cluster 8
sits adjacent to the other server-side / classifier-side clusters
(Cluster 9 AUP false-positive, Cluster 10 GrowthBook A/B overrides)
which share the "server-controlled behavior the operator cannot see
or stop from the client" structural pattern.
CVR rationale: cc-safe-setup has 1,330 14-day independent users.
README is the discovery surface for the entry-level subset who arrive
via npm-install or GitHub search. A dedicated Cluster 8 line item
puts the v2.1.150 audit trail concern in front of operators who
might otherwise discover the cluster only after a security review
prompts the question.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant