diff --git a/.claude/hooks/setup-security-tools/external-tools.json b/.claude/hooks/setup-security-tools/external-tools.json index f8f6d2a2..fc18b17c 100644 --- a/.claude/hooks/setup-security-tools/external-tools.json +++ b/.claude/hooks/setup-security-tools/external-tools.json @@ -56,7 +56,7 @@ "sha256": "c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af" } }, - "ecosystems": ["npm", "yarn", "pnpm", "pip", "uv", "cargo"] + "ecosystems": ["npm", "yarn", "pnpm", "pip", "pip3", "uv", "cargo"] }, "sfw-enterprise": { "description": "Socket Firewall (enterprise tier)", @@ -85,7 +85,7 @@ "sha256": "9a50e1ddaf038138c3f85418dc5df0113bbe6fc884f5abe158beaa9aea18d70a" } }, - "ecosystems": ["npm", "yarn", "pnpm", "pip", "uv", "cargo", "gem", "bundler", "nuget"] + "ecosystems": ["npm", "yarn", "pnpm", "pip", "pip3", "uv", "cargo", "gem", "bundler", "nuget"] } } } diff --git a/.claude/hooks/setup-security-tools/index.mts b/.claude/hooks/setup-security-tools/index.mts index eb82e518..0c8c2086 100644 --- a/.claude/hooks/setup-security-tools/index.mts +++ b/.claude/hooks/setup-security-tools/index.mts @@ -19,6 +19,7 @@ import { fileURLToPath } from 'node:url' import { whichSync } from '@socketsecurity/lib/bin' import { downloadBinary } from '@socketsecurity/lib/dlx/binary' import { getDefaultLogger } from '@socketsecurity/lib/logger' +import { normalizePath } from '@socketsecurity/lib/paths/normalize' import { getSocketHomePath } from '@socketsecurity/lib/paths/socket' import { spawn, spawnSync } from '@socketsecurity/lib/spawn' import { z } from 'zod' @@ -194,6 +195,7 @@ async function setupSfw(apiKey: string | undefined): Promise { // Create shims. const isWindows = process.platform === 'win32' + const shimDir = path.join(getSocketHomePath(), 'sfw', 'shims') await fs.mkdir(shimDir, { recursive: true }) const ecosystems = [...(sfwConfig.ecosystems ?? [])] @@ -202,12 +204,14 @@ async function setupSfw(apiKey: string | undefined): Promise { } const cleanPath = (process.env['PATH'] ?? '').split(path.delimiter) .filter(p => p !== shimDir).join(path.delimiter) + const sfwBin = normalizePath(binaryPath) const created: string[] = [] for (const cmd of ecosystems) { - const realBin = whichSync(cmd, { nothrow: true, path: cleanPath }) + let realBin = whichSync(cmd, { nothrow: true, path: cleanPath }) if (!realBin || typeof realBin !== 'string') continue + realBin = normalizePath(realBin) - // Bash shim (macOS/Linux). + // Bash shim (macOS/Linux/Windows Git Bash). const bashLines = [ '#!/bin/bash', `export PATH="$(echo "$PATH" | tr ':' '\\n' | grep -vxF '${shimDir}' | paste -sd: -)"`, @@ -226,7 +230,7 @@ async function setupSfw(apiKey: string | undefined): Promise { 'fi', ) } - bashLines.push(`exec "${binaryPath}" "${realBin}" "$@"`) + bashLines.push(`exec "${sfwBin}" "${realBin}" "$@"`) const bashContent = bashLines.join('\n') + '\n' const bashPath = path.join(shimDir, cmd) if (!existsSync(bashPath) || await fs.readFile(bashPath, 'utf8').catch(() => '') !== bashContent) { @@ -256,7 +260,7 @@ async function setupSfw(apiKey: string | undefined): Promise { + `set "PATH=%PATH:;${shimDir};=%"\r\n` + `set "PATH=%PATH:~1,-1%"\r\n` + cmdApiKeyBlock - + `"${binaryPath}" "${realBin}" %*\r\n` + + `"${sfwBin}" "${realBin}" %*\r\n` const cmdPath = path.join(shimDir, `${cmd}.cmd`) if (!existsSync(cmdPath) || await fs.readFile(cmdPath, 'utf8').catch(() => '') !== cmdContent) { await fs.writeFile(cmdPath, cmdContent) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 18fa8969..4b67609d 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -172,9 +172,9 @@ runs: strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } CLEAN_PATH="$(strip_shim_dir)" SSL_WORKAROUND="" - SHIM_CMDS="npm yarn pnpm pip uv cargo" + SHIM_CMDS="npm yarn pnpm pip pip3 uv cargo" if [ "$SFW_IS_ENTERPRISE" = "true" ]; then - SHIM_CMDS="npm yarn pnpm pip uv cargo gem bundler nuget" + SHIM_CMDS="npm yarn pnpm pip pip3 uv cargo gem bundler nuget" # Go wrapper mode is only supported on Linux. [[ "$OSTYPE" == linux* ]] && SHIM_CMDS="$SHIM_CMDS go" else