Skip to content

Commit 0f6a6d1

Browse files
committed
Merge remote-tracking branch 'origin/main' into chore/bump-socket-registry-sha
2 parents 90b5d1b + e3896a7 commit 0f6a6d1

File tree

4 files changed

+129
-293
lines changed

4 files changed

+129
-293
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Scans your Claude Code configuration (`.claude/` directory) for security issues
1212
### 2. Zizmor
1313
Static analysis tool for GitHub Actions workflows. Catches unpinned actions, secret exposure, template injection, and permission issues.
1414

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.
15+
**How it's installed**: Binary downloaded from [GitHub releases](https://github.com/zizmorcore/zizmor/releases), SHA-256 verified, cached via the dlx system at `~/.socket/_dlx/`. If you already have it via `brew install zizmor`, the download is skipped.
1616

1717
### 3. SFW (Socket Firewall)
1818
Intercepts package manager commands (`npm install`, `pnpm add`, etc.) and scans packages against Socket.dev's malware database before installation.
@@ -34,7 +34,7 @@ Claude will ask if you have an API key, then run the setup script.
3434
| Tool | Location | Persists across repos? |
3535
|------|----------|----------------------|
3636
| AgentShield | `node_modules/.bin/agentshield` | No (per-repo devDep) |
37-
| Zizmor | `~/.socket/zizmor/bin/zizmor` | Yes |
37+
| Zizmor | `~/.socket/_dlx/<hash>/zizmor` | Yes |
3838
| SFW binary | `~/.socket/_dlx/<hash>/sfw` | Yes |
3939
| SFW shims | `~/.socket/sfw/shims/npm`, etc. | Yes |
4040

@@ -66,7 +66,7 @@ Self-contained. To add to another Socket repo:
6666

6767
**"AgentShield not found"** — Run `pnpm install`. It's the `ecc-agentshield` devDependency.
6868

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.
69+
**"zizmor found but wrong version"** — The script downloads the expected version via the dlx cache. Your system version (e.g. from brew) will be ignored in favor of the correct version.
7070

7171
**"No supported package managers found"** — SFW only creates shims for package managers found on your PATH. Install npm/pnpm/etc. first.
7272

.claude/hooks/setup-security-tools/external-tools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"zizmor": {
55
"description": "GitHub Actions security scanner",
66
"version": "1.23.1",
7-
"repository": "woodruffw/zizmor",
7+
"repository": "zizmorcore/zizmor",
88
"assets": {
99
"darwin-arm64": "zizmor-aarch64-apple-darwin.tar.gz",
1010
"darwin-x64": "zizmor-x86_64-apple-darwin.tar.gz",

.claude/hooks/setup-security-tools/index.mts

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// 1. AgentShield — scans Claude AI config for prompt injection / secrets.
66
// Already a devDep (ecc-agentshield); this script verifies it's installed.
77
// 2. Zizmor — static analysis for GitHub Actions workflows. Downloads the
8-
// correct binary, verifies SHA-256, caches at ~/.socket/zizmor/bin/zizmor.
8+
// correct binary, verifies SHA-256, cached via the dlx system.
99
// 3. SFW (Socket Firewall) — intercepts package manager commands to scan
1010
// for malware. Downloads binary, verifies SHA-256, creates PATH shims.
1111
// Enterprise vs free determined by SOCKET_API_KEY in env / .env / .env.local.
@@ -18,7 +18,6 @@ import { fileURLToPath } from 'node:url'
1818

1919
import { whichSync } from '@socketsecurity/lib/bin'
2020
import { downloadBinary } from '@socketsecurity/lib/dlx/binary'
21-
import { httpDownload } from '@socketsecurity/lib/http-request'
2221
import { getDefaultLogger } from '@socketsecurity/lib/logger'
2322
import { getSocketHomePath } from '@socketsecurity/lib/paths/socket'
2423
import { spawn, spawnSync } from '@socketsecurity/lib/spawn'
@@ -121,53 +120,50 @@ async function setupZizmor(): Promise<boolean> {
121120
logger.log(`Found on PATH but wrong version (need v${ZIZMOR.version})`)
122121
}
123122

124-
// Check cached binary.
125-
const ext = process.platform === 'win32' ? '.exe' : ''
126-
const binDir = path.join(getSocketHomePath(), 'zizmor', 'bin')
127-
const binPath = path.join(binDir, `zizmor${ext}`)
128-
if (existsSync(binPath) && await checkZizmorVersion(binPath)) {
129-
logger.log(`Cached: ${binPath} (v${ZIZMOR.version})`)
130-
return true
131-
}
132-
133-
// Download.
123+
// Download archive via dlx (handles caching + checksum).
134124
const platformKey = `${process.platform}-${process.arch}`
135125
const asset = ZIZMOR.assets?.[platformKey]
136126
if (!asset) throw new Error(`Unsupported platform: ${platformKey}`)
137127
const expectedSha = ZIZMOR.checksums?.[asset]
138128
if (!expectedSha) throw new Error(`No checksum for: ${asset}`)
139129
const url = `https://github.com/${ZIZMOR.repository}/releases/download/v${ZIZMOR.version}/${asset}`
140-
const isZip = asset.endsWith('.zip')
141130

142131
logger.log(`Downloading zizmor v${ZIZMOR.version} (${asset})...`)
143-
const tmpFile = path.join(tmpdir(), `zizmor-${Date.now()}-${asset}`)
144-
try {
145-
await httpDownload(url, tmpFile, { sha256: expectedSha })
146-
logger.log('Download complete, checksum verified.')
132+
const { binaryPath: archivePath, downloaded } = await downloadBinary({
133+
url,
134+
name: `zizmor-${ZIZMOR.version}-${asset}`,
135+
sha256: expectedSha,
136+
})
137+
logger.log(downloaded ? 'Download complete, checksum verified.' : `Using cached archive: ${archivePath}`)
138+
139+
// Extract binary from the cached archive.
140+
const ext = process.platform === 'win32' ? '.exe' : ''
141+
const binPath = path.join(path.dirname(archivePath), `zizmor${ext}`)
142+
if (existsSync(binPath) && await checkZizmorVersion(binPath)) {
143+
logger.log(`Cached: ${binPath} (v${ZIZMOR.version})`)
144+
return true
145+
}
147146

148-
// Extract.
149-
const extractDir = path.join(tmpdir(), `zizmor-extract-${Date.now()}`)
150-
await fs.mkdir(extractDir, { recursive: true })
147+
const isZip = asset.endsWith('.zip')
148+
const extractDir = path.join(tmpdir(), `zizmor-extract-${Date.now()}`)
149+
await fs.mkdir(extractDir, { recursive: true })
150+
try {
151151
if (isZip) {
152152
await spawn('powershell', ['-NoProfile', '-Command',
153-
`Expand-Archive -Path '${tmpFile}' -DestinationPath '${extractDir}' -Force`], { stdio: 'pipe' })
153+
`Expand-Archive -Path '${archivePath}' -DestinationPath '${extractDir}' -Force`], { stdio: 'pipe' })
154154
} else {
155-
await spawn('tar', ['xzf', tmpFile, '-C', extractDir], { stdio: 'pipe' })
155+
await spawn('tar', ['xzf', archivePath, '-C', extractDir], { stdio: 'pipe' })
156156
}
157-
158-
// Install.
159157
const extractedBin = path.join(extractDir, `zizmor${ext}`)
160158
if (!existsSync(extractedBin)) throw new Error(`Binary not found after extraction: ${extractedBin}`)
161-
await fs.mkdir(binDir, { recursive: true })
162159
await fs.copyFile(extractedBin, binPath)
163160
await fs.chmod(binPath, 0o755)
164-
await fs.rm(extractDir, { recursive: true, force: true })
165-
166-
logger.log(`Installed to ${binPath}`)
167-
return true
168161
} finally {
169-
if (existsSync(tmpFile)) await fs.unlink(tmpFile).catch(() => {})
162+
await fs.rm(extractDir, { recursive: true, force: true }).catch(() => {})
170163
}
164+
165+
logger.log(`Installed to ${binPath}`)
166+
return true
171167
}
172168

173169
// ── SFW ──

0 commit comments

Comments
 (0)