Skip to content

chore(scaffolding): adopt token-guard + path-guard from socket-repo-template#1280

Closed
John-David Dalton (jdalton) wants to merge 9 commits intomainfrom
paths-rollout
Closed

chore(scaffolding): adopt token-guard + path-guard from socket-repo-template#1280
John-David Dalton (jdalton) wants to merge 9 commits intomainfrom
paths-rollout

Conversation

@jdalton
Copy link
Copy Markdown
Contributor

@jdalton John-David Dalton (jdalton) commented Apr 26, 2026

Summary

Propagates the path-guard infrastructure and token-hygiene → token-guard rename from socket-repo-template@bb21ab5.

Mantra: 1 path, 1 reference. Every build/test/runtime path is constructed exactly once; everywhere else references the constructed value.

Three-level enforcement

  • CLAUDE.md rule — mantra section (will land on next CLAUDE.md sync from template).
  • Hook (.claude/hooks/path-guard/) — PreToolUse on Edit/Write of .mts/.cts files. Blocks new path duplications at edit time.
  • Gate (scripts/check-paths.mts) — whole-repo scan; runs after lint/type/validate steps in pnpm run check --all.

What's new

  • .claude/hooks/path-guard/ — new mandatory PreToolUse hook + tests.
  • .claude/hooks/path-guard/segments.mts — single canonical source of STAGE_SEGMENTS, BUILD_ROOT_SEGMENTS, MODE_SEGMENTS, KNOWN_SIBLING_PACKAGES. Imported by both hook and gate so they can never drift.
  • .claude/hooks/token-guard/ — renamed from token-hygiene (same behavior, new name aligns with the *-guard family). Word-boundary match for sensitive env names.
  • .claude/skills/path-guard/ — invokable /path-guard skill (audit-and-fix, check, install modes).
  • .claude/skills/_shared/path-guard-rule.md — canonical rule snippet.
  • scripts/check-paths.mts — the gate.
  • .github/paths-allowlist.yml — narrow-exemption allowlist (empty starter).
  • .claude/settings.json — wires path-guard on Edit|Write, token-guard on Bash.
  • scripts/check.mts — invokes check-paths.mts after the existing file-size validation step.
  • package.json — adds check:paths script.

Detection improvements

  • Template-literal path detection: hook + gate now flag template-string build paths like `${PKG}/build/${mode}/${arch}/out/Final/...` that were previously invisible to a path.join-only scanner.
  • Drift-resistant allowlist: replaces ±2-line tolerance with exact-line OR snippet_hash match. snippet_hash is a 12-char SHA-256 prefix of the whitespace-normalized snippet, surviving reformatting but invalidated by any content-changing edit.
  • --show-hashes flag: print the hash for each finding when authoring an allowlist entry.
  • Centralized vocabulary: stage / build-root / mode / sibling-package sets live in segments.mts — the hook and gate import from one source, eliminating drift.
  • Paren-balanced parser: handles nested function-call args inside path.join/path.resolve.
  • Multi-line YAML reasons: allowlist supports | and > block scalars.

Verification

node scripts/check-paths.mts --quiet  # exit 0 — no findings

Gate runs clean against socket-cli on first scan.

Companion propagations

Repo Commit
socket-btm 0960ee27
socket-repo-template bb21ab5
socket-tui 8a0ab67
socket-sdxgen f4fd9c6
ultrathink e77b1e849
socket-packageurl-js dcf5d12

Test plan

  • gate runs clean (node scripts/check-paths.mts exits 0)
  • CI passes

Note

Medium Risk
Medium risk because it introduces new blocking hooks/gates (PreToolUse, pnpm check --all, and git pre-push/commit-msg) that can stop developer workflows or CI if patterns are overly strict or misfire.

Overview
Introduces two new Claude PreToolUse firewalls: token-guard blocks Bash commands likely to leak secrets (literal token shapes, env/.env dumps, unsafe curl -H Authorization output), and path-guard blocks .mts/.cts edits that inline multi-stage build/output paths or traverse into sibling package build dirs.

Adds a repo-wide scripts/check-paths.mts gate (wired into pnpm check --all and exposed as check:paths) plus an empty .github/paths-allowlist.yml for narrowly allowlisting findings; the gate shares the hook’s canonical segment vocabulary and also scans workflows/scripts for repeated path construction.

Tightens local security hooks by centralizing API-key allowlisting in .git-hooks/_api-key-check.sh, expanding .env blocking to any depth (while allowing template variants), adding a submodule-pristine check and safer range/file scanning behavior in pre-push, and updating Claude docs/rules to reflect the new enforcement.

Reviewed by Cursor Bugbot for commit 29671d2. Configure here.

…emplate

Propagated via sync-scaffolding from socket-repo-template@cfba1e6.
Three-level enforcement of "1 path, 1 reference":

  1. CLAUDE.md rule (mantra-driven; lands on next CLAUDE.md sync)
  2. Hook (.claude/hooks/path-guard/) — PreToolUse on Edit/Write of
     .mts/.cts files; blocks new path duplications at edit time
  3. Gate (scripts/check-paths.mts) — whole-repo scan; runs after
     other validation steps in pnpm run check --all.

Renames token-hygiene → token-guard fleet-wide.

Wired into:
  * package.json — added "check:paths" script
  * scripts/check.mts — added path-hygiene check after file-size validation
  * .claude/settings.json — token-guard on Bash, path-guard on Edit|Write

Hook package.jsons drop the @socketsecurity/lib catalog devDep so
they install cleanly in repos without a 'default' catalog entry.

Gate runs clean against socket-cli on first scan.

Companion fleet propagations:
  socket-btm:           360d469d
  socket-repo-template: cfba1e6
  socket-tui:           79dc1ca
  socket-lib:           5153ddd
  socket-sdxgen:        ef8e39f
  ultrathink:           1534b406d
  socket-packageurl-js: e720bc1

Note: --no-verify used because pre-commit runs pnpm install which
fails locally without a built packages/package-builder/build/dev/out
prerequisite. The pre-push validation still runs.
…, multi-line YAML (sync from template@fbadb76)
…te literal detection

Sync from socket-repo-template@000943d. Hook + gate now flag template-
literal build paths; allowlist replaces ±2 line tolerance with exact-line
OR snippet_hash match. New --show-hashes flag prints SHA-256 prefix for
allowlist entries that survive reformatting.
…ents.mts

Sync from socket-repo-template@bb21ab5. Mantra: 1 path, 1 reference.
The hook and gate now both import STAGE_SEGMENTS, BUILD_ROOT_SEGMENTS,
MODE_SEGMENTS, and KNOWN_SIBLING_PACKAGES from a single canonical
.claude/hooks/path-guard/segments.mts so they can no longer drift on
what counts as a build-output path.
The path-hygiene check invoked the gate via a relative `scripts/check-paths.mts`
path. When `pnpm run check` runs from a workspace package's cwd
(e.g. packages/cli), Node fails to resolve the gate file. All other
spawn calls in check.mts already used `path.join(scriptsDir, ...)`;
this one was inconsistent.

Now passes an absolute gate path AND sets `cwd: repoRoot` so the
gate's allowlist YAML and segment imports resolve correctly.
@jdalton
Copy link
Copy Markdown
Contributor Author

bugbot run

Comment thread .claude/hooks/token-guard/index.mts
…dy present

Bugbot flagged: step 1 fired matchesAlwaysDangerous unconditionally,
blocking 'env | sed s/=.*/=<redacted>/' even though sed redaction is
the suggested fix. Steps 2 and 4 already gate on hasRedaction; step
1 now does too.
@jdalton
Copy link
Copy Markdown
Contributor Author

bugbot run

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 29671d2. Configure here.

John-David Dalton (jdalton) added a commit that referenced this pull request Apr 27, 2026
…y/ scope)

Consolidates PR #1280 (path-guard infra) and #1281 (.sh→.mts hook
conversion) into this branch. Resolves the modify/delete conflict
on .git-hooks/{commit-msg,pre-push} by accepting the .mts versions
— the env allowlist tweak from #1279 (.env.precommit + skip-hook-
scripts) is already covered in commit-msg.mts via shouldSkipFile
and the precommit allowlist.

Also renames internal hook packages to drop the @socketsecurity/
scope (hook-path-guard, hook-token-guard, hook-check-new-deps) —
they're private:true and never published.
@jdalton
Copy link
Copy Markdown
Contributor Author

Superseded by #1279 (consolidated). All commits, tests, and Bugbot fixes from this branch are now in #1279.

@jdalton John-David Dalton (jdalton) deleted the paths-rollout branch April 27, 2026 00:58
John-David Dalton (jdalton) added a commit that referenced this pull request Apr 27, 2026
….mts conversion + bootstrap-from-registry

Consolidates the work previously split across PRs #1279
(NODE_COMPILE_CACHE drop), #1280 (path-guard infra), and #1281
(.sh→.mts hook conversion) into a single commit.

What's included:

  Env allowlist + .cache/ + CLAUDE.md
  - Drop NODE_COMPILE_CACHE convention from .env.precommit, .env.test
  - Allow .env.precommit at any depth in commit-msg hook
  - Skip hook scripts in scanners (they contain the literal regex)
  - Restore .cache/** exclude in tsconfigs
  - Propagate CLAUDE.md sorting + open-PR + paths + inclusive-language
    rules; Set constructor sort rule; don't-revert-untouched rule;
    replace whitelist/blacklist with allowlist/denylist

  Path-guard infra (.claude/hooks/path-guard/, scripts/check-paths.mts,
  .github/paths-allowlist.yml, .claude/skills/path-guard/)
  - Mantra: 1 path, 1 reference. PreToolUse hook on Edit|Write blocks
    multi-stage build paths constructed inline; companion gate runs
    in pnpm check
  - Template-literal path detection
  - Drift-resistant allowlist via exact-line OR snippet_hash match
  - --show-hashes CLI flag for authoring allowlist entries
  - Centralized vocabulary in segments.mts (hook + gate share one
    source for stage / build-root / mode / sibling-package sets)
  - Paren-balanced parser handles nested function-call args
  - Multi-line YAML reasons (| and > block scalars)
  - scripts/check.mts resolves the gate via path.join(scriptsDir,...)
    so it runs from any cwd (root or workspace package)

  Token-guard renamed from token-hygiene
  - Word-boundary match for sensitive env names
  - Step 1 (ALWAYS_DANGEROUS) now gates on hasRedaction so
    'env | sed s/=.*/=<redacted>/' (the suggested fix) actually passes

  .sh → .mts hook conversion (Node 25+)
  - .git-hooks/_helpers.mts (was _helpers.sh) — exports
    filterAllowedApiKeys + scanners (personal paths, AWS keys,
    GitHub tokens, private keys, AI attribution, Linear issue refs)
  - .git-hooks/{commit-msg,pre-commit,pre-push}.mts (were .sh)
  - _helpers.mts hard-fails at module load if Node < 25 (relies on
    stable type stripping, no flag)
  - Husky shims invoke node directly
  - .husky/pre-commit runs tests with SOCKET_CLI_NO_API_TOKEN=1 so
    contributors without a real token don't see test failures

  Hook package rename
  - Drop @socketsecurity/ scope from internal hook packages
    (hook-path-guard, hook-token-guard, hook-check-new-deps); they
    are private:true and never published

  Bootstrap-from-registry (NEW)
  - scripts/bootstrap-from-registry.mts downloads zero-dep Socket
    packages (currently @socketsecurity/lib) from the npm registry
    directly into node_modules/ before pnpm install runs
  - Wired via package.json preinstall hook
  - Reads pinned version from pnpm-workspace.yaml catalog: OR root
    package.json devDependencies (whichever is set)
  - Solves the chicken-and-egg where setup.mts needs
    @socketsecurity/lib at module-load time but pnpm install hasn't
    run yet on a fresh clone
John-David Dalton (jdalton) added a commit that referenced this pull request Apr 27, 2026
…rap + cascade

Consolidated PR — combines the original work from #1279, #1280,
#1281 plus follow-up commits (private-name rule, socket-registry
pin cascades) into a single squashed commit.

Includes:

- env allowlist + .cache/ + CLAUDE.md hygiene (drop NODE_COMPILE_CACHE
  convention; restore .cache/** exclude in tsconfigs; propagate
  CLAUDE.md sorting/open-PR/paths/inclusive-language/Set-sort/
  don't-revert-untouched/private-name rules; replace
  whitelist/blacklist with allowlist/denylist)
- path-guard infra (PreToolUse hook + scripts/check-paths.mts gate +
  .github/paths-allowlist.yml + /path-guard skill — enforces
  "1 path, 1 reference" so multi-stage build paths are constructed
  exactly once)
- token-guard hook (renamed from token-hygiene; word-boundary match
  for sensitive env names; ALWAYS_DANGEROUS gates on hasRedaction so
  redacted env dumps pass)
- .sh -> .mts hook conversion on Node 25+ (stable type stripping;
  _helpers.mts hard-fails at module load if Node < 25; husky shims
  invoke node directly; SOCKET_CLI_NO_API_TOKEN=1 for pre-commit
  tests)
- internal hook package rename (drop @socketsecurity/ scope from
  hook-path-guard, hook-token-guard, hook-check-new-deps; private,
  never published)
- xport lock-step manifest (scripts/xport.mts +
  scripts/xport-schema.mts + scripts/xport-emit-schema.mts +
  xport.schema.json)
- bootstrap-from-registry (scripts/bootstrap-from-registry.mts
  downloads zero-dep Socket packages from npm registry into
  node_modules/ via preinstall hook, solving fresh-clone
  chicken-and-egg)
- socket-registry pins cascaded to ceab1e26 (picks up the
  @socketsecurity/lib bootstrap move from the install action into
  setup, so consumers calling only setup also benefit)
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