Skip to content

Commit 94fbd1f

Browse files
authored
Add one-command security tools setup and pre-push scanning (#1185)
* feat(security): add /setup-security-tools and pre-push scanning One command to set up AgentShield, zizmor, and Socket Firewall. Downloads binaries with SHA-256 verification, creates PATH shims (bash + Windows .cmd), and adds blocking scans to pre-push hook. * fix(security): address review feedback on setup-security-tools - Remove GIT_SSL_NO_VERIFY=true from SFW free shims (MITM risk) - Remove dead sha256File function and unused createReadStream/createHash imports - Fix pre-push: skip scan when no baseline exists instead of scanning all history - Fix pre-push: use remote_sha..local_sha for existing branches to avoid re-scanning already-pushed commits * fix(security): use $remote var, remove dead code, fix setupSfw return * fix(security): address round-2 review feedback - Use $remote variable instead of hardcoded 'origin' in pre-push hook - Remove unused YELLOW color variable - Return false from setupSfw when no shims were created - Add sync note referencing .husky/security-checks.sh * fix(security): add API key env file loading to Windows enterprise shims Windows .cmd shims for enterprise SFW had no equivalent of the bash shim's .env.local/.env file reading logic. Enterprise features would silently fail unless SOCKET_API_KEY was set as an OS-level env variable. * fix(security): redirect stdin for pre-checks, fix rebase suggestion - Redirect agentshield and zizmor stdin from /dev/null to prevent them from consuming git's ref data pipe, which would cause the while-read loop to silently iterate zero times - Use computed range base instead of $remote_sha in rebase suggestion so new-branch pushes don't print the zero SHA * fix: pin SFW version in download URL and fix shell range parsing - SFW: Replace /releases/latest/download/ with pinned /releases/download/v1.6.1/ to match hardcoded checksums. Latest URL breaks on new releases. - pre-push: Fix ${range%..*} → ${range%%\.\.*} for correct base SHA extraction. * refactor: load security tool config from external-tools.json Extract hardcoded zizmor/sfw versions, checksums, platform maps, and ecosystems into external-tools.json with Zod schema validation. Makes tool updates a JSON edit instead of code changes.
1 parent 06a8a9b commit 94fbd1f

File tree

8 files changed

+748
-0
lines changed

8 files changed

+748
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
Set up all Socket security tools for local development.
2+
3+
## What this sets up
4+
5+
1. **AgentShield** — scans Claude config for prompt injection and secrets
6+
2. **Zizmor** — static analysis for GitHub Actions workflows
7+
3. **SFW (Socket Firewall)** — intercepts package manager commands to scan for malware
8+
9+
## Setup
10+
11+
First, ask the user if they have a Socket API key for SFW enterprise features.
12+
13+
If they do:
14+
1. Ask them to provide it
15+
2. Write it to `.env.local` as `SOCKET_API_KEY=<their-key>` (create if needed)
16+
3. Verify `.env.local` is in `.gitignore` — if not, add it and warn
17+
18+
If they don't, proceed with SFW free mode.
19+
20+
Then run:
21+
```bash
22+
node .claude/hooks/setup-security-tools/index.mts
23+
```
24+
25+
After the script completes, add the SFW shim directory to PATH:
26+
```bash
27+
export PATH="$HOME/.socket/sfw/shims:$PATH"
28+
```
29+
30+
## Notes
31+
32+
- Safe to re-run (idempotent)
33+
- AgentShield needs `pnpm install` (it's a devDep)
34+
- Zizmor is cached at `~/.socket/zizmor/bin/`
35+
- SFW binary is cached via dlx at `~/.socket/_dlx/`
36+
- SFW shims are shared across repos at `~/.socket/sfw/shims/`
37+
- `.env.local` must NEVER be committed
38+
- `/update` will check for new versions of these tools via `node .claude/hooks/setup-security-tools/update.mts`
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# setup-security-tools Hook
2+
3+
Sets up all three Socket security tools for local development in one command.
4+
5+
## Tools
6+
7+
### 1. AgentShield
8+
Scans your Claude Code configuration (`.claude/` directory) for security issues like prompt injection, leaked secrets, and overly permissive tool permissions.
9+
10+
**How it's installed**: Already a devDependency (`ecc-agentshield`). The setup script just verifies it's available — if not, run `pnpm install`.
11+
12+
### 2. Zizmor
13+
Static analysis tool for GitHub Actions workflows. Catches unpinned actions, secret exposure, template injection, and permission issues.
14+
15+
**How it's installed**: Binary downloaded from [GitHub releases](https://github.com/woodruffw/zizmor/releases), SHA-256 verified, cached at `~/.socket/zizmor/bin/zizmor`. If you already have it via `brew install zizmor`, the download is skipped.
16+
17+
### 3. SFW (Socket Firewall)
18+
Intercepts package manager commands (`npm install`, `pnpm add`, etc.) and scans packages against Socket.dev's malware database before installation.
19+
20+
**How it's installed**: Binary downloaded from GitHub, SHA-256 verified, cached via the dlx system at `~/.socket/_dlx/`. Small wrapper scripts ("shims") are created at `~/.socket/sfw/shims/` that transparently route commands through the firewall.
21+
22+
**Free vs Enterprise**: If you have a `SOCKET_API_KEY` (in env, `.env`, or `.env.local`), enterprise mode is used with additional ecosystem support (gem, bundler, nuget, go). Otherwise, free mode covers npm, yarn, pnpm, pip, uv, and cargo.
23+
24+
## How to use
25+
26+
```
27+
/setup-security-tools
28+
```
29+
30+
Claude will ask if you have an API key, then run the setup script.
31+
32+
## What gets installed where
33+
34+
| Tool | Location | Persists across repos? |
35+
|------|----------|----------------------|
36+
| AgentShield | `node_modules/.bin/agentshield` | No (per-repo devDep) |
37+
| Zizmor | `~/.socket/zizmor/bin/zizmor` | Yes |
38+
| SFW binary | `~/.socket/_dlx/<hash>/sfw` | Yes |
39+
| SFW shims | `~/.socket/sfw/shims/npm`, etc. | Yes |
40+
41+
## Pre-push integration
42+
43+
The `.git-hooks/pre-push` hook automatically runs:
44+
- **AgentShield scan** (blocks push on failure)
45+
- **Zizmor scan** (blocks push on failure)
46+
47+
This means every push is checked — you don't have to remember to run `/security-scan`.
48+
49+
## Re-running
50+
51+
Safe to run multiple times:
52+
- AgentShield: just re-checks availability
53+
- Zizmor: skips download if cached binary matches expected version
54+
- SFW: skips download if cached, only rewrites shims if content changed
55+
56+
## Copying to another repo
57+
58+
Self-contained. To add to another Socket repo:
59+
60+
1. Copy `.claude/hooks/setup-security-tools/` and `.claude/commands/setup-security-tools.md`
61+
2. Run `cd .claude/hooks/setup-security-tools && npm install`
62+
3. Ensure `.claude/hooks/` is not gitignored (add `!/.claude/hooks/` to `.gitignore`)
63+
4. Ensure `ecc-agentshield` is a devDep in the target repo
64+
65+
## Troubleshooting
66+
67+
**"AgentShield not found"** — Run `pnpm install`. It's the `ecc-agentshield` devDependency.
68+
69+
**"zizmor found but wrong version"** — The script downloads the expected version to `~/.socket/zizmor/bin/`. Your system version (e.g. from brew) will be ignored in favor of the correct version.
70+
71+
**"No supported package managers found"** — SFW only creates shims for package managers found on your PATH. Install npm/pnpm/etc. first.
72+
73+
**SFW shims not intercepting** — Make sure `~/.socket/sfw/shims` is at the *front* of PATH. Run `which npm` — it should point to the shim, not the real binary.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"description": "Security tools for Claude Code hooks (self-contained, no external deps)",
3+
"tools": {
4+
"zizmor": {
5+
"description": "GitHub Actions security scanner",
6+
"version": "1.23.1",
7+
"repository": "woodruffw/zizmor",
8+
"assets": {
9+
"darwin-arm64": "zizmor-aarch64-apple-darwin.tar.gz",
10+
"darwin-x64": "zizmor-x86_64-apple-darwin.tar.gz",
11+
"linux-arm64": "zizmor-aarch64-unknown-linux-gnu.tar.gz",
12+
"linux-x64": "zizmor-x86_64-unknown-linux-gnu.tar.gz",
13+
"win32-x64": "zizmor-x86_64-pc-windows-msvc.zip"
14+
},
15+
"checksums": {
16+
"zizmor-aarch64-apple-darwin.tar.gz": "2632561b974c69f952258c1ab4b7432d5c7f92e555704155c3ac28a2910bd717",
17+
"zizmor-aarch64-unknown-linux-gnu.tar.gz": "3725d7cd7102e4d70827186389f7d5930b6878232930d0a3eb058d7e5b47e658",
18+
"zizmor-x86_64-apple-darwin.tar.gz": "89d5ed42081dd9d0433a10b7545fac42b35f1f030885c278b9712b32c66f2597",
19+
"zizmor-x86_64-pc-windows-msvc.zip": "33c2293ff02834720dd7cd8b47348aafb2e95a19bdc993c0ecaca9c804ade92a",
20+
"zizmor-x86_64-unknown-linux-gnu.tar.gz": "67a8df0a14352dd81882e14876653d097b99b0f4f6b6fe798edc0320cff27aff"
21+
}
22+
},
23+
"sfw-free": {
24+
"description": "Socket Firewall (free tier)",
25+
"version": "v1.6.1",
26+
"repository": "SocketDev/sfw-free",
27+
"platforms": {
28+
"darwin-arm64": "macos-arm64",
29+
"darwin-x64": "macos-x86_64",
30+
"linux-arm64": "linux-arm64",
31+
"linux-x64": "linux-x86_64",
32+
"win32-x64": "windows-x86_64"
33+
},
34+
"checksums": {
35+
"linux-arm64": "df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1",
36+
"linux-x86_64": "4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff",
37+
"macos-arm64": "bf1616fc44ac49f1cb2067fedfa127a3ae65d6ec6d634efbb3098cfa355e5555",
38+
"macos-x86_64": "724ccea19d847b79db8cc8e38f5f18ce2dd32336007f42b11bed7d2e5f4a2566",
39+
"windows-x86_64": "c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af"
40+
},
41+
"ecosystems": ["npm", "yarn", "pnpm", "pip", "uv", "cargo"]
42+
},
43+
"sfw-enterprise": {
44+
"description": "Socket Firewall (enterprise tier)",
45+
"version": "v1.6.1",
46+
"repository": "SocketDev/firewall-release",
47+
"platforms": {
48+
"darwin-arm64": "macos-arm64",
49+
"darwin-x64": "macos-x86_64",
50+
"linux-arm64": "linux-arm64",
51+
"linux-x64": "linux-x86_64",
52+
"win32-x64": "windows-x86_64"
53+
},
54+
"checksums": {
55+
"linux-arm64": "671270231617142404a1564e52672f79b806f9df3f232fcc7606329c0246da55",
56+
"linux-x86_64": "9115b4ca8021eb173eb9e9c3627deb7f1066f8debd48c5c9d9f3caabb2a26a4b",
57+
"macos-arm64": "acad0b517601bb7408e2e611c9226f47dcccbd83333d7fc5157f1d32ed2b953d",
58+
"macos-x86_64": "01d64d40effda35c31f8d8ee1fed1388aac0a11aba40d47fba8a36024b77500c",
59+
"windows-x86_64": "9a50e1ddaf038138c3f85418dc5df0113bbe6fc884f5abe158beaa9aea18d70a"
60+
},
61+
"ecosystems": ["npm", "yarn", "pnpm", "pip", "uv", "cargo", "gem", "bundler", "nuget"]
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)