examples: cache-residue-detector.sh (Cluster 8 — opt-out gap detection)#453
Conversation
…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>
There was a problem hiding this comment.
💡 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" |
There was a problem hiding this comment.
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 👍 / 👎.
…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.
… 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>
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.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.CC_CACHE_RESIDUE_DETECTOR_STRICT=1) flips to forward-looking: warn even when opt-outs aren't set.~/.claude.json(Linux/CLI) for three cache keys:cachedGrowthBookFeatures,cachedExperimentFeatures,cachedStatsigGates. Reports per-key entry counts.cachedGrowthBookFeaturesfile (~/Library/Application Support/Claude/) as informational on non-macOS.jq-based cleanup commands the operator can run safely.jqmissing → grep fallback flags presence without counts, advises installingjq.| 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:
Verified on the author's real
~/.claude.json: 276cachedGrowthBookFeaturesentries + 12cachedExperimentFeatures+ 2cachedStatsigGates. 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_brookfeature flag anthropics/claude-code#62061 (46+ reactions, central report of v2.1.150 server-side injection)~/.claude.jsonwith actual residue🤖 Generated with Claude Code