Skip to content

Commit 474da37

Browse files
committed
chore(sync): cascade SOCKET_API_TOKEN canonical + cross-repo-guard placeholder fixes from socket-repo-template
1 parent 12404c2 commit 474da37

8 files changed

Lines changed: 83 additions & 26 deletions

File tree

.claude/commands/setup-security-tools.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ Set up all Socket security tools for local development.
88

99
## Setup
1010

11-
First, ask the user if they have a Socket API key for SFW enterprise features.
11+
First, ask the user if they have a Socket API token for SFW enterprise features.
1212

1313
If they do:
1414
1. Ask them to provide it
15-
2. Write it to `.env.local` as `SOCKET_API_KEY=<their-key>` (create if needed)
15+
2. Write it to `.env.local` as `SOCKET_API_TOKEN=<their-token>` (create if needed). The deprecated `SOCKET_API_KEY` name is also accepted as an alias for one cycle, but new files should use `SOCKET_API_TOKEN`.
1616
3. Verify `.env.local` is in `.gitignore` — if not, add it and warn
1717

1818
If they don't, proceed with SFW free mode.

.claude/hooks/cross-repo-guard/test/cross-repo-guard.test.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ test('blocks ../socket-lib/ relative reference', async () => {
4545
assert.ok(stderr.includes('cross-repo-guard'))
4646
})
4747

48-
test('blocks /Users/<name>/projects/<fleet-repo>/ absolute reference', async () => {
48+
test('blocks /Users/<user>/projects/<fleet-repo>/ absolute reference', async () => {
4949
const { code, stderr } = await runHook({
5050
tool_name: 'Write',
5151
tool_input: {

.claude/hooks/setup-security-tools/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ package manager — that transparently route commands through the
5151
firewall. You make sure that directory is at the front of your PATH;
5252
nothing else changes about how you use the tools.
5353

54-
**Free vs. Enterprise**: if `SOCKET_API_KEY` is set in your env,
54+
**Free vs. Enterprise**: if `SOCKET_API_TOKEN` is set in your env,
5555
`.env`, or `.env.local`, the script installs the enterprise SFW
5656
build (which adds gem, bundler, nuget, and go support). Otherwise
5757
it installs the free build (npm, yarn, pnpm, pip, pip3, uv, cargo).
58+
The legacy name `SOCKET_API_KEY` is still recognized as an alias
59+
for one cycle so existing dev setups don't break in lockstep with
60+
the rename — pass either name and the bootstrap reads it.
5861

5962
## How to use
6063

@@ -64,8 +67,9 @@ pnpm run setup
6467

6568
(That's wired in `package.json` to `node .claude/hooks/setup-security-tools/index.mts`.)
6669

67-
The script will detect whether you have a `SOCKET_API_KEY`, ask if
68-
unsure, then download whatever isn't already cached.
70+
The script will detect whether you have a `SOCKET_API_TOKEN` (or the
71+
deprecated `SOCKET_API_KEY` alias), ask if unsure, then download
72+
whatever isn't already cached.
6973

7074
## Where each tool lands
7175

.git-hooks/_helpers.mts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,21 @@ export const FAKE_TOKEN_MARKER = 'socket-test-fake-token'
5252
// lib's rename PR lands.
5353
export const FAKE_TOKEN_LEGACY = 'socket-lib-test-fake-token'
5454

55-
// Name of the env var used in shell examples; not a token value.
56-
export const SOCKET_SECURITY_ENV = 'SOCKET_SECURITY_API_KEY='
55+
// Env-var name prefixes used in shell examples / `.env.example` files.
56+
// Lines containing `<name>=` are documentation, not real tokens — drop
57+
// them from secret-scanner hits. SOCKET_API_TOKEN is the canonical
58+
// fleet name; the rest are legacy variants kept on the allowlist for
59+
// one cycle so existing `.env.example` files don't trip the gate
60+
// after the rebrand.
61+
export const SOCKET_TOKEN_ENV_NAMES: readonly string[] = [
62+
'SOCKET_API_TOKEN=',
63+
'SOCKET_API_KEY=',
64+
'SOCKET_SECURITY_API_TOKEN=',
65+
'SOCKET_SECURITY_API_KEY=',
66+
]
67+
// Back-compat alias — earlier callers imported this single-string
68+
// constant. New code should reach for SOCKET_TOKEN_ENV_NAMES.
69+
export const SOCKET_SECURITY_ENV = SOCKET_TOKEN_ENV_NAMES[0]!
5770

5871
// ── Output ──────────────────────────────────────────────────────────
5972
//
@@ -79,7 +92,7 @@ const isAllowedApiKey = (line: string): boolean =>
7992
line.includes(ALLOWED_PUBLIC_KEY) ||
8093
line.includes(FAKE_TOKEN_MARKER) ||
8194
line.includes(FAKE_TOKEN_LEGACY) ||
82-
line.includes(SOCKET_SECURITY_ENV) ||
95+
SOCKET_TOKEN_ENV_NAMES.some(name => line.includes(name)) ||
8396
line.includes('.example')
8497

8598
// Drops any line that matches an allowlist entry. Kept for callers
@@ -94,8 +107,20 @@ export const filterAllowedApiKeys = (lines: readonly string[]): string[] =>
94107
const PERSONAL_PATH_RE =
95108
/(\/Users\/[^/\s]+\/|\/home\/[^/\s]+\/|C:\\Users\\[^\\]+\\)/
96109

97-
// Placeholders we ALLOW (documentation, not real leaks): any path
98-
// component wrapped in <...> or starting with $VAR / ${VAR}.
110+
// Placeholders we ALLOW (documentation, not real leaks). The scanner
111+
// accepts any path component wrapped in <...> or starting with $VAR /
112+
// ${VAR}, but for **canonical fleet style** use exactly these forms in
113+
// docs / tests / comments / error messages — pick the one matching the
114+
// path's platform:
115+
//
116+
// POSIX → /Users/<user>/... (macOS — `<user>` matches $USER)
117+
// POSIX → /home/<user>/... (Linux — same convention)
118+
// Windows → C:\Users\<USERNAME>\... (matches %USERNAME%)
119+
//
120+
// Don't drift to `<name>` / `<me>` / `<USER>` / `<u>` etc. The
121+
// `suggestPersonalPathReplacement` helper below auto-rewrites real
122+
// paths into these canonical shapes; mirror its output everywhere
123+
// else.
99124
const PERSONAL_PATH_PLACEHOLDER_RE =
100125
/(\/Users\/<[^>]*>\/|\/home\/<[^>]*>\/|C:\\Users\\<[^>]*>\\|\/Users\/\$\{?[A-Z_]+\}?\/|\/home\/\$\{?[A-Z_]+\}?\/)/
101126

.git-hooks/pre-commit.mts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,11 @@ const main = (): number => {
110110
}
111111
}
112112
logger.info(
113-
'Replace with `<user>` / `<USERNAME>` placeholders, an env var ' +
114-
'(`$HOME`, `${USER}`), or — for documentation lines that need ' +
115-
'the literal username form — append the marker ' +
116-
'`# zizmor: documentation-placeholder`.',
113+
'Replace with the canonical placeholder for the path platform: ' +
114+
'`/Users/<user>/...` (macOS), `/home/<user>/...` (Linux), or ' +
115+
'`C:\\Users\\<USERNAME>\\...` (Windows). Env vars also work ' +
116+
'(`$HOME`, `${USER}`). For documentation lines that need the ' +
117+
`literal form, append the marker \`${socketHookMarkerFor(file, 'personal-path')}\`.`,
117118
)
118119
errors++
119120
}
@@ -132,7 +133,9 @@ const main = (): number => {
132133
const hits = scanSocketApiKeys(text)
133134
if (hits.length > 0) {
134135
logger.warn(`Potential API key found in: ${file}`)
135-
hits.slice(0, 3).forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
136+
hits
137+
.slice(0, 3)
138+
.forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
136139
logger.info('If this is a real API key, DO NOT COMMIT IT.')
137140
}
138141
}
@@ -151,14 +154,18 @@ const main = (): number => {
151154
const aws = scanAwsKeys(text)
152155
if (aws.length > 0) {
153156
logger.fail(`Potential AWS credentials found in: ${file}`)
154-
aws.slice(0, 3).forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
157+
aws
158+
.slice(0, 3)
159+
.forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
155160
errors++
156161
}
157162

158163
const gh = scanGitHubTokens(text)
159164
if (gh.length > 0) {
160165
logger.fail(`Potential GitHub token found in: ${file}`)
161-
gh.slice(0, 3).forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
166+
gh.slice(0, 3).forEach(h =>
167+
logger.info(`${h.lineNumber}:${h.line.trim()}`),
168+
)
162169
errors++
163170
}
164171

.git-hooks/pre-push.mts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@ const scanCommitMessages = (range: string): number => {
174174
}
175175
if (errors > 0) {
176176
logger.info('')
177-
logger.info('These commits were likely created with --no-verify, bypassing the')
177+
logger.info(
178+
'These commits were likely created with --no-verify, bypassing the',
179+
)
178180
logger.info('commit-msg hook that strips AI attribution.')
179181
logger.info('')
180182
const rangeBase = range.split('..')[0]
@@ -267,32 +269,39 @@ const scanFilesInRange = (range: string): number => {
267269
}
268270
}
269271
logger.info(
270-
'Replace with `<user>` / `<USERNAME>` placeholders, an env var ' +
271-
'(`$HOME`, `${USER}`), or — for documentation lines that need ' +
272-
'the literal username form — append the marker ' +
273-
'`# zizmor: documentation-placeholder`.',
272+
'Replace with the canonical placeholder for the path platform: ' +
273+
'`/Users/<user>/...` (macOS), `/home/<user>/...` (Linux), or ' +
274+
'`C:\\Users\\<USERNAME>\\...` (Windows). Env vars also work ' +
275+
'(`$HOME`, `${USER}`). For documentation lines that need the ' +
276+
`literal form, append the marker \`${socketHookMarkerFor(file, 'personal-path')}\`.`,
274277
)
275278
errors++
276279
}
277280

278281
const apiHits = scanSocketApiKeys(text)
279282
if (apiHits.length > 0) {
280283
logger.fail(`Real API key detected in: ${file}`)
281-
apiHits.slice(0, 3).forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
284+
apiHits
285+
.slice(0, 3)
286+
.forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
282287
errors++
283288
}
284289

285290
const awsHits = scanAwsKeys(text)
286291
if (awsHits.length > 0) {
287292
logger.fail(`Potential AWS credentials found in: ${file}`)
288-
awsHits.slice(0, 3).forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
293+
awsHits
294+
.slice(0, 3)
295+
.forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
289296
errors++
290297
}
291298

292299
const ghHits = scanGitHubTokens(text)
293300
if (ghHits.length > 0) {
294301
logger.fail(`Potential GitHub token found in: ${file}`)
295-
ghHits.slice(0, 3).forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
302+
ghHits
303+
.slice(0, 3)
304+
.forEach(h => logger.info(`${h.lineNumber}:${h.line.trim()}`))
296305
errors++
297306
}
298307

CLAUDE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ Behavior the hook can't catch: redact `token` / `jwt` / `access_token` / `refres
160160

161161
Full hook spec in [`.claude/hooks/token-guard/README.md`](.claude/hooks/token-guard/README.md).
162162

163+
**Personal-path placeholders** — when a doc / test / comment needs to show an example user-home path, use the canonical platform-specific placeholder so the personal-paths scanner recognizes it as documentation: `/Users/<user>/...` (macOS), `/home/<user>/...` (Linux), `C:\Users\<USERNAME>\...` (Windows). Don't drift to `<name>` / `<me>` / `<USER>` / `<u>` etc. — the scanner accepts anything in `<...>` but a fleet-wide audit relies on the canonical strings being grep-able. Env vars (`$HOME`, `${USER}`, `%USERNAME%`) also satisfy the scanner.
164+
165+
**Socket API token env var** — the canonical fleet name is `SOCKET_API_TOKEN`. The legacy names `SOCKET_API_KEY`, `SOCKET_SECURITY_API_TOKEN`, and `SOCKET_SECURITY_API_KEY` are accepted as aliases for one cycle (deprecation grace period) — bootstrap hooks read all four and normalize to `SOCKET_API_TOKEN` going forward. New `.env.example` files, docs, workflow inputs, and action env exports use `SOCKET_API_TOKEN`. Don't confuse with `SOCKET_CLI_API_TOKEN` (socket-cli's separate setting).
166+
167+
**Cross-repo path references**`../<fleet-repo>/...` (relative escape) and `/<abs-prefix>/projects/<fleet-repo>/...` (absolute sibling-clone) are both forbidden. Either form hardcodes a clone-layout assumption that breaks in CI / fresh clones / non-standard checkouts. Import via the published npm package (`@socketsecurity/lib/<subpath>`, `@socketsecurity/registry/<subpath>`) — every fleet repo is a real workspace dep. The `cross-repo-guard` PreToolUse hook blocks both forms at edit time; the git-side `scanCrossRepoPaths` gate catches commits/pushes too.
168+
163169
### Agents & skills
164170

165171
- `/scanning-security` — AgentShield + zizmor audit

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)