Skip to content

Commit f76b7a8

Browse files
committed
Merge remote-tracking branch 'origin/paths-rollout' into chore/harden-env-allowlist
2 parents 6186ee4 + 8ad29da commit f76b7a8

31 files changed

Lines changed: 5723 additions & 26 deletions

.claude/agents/security-reviewer.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ Apply these rules from CLAUDE.md exactly:
44

55
**Safe File Operations**: Use safeDelete()/safeDeleteSync() from @socketsecurity/lib/fs. NEVER fs.rm(), fs.rmSync(), or rm -rf. Use os.tmpdir() + fs.mkdtemp() for temp dirs. NEVER use fetch() — use httpJson/httpText/httpRequest from @socketsecurity/lib/http-request.
66

7-
**Absolute Rules**: NEVER use npx, pnpm dlx, or yarn dlx. Use pnpm exec or pnpm run with pinned devDeps.
7+
**Absolute Rules**: NEVER use npx, pnpm dlx, or yarn dlx. Use pnpm exec or pnpm run with pinned devDeps. # zizmor: documentation-prohibition
88

99
**Work Safeguards**: Scripts modifying multiple files must have backup/rollback. Git operations that rewrite history require explicit confirmation.
1010

1111
**Review checklist:**
1212

1313
1. **Secrets**: Hardcoded API keys, passwords, tokens, private keys in code or config
1414
2. **Injection**: Command injection via shell: true or string interpolation in spawn/exec. Path traversal in file operations.
15-
3. **Dependencies**: npx/dlx usage. Unpinned versions (^ or ~). Missing minimumReleaseAge bypass justification.
15+
3. **Dependencies**: npx/dlx usage. Unpinned versions (^ or ~). Missing minimumReleaseAge bypass justification. # zizmor: documentation-checklist
1616
4. **File operations**: fs.rm without safeDelete. process.chdir usage. fetch() usage (must use lib's httpRequest).
1717
5. **GitHub Actions**: Unpinned action versions (must use full SHA). Secrets outside env blocks. Template injection from untrusted inputs.
1818
6. **Error handling**: Sensitive data in error messages. Stack traces exposed to users.

.claude/hooks/path-guard/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# path-guard
2+
3+
Claude Code `PreToolUse` hook that refuses `Edit`/`Write` tool calls that would *construct* a multi-segment build/output path inline in a `.mts` or `.cts` file. Mandatory across the Socket fleet — every repo ships this file byte-for-byte via `scripts/sync-scaffolding.mjs`.
4+
5+
**Mantra: 1 path, 1 reference.**
6+
7+
Construct a path *once* in the canonical `paths.mts` (or a build-infra helper); reference the computed value everywhere else.
8+
9+
## What it blocks
10+
11+
| Rule | Example | Fix |
12+
|------|---------|-----|
13+
| **A** — Multi-stage path constructed inline | `path.join(PKG, 'build', mode, 'out', 'Final', name)` | Construct in the package's `scripts/paths.mts` (or use `getFinalBinaryPath` from `build-infra/lib/paths`); import the computed value here |
14+
| **B** — Cross-package path traversal | `path.join(PKG, '..', 'lief-builder', 'build', ...)` | Add `lief-builder: workspace:*` as a dep; import its `paths.mts` via the workspace `exports` field |
15+
16+
The hook fires on `Edit` and `Write` tool calls when the target path ends in `.mts` or `.cts`. Other extensions (`.ts`, `.mjs`, `.js`, `.yml`, `.json`, `.md`) pass through — TS path code lives in `.mts` per CLAUDE.md, and other file types are covered by the `scripts/check-paths.mts` gate at commit time.
17+
18+
## What it allows
19+
20+
- Edits to a `paths.mts` (canonical constructor — every package's source of truth).
21+
- Edits to `scripts/check-paths.mts` (the gate, which legitimately enumerates patterns).
22+
- Edits to this hook's own files (the test suite has to enumerate the same patterns).
23+
- Edits to `scripts/check-consistency.mts` (existing path-scanning gate).
24+
- `path.join` calls with a single stage segment (e.g. `path.join(packageRoot, 'build', 'temp')`) — that's a one-off helper path, not a multi-stage build output.
25+
- `path.join` calls with no stage segments at all (most general-purpose joins).
26+
- Any string concatenation that doesn't go through `path.join` — the hook is regex-based and intentionally narrow; the gate runs a deeper scan at commit time.
27+
28+
## Stage segments the hook recognizes
29+
30+
These come from `build-infra/lib/constants.mts` `BUILD_STAGES` plus the lowercase directory-name siblings used by some builders:
31+
32+
`Final`, `Release`, `Stripped`, `Compressed`, `Optimized`, `Synced`, `wasm`, `downloaded`
33+
34+
Two or more in the same `path.join` call (or one stage + one of `'build'`/`'out'` + one mode `'dev'`/`'prod'`) triggers Rule A.
35+
36+
## Known sibling packages (for Rule B)
37+
38+
The hook recognizes Rule B traversals only when the next segment after `..` is a known fleet package name:
39+
40+
`binflate`, `binject`, `binpress`, `bin-infra`, `build-infra`, `codet5-models-builder`, `curl-builder`, `iocraft-builder`, `ink-builder`, `libpq-builder`, `lief-builder`, `minilm-builder`, `models`, `napi-go`, `node-smol-builder`, `onnxruntime-builder`, `opentui-builder`, `stubs-builder`, `ultraviolet-builder`, `yoga-layout-builder`
41+
42+
When a new package joins the workspace, add it here.
43+
44+
## Control flow
45+
46+
The hook reads the tool-use payload from stdin, type-checks `tool_name === 'Edit'` or `'Write'`, filters to `.mts`/`.cts` files, and runs `check(source)`. Any rule violation `throw`s a typed `BlockError`; a single top-level `try/catch` in `main()` writes the block message to stderr and sets `process.exitCode = 2`.
47+
48+
Hook bugs fail **open** — a crash in the hook writes a log line and returns exit 0 so legitimate work isn't blocked on a bad deploy. The companion `scripts/check-paths.mts` gate runs a thorough whole-repo scan at `pnpm check` time, catching anything the hook misses.
49+
50+
## Testing
51+
52+
```bash
53+
pnpm --filter @socketsecurity/hook-path-guard test
54+
```
55+
56+
Adding a new detection pattern: update `STAGE_SEGMENTS` (or `KNOWN_SIBLING_PACKAGES`) in `index.mts`, add a positive and negative test in `test/path-guard.test.mts`.
57+
58+
## Updating across the fleet
59+
60+
This file is in `IDENTICAL_FILES` in `scripts/sync-scaffolding.mjs` (in `socket-repo-template`). After editing, run from `socket-repo-template`:
61+
62+
```bash
63+
node scripts/sync-scaffolding.mjs --all --fix
64+
```
65+
66+
to propagate the change to every fleet repo.

0 commit comments

Comments
 (0)