v1.55.1.0 fix: telemetry consent accuracy + gstack-slug cache sanitization#1848
Merged
Conversation
The compute and fallback paths filter slug output to [a-zA-Z0-9._-], but a value read straight from ~/.gstack/slug-cache was echoed into eval output unsanitized. A locally-planted cache file could inject shell into eval "$(gstack-slug)". Re-sanitize on every path so the invariant the file header promises actually holds, and heal a poisoned cache on the next write. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The telemetry consent prompt promised "no repo names" while the preamble epilogue records the repo basename in the local skill-usage.jsonl. It is already stripped before any remote upload, so it never left the machine, but the copy was unqualified. Reword it to state repo name is local-only and stripped before upload. Also sanitize the basename to [a-zA-Z0-9._-] before it goes into the hand-built JSON, so a repo directory name containing quotes or newlines can neither break the JSON nor leak a fragment past the regex stripper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generated output of the preceding resolver change: the corrected consent copy and sanitized repo basename now appear in every skill preamble. Golden ship fixtures refreshed to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pins the contract that repo/branch identity in the synced skill-usage.jsonl is stripped before the remote POST. Three checks: a floor (the three known fields), coverage (every repo/branch field a producer writes into skill-usage.jsonl is stripped, so a future producer rename can't silently leak), and behavior (runs the actual sed strip expressions over a sample event). Scoped to the synced file, so the local-only timeline branch field is correctly excluded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Proves a poisoned ~/.gstack/slug-cache file cannot inject shell metacharacters into gstack-slug output (the value consumed by eval). Verified red when the cache-read sanitization is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
E2E Evals: ✅ PASS58/58 tests passed | $9.41 total cost | 12 parallel runners
12x ubicloud-standard-8 (Docker: pre-baked toolchain + deps) | wall clock ≈ slowest suite |
This was referenced Jun 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A small security + privacy correctness fix, surfaced by an external "responsible disclosure" review of the design-shotgun skill. Five of six flagged items were working-as-intended with guards the report missed; two led to real hardening here.
Security — slug helper
bin/gstack-slugnow sanitizes its output to[a-zA-Z0-9._-]on every path, including values read from its on-disk cache. The compute/fallback paths already filtered, but a cached value was echoed intoeval "$(gstack-slug)"unsanitized, so a tampered~/.gstack/slug-cachefile could inject shell. The filter now runs unconditionally before the value is emitted, and a poisoned cache is healed on the next write.Privacy — telemetry
Repo identity (
repo,_repo_slug,_branch) was already stripped before any remote upload; this PR keeps the behavior and locks it with a test.Test Coverage
Both new tests verified RED when their fix is removed. Tests: +2 files.
Pre-Landing Review
No issues found. Meaningful surface is ~12 lines of sanitization logic; reviewed inline (no SQL, no LLM trust boundary, no auth). Security-positive.
Design Review
No frontend files changed — design review skipped.
Eval Results
bun testsuite (skill validation + gen-skill-docs quality + golden regression + both new invariant tests) passes: exit 0, 0 failures.Adversarial Review
Claude + Codex, both: ship/land. Injection verified closed (newline payloads, self-heal, BRANCH path all checked); generated JSON well-formed; repo fields stripped before upload;
bash -nclean. One low non-exploitable finding (a metachar-only cache yields an empty SLUG for the session, handled downstream by${SLUG:-unknown}) — noted as a low-priority follow-up, not blocking.Scope Drift
Scope Check: CLEAN. Intent: fix the disclosed issues. Delivered: exactly that + tests + generated-doc regen.
Plan Completion
All code + test items DONE (gstack-slug sanitize, telemetry copy + basename sanitize, both invariant/regression tests). One non-code item deferred: sending the reply to the external reviewers (a communication, not a code deliverable).
Verification Results
Skipped — CLI/skill repo, no dev server to drive.
TODOS
No TODO items completed in this PR.
Test plan
bun testpasses (exit 0, 0 failures), run on merged state🤖 Generated with Claude Code