Keep internal tracking ids out of the published package - #151
Conversation
…0.18.1) Three strings a user actually reads ended in an internal tracking id — the `doctor` hook warning, a `sweep` line about unattributable transcripts, and the header of the Cursor wrapper script the installer writes into the home directory. They carry no meaning outside the team, so they are gone and the sentences say the same thing without them. The shipped plugin hook manifest and the comments esbuild inlines into the committed bundle are scrubbed the same way. Add scripts/check-no-internal-refs.mjs: it resolves the exact file set npm pack ships (the `files` list plus package.json) and fails on an internal id, a tracker URL, a private repository name or a company email domain. Because it runs after the bundle rebuild it sees the same bytes the tarball will carry, so a comment that reaches dist-bundle is caught in CI rather than by a reader on npm. It also takes `--dir` so the same check can be run against an extracted tarball. Wired into CI and into the release job — a publish cannot be taken back.
|
REVIEWER: [high] The check misses a surface we actually distribute. Fixed: the scan now also covers |
|
REVIEWER: [low] The extension test used the whole path, not the filename: REVIEWER: [low] |
The npm tarball is not the only thing a stranger receives. The Claude Code plugin marketplace manifest and the Gemini / Codex extension directories are installed from git, so a scan scoped to the package's `files` list declares victory while a leak sits in a file a Codex user reads on install — and one did: extensions/codex/README.md carried three tracking ids, one of them in a heading. Widen the scan to .claude-plugin/marketplace.json and extensions/, and rewrite those lines. `--dir` stays package-only: an extracted tarball contains nothing else. Also take the extension off the basename rather than the whole path, so a dot in a directory name can't decide whether a file is scanned.
CI has failed at the vulnerability gate on every push to main since 2026-07-24 (dev-only advisories behind pinned versions), and every later step is skipped — so the new guard would have been merged in a state where it could never fire on a pull request. It is a plain node script with no dependencies, so it now runs first. It reads the committed bundle; the bundle-sync step still ties those bytes to a fresh build, and the release job keeps its copy after the rebuild.
|
REVIEWER: [high] The guard I added never ran. CI on this repo has failed at the vulnerability gate on every push to Moved it to the first step, before Verified on the pushed run rather than assumed. |
What
The published
backthreadpackage shipped internal tracking ids. Three of them sat in strings a user reads without ever opening the bundle:backthread doctorPROJECT-scoped only — blind in git worktrees + other repos (ARP-680). Re-run ...PROJECT-scoped only — blind in git worktrees + other repos. Re-run ...backthread sweep... — left for GitHub-derived recovery (ARP-538).... — left for GitHub-derived recovery.~/.cursor/hooks/backthread-*.shheader# Backthread wrapper for Cursor — generated by \backthread install --agent cursor` (ARP-692).`# Backthread wrapper for Cursor — generated by \backthread install --agent cursor`.`The rest were comments that esbuild inlines into the committed
dist-bundle/backthread.js, plus five in the shipped plugin hook manifest (cli/hooks/hooks.json). All rewritten to keep the rationale and drop the id — e.g. "a per-project hook is exactly what froze the dogfood log" became "a per-project hook is exactly what silently stops capturing", which is the fact a reader can act on.The check
scripts/check-no-internal-refs.mjsresolves the exact file setnpm packships — thefileslist incli/package.jsonpluspackage.json— and fails on an internal id, a tracker URL, a private repository name or a company email domain. Source files that never reach the tarball are deliberately out of scope; the bundle is in scope, which is the part that matters, because a comment can travel into it silently.It runs after the bundle rebuild in CI, so it inspects the same bytes the tarball will carry, and again in the release job — a publish cannot be taken back.
--dir <path>points it at an extractedpackage/so the published artifact can be verified directly.Before:
After:
OK — no internal references in the shipped surface.Notes
0.18.1vianpm run bump(four version files + bundle in lockstep).