From 968ebb2f246a49b36b2d4c89c201ae4d5a32af1c Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 10:53:49 -0400 Subject: [PATCH 01/10] fix(ci): inline CI setup, add Node 24 support, harden workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously our CI workflows depended on a shared composite action from the socket-registry repo (setup-and-install). That action was pinned to an October 2025 SHA that predated Node 24 support, and updating it meant tracking SHA cascades across multiple layers of nested actions. This commit replaces that dependency by inlining every setup step directly into each workflow file. Now each workflow is self-contained and easy to read top-to-bottom: 1. actions/checkout — clone the repo 2. pnpm/action-setup — install pnpm (version from package.json) 3. actions/setup-node — install the right Node.js version 4. Download sfw-free — fetch the Socket Firewall binary 5. Create sfw shims — wrap npm/yarn/pnpm through the firewall 6. pnpm install — install dependencies (through the firewall) All three actions are pinned to full commit SHAs (not version tags) so the exact code that runs is deterministic and auditable. Binary downloads (sfw-free v1.6.1) are verified against SHA-256 checksums baked into the workflow. If someone tampers with a release asset, CI will fail immediately instead of running untrusted code. The sfw shim scripts handle both Linux/macOS and Windows: - On Windows, MSYS-style paths (/c/Users/...) are converted to native format (C:\Users\...) so sfw-free can resolve them correctly. - .cmd wrapper files are generated alongside bash shims for Windows. - Each shim strips its own directory from PATH before exec to prevent infinite recursion (shim calling itself instead of the real binary). Other changes: - Node 24 is now tested in the CI matrix alongside Node 20 and 22. Provenance publishes with Node 24. - The lint job now runs zizmor (a GitHub Actions security auditor) on every push/PR. It downloads a pinned, checksum-verified native binary — no Docker, Python, or pip needed. It scans .github/ for template injection, unpinned actions, cache poisoning, and other issues. - Removed three dead workflow files that referenced shared workflows which no longer exist upstream: claude-auto-review.yml, claude.yml, and socket-auto-pr.yml. - Fixed template injection in provenance.yml: inputs.dist-tag was interpolated directly into run blocks (attackable via workflow dispatch). Now passed through an environment variable instead. - Removed the push/tag trigger from e2e-tests.yml to eliminate a cache-poisoning vector flagged by zizmor (PR + tag triggers combined with action caching). - Removed the old npm install -g npm@latest hack from provenance.yml since Node 24 ships with a modern npm. --- .github/workflows/ci.yml | 288 ++++++++++++++++++++++- .github/workflows/claude-auto-review.yml | 17 -- .github/workflows/claude.yml | 24 -- .github/workflows/e2e-tests.yml | 82 ++++++- .github/workflows/provenance.yml | 95 +++++++- .github/workflows/socket-auto-pr.yml | 30 --- 6 files changed, 451 insertions(+), 85 deletions(-) delete mode 100644 .github/workflows/claude-auto-review.yml delete mode 100644 .github/workflows/claude.yml delete mode 100644 .github/workflows/socket-auto-pr.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a9a24204..768c63ec6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,9 +14,135 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: SocketDev/socket-registry/.github/actions/setup-and-install@51be85d39d3b4a42dd9d4712948b9d30a2e04794 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Install zizmor + shell: bash + run: | # zizmor: ignore[github-env] + ZIZMOR_VERSION="1.23.1" + ZIZMOR_DIR="${RUNNER_TEMP:-/tmp}/zizmor-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="zizmor-x86_64-unknown-linux-gnu.tar.gz" ; EXPECTED_SHA256="67a8df0a14352dd81882e14876653d097b99b0f4f6b6fe798edc0320cff27aff" ;; + Linux-aarch64) ASSET="zizmor-aarch64-unknown-linux-gnu.tar.gz" ; EXPECTED_SHA256="3725d7cd7102e4d70827186389f7d5930b6878232930d0a3eb058d7e5b47e658" ;; + Darwin-x86_64) ASSET="zizmor-x86_64-apple-darwin.tar.gz" ; EXPECTED_SHA256="89d5ed42081dd9d0433a10b7545fac42b35f1f030885c278b9712b32c66f2597" ;; + Darwin-arm64) ASSET="zizmor-aarch64-apple-darwin.tar.gz" ; EXPECTED_SHA256="2632561b974c69f952258c1ab4b7432d5c7f92e555704155c3ac28a2910bd717" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="zizmor-x86_64-pc-windows-msvc.zip" ; EXPECTED_SHA256="33c2293ff02834720dd7cd8b47348aafb2e95a19bdc993c0ecaca9c804ade92a" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + ZIZMOR_BIN="$ZIZMOR_DIR/zizmor" + [[ "$ASSET" == *.zip ]] && ZIZMOR_BIN="$ZIZMOR_DIR/zizmor.exe" + if [ ! -x "$ZIZMOR_BIN" ]; then + mkdir -p "$ZIZMOR_DIR" + DOWNLOAD_URL="https://github.com/woodruffw/zizmor/releases/download/v${ZIZMOR_VERSION}/${ASSET}" + DOWNLOAD_FILE="${ZIZMOR_DIR}/${ASSET}" + curl -fsSL -o "$DOWNLOAD_FILE" "$DOWNLOAD_URL" + ACTUAL_SHA256="$(shasum -a 256 "$DOWNLOAD_FILE" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + exit 1 + fi + if [[ "$ASSET" == *.zip ]]; then + unzip -qo "$DOWNLOAD_FILE" -d "$ZIZMOR_DIR" + else + tar xzf "$DOWNLOAD_FILE" -C "$ZIZMOR_DIR" + fi + rm -f "$DOWNLOAD_FILE" + chmod +x "$ZIZMOR_BIN" + fi + echo "$ZIZMOR_DIR" >> "${GITHUB_PATH:-/dev/null}" + + - name: Audit GitHub Actions + shell: bash + env: + GITHUB_TOKEN: ${{ github.token }} + run: | + if [ -d .github ]; then + zizmor .github --gh-token "${GITHUB_TOKEN}" --min-severity medium + fi + + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 22 + cache: pnpm + + - name: Download sfw-free + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | # zizmor: ignore[github-env] + SFW_DIR="${RUNNER_TEMP:-/tmp}/sfw-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="sfw-free-linux-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff" ;; + Linux-aarch64) ASSET="sfw-free-linux-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1" ;; + Darwin-x86_64) ASSET="sfw-free-macos-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="724ccea19d847b79db8cc8e38f5f18ce2dd32336007f42b11bed7d2e5f4a2566" ;; + Darwin-arm64) ASSET="sfw-free-macos-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="bf1616fc44ac49f1cb2067fedfa127a3ae65d6ec6d634efbb3098cfa355e5555" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="sfw-free-windows-x86_64.exe" ; SFW_BIN="$SFW_DIR/sfw.exe" ; EXPECTED_SHA256="c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + if [ ! -x "$SFW_BIN" ]; then + mkdir -p "$SFW_DIR" + DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ + --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" + curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" + ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$SFW_BIN" + exit 1 + fi + chmod +x "$SFW_BIN" + fi + echo "SFW_BIN=$SFW_BIN" >> "${GITHUB_ENV:-/dev/null}" + + - name: Create sfw shims + shell: bash + run: | # zizmor: ignore[github-env] + SHIM_DIR="${RUNNER_TEMP:-/tmp}/sfw-shim" + rm -rf "$SHIM_DIR" + mkdir -p "$SHIM_DIR" + IS_WINDOWS=false + [[ "$OSTYPE" == msys* || "$OSTYPE" == cygwin* ]] && IS_WINDOWS=true + msys_to_win_path() { + if $IS_WINDOWS && [[ "$1" =~ ^/([a-zA-Z])/(.*) ]]; then + echo "${BASH_REMATCH[1]^^}:\\${BASH_REMATCH[2]//\//\\}" + else + echo "$1" + fi + } + strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } + CLEAN_PATH="$(strip_shim_dir)" + for CMD in npm yarn pnpm pip uv cargo; do + REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" + [ -z "$REAL" ] && continue + REAL="$(msys_to_win_path "$REAL")" + printf '%s\n' \ + '#!/bin/bash' \ + "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ + > "$SHIM_DIR/$CMD" + chmod +x "$SHIM_DIR/$CMD" + if $IS_WINDOWS; then + printf '@echo off\r\nset "PATH=;%%PATH%%;"\r\nset "PATH=%%PATH:;%s;=;%%"\r\nset "PATH=%%PATH:~1,-1%%"\r\n"%s" "%s" %%*\r\n' \ + "$SHIM_DIR" "$SFW_BIN" "$REAL" > "$SHIM_DIR/$CMD.cmd" + fi + done + echo "$SHIM_DIR" >> "${GITHUB_PATH:-/dev/null}" + echo "SFW_SHIM_DIR=$SHIM_DIR" >> "${GITHUB_ENV:-/dev/null}" + + - name: Install dependencies + run: pnpm install --loglevel error - name: Lint run: pnpm check:lint @@ -25,9 +151,87 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: SocketDev/socket-registry/.github/actions/setup-and-install@51be85d39d3b4a42dd9d4712948b9d30a2e04794 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 22 + cache: pnpm + + - name: Download sfw-free + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | # zizmor: ignore[github-env] + SFW_DIR="${RUNNER_TEMP:-/tmp}/sfw-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="sfw-free-linux-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff" ;; + Linux-aarch64) ASSET="sfw-free-linux-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1" ;; + Darwin-x86_64) ASSET="sfw-free-macos-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="724ccea19d847b79db8cc8e38f5f18ce2dd32336007f42b11bed7d2e5f4a2566" ;; + Darwin-arm64) ASSET="sfw-free-macos-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="bf1616fc44ac49f1cb2067fedfa127a3ae65d6ec6d634efbb3098cfa355e5555" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="sfw-free-windows-x86_64.exe" ; SFW_BIN="$SFW_DIR/sfw.exe" ; EXPECTED_SHA256="c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + if [ ! -x "$SFW_BIN" ]; then + mkdir -p "$SFW_DIR" + DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ + --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" + curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" + ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$SFW_BIN" + exit 1 + fi + chmod +x "$SFW_BIN" + fi + echo "SFW_BIN=$SFW_BIN" >> "${GITHUB_ENV:-/dev/null}" + + - name: Create sfw shims + shell: bash + run: | # zizmor: ignore[github-env] + SHIM_DIR="${RUNNER_TEMP:-/tmp}/sfw-shim" + rm -rf "$SHIM_DIR" + mkdir -p "$SHIM_DIR" + IS_WINDOWS=false + [[ "$OSTYPE" == msys* || "$OSTYPE" == cygwin* ]] && IS_WINDOWS=true + msys_to_win_path() { + if $IS_WINDOWS && [[ "$1" =~ ^/([a-zA-Z])/(.*) ]]; then + echo "${BASH_REMATCH[1]^^}:\\${BASH_REMATCH[2]//\//\\}" + else + echo "$1" + fi + } + strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } + CLEAN_PATH="$(strip_shim_dir)" + for CMD in npm yarn pnpm pip uv cargo; do + REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" + [ -z "$REAL" ] && continue + REAL="$(msys_to_win_path "$REAL")" + printf '%s\n' \ + '#!/bin/bash' \ + "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ + > "$SHIM_DIR/$CMD" + chmod +x "$SHIM_DIR/$CMD" + if $IS_WINDOWS; then + printf '@echo off\r\nset "PATH=;%%PATH%%;"\r\nset "PATH=%%PATH:;%s;=;%%"\r\nset "PATH=%%PATH:~1,-1%%"\r\n"%s" "%s" %%*\r\n' \ + "$SHIM_DIR" "$SFW_BIN" "$REAL" > "$SHIM_DIR/$CMD.cmd" + fi + done + echo "$SHIM_DIR" >> "${GITHUB_PATH:-/dev/null}" + echo "SFW_SHIM_DIR=$SHIM_DIR" >> "${GITHUB_ENV:-/dev/null}" + + - name: Install dependencies + run: pnpm install --loglevel error - name: Type check run: pnpm check:tsc @@ -41,9 +245,87 @@ jobs: node-version: [20, 22, 24] os: [ubuntu-latest] steps: - - uses: SocketDev/socket-registry/.github/actions/setup-and-install@51be85d39d3b4a42dd9d4712948b9d30a2e04794 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} + cache: pnpm + + - name: Download sfw-free + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | # zizmor: ignore[github-env] + SFW_DIR="${RUNNER_TEMP:-/tmp}/sfw-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="sfw-free-linux-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff" ;; + Linux-aarch64) ASSET="sfw-free-linux-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1" ;; + Darwin-x86_64) ASSET="sfw-free-macos-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="724ccea19d847b79db8cc8e38f5f18ce2dd32336007f42b11bed7d2e5f4a2566" ;; + Darwin-arm64) ASSET="sfw-free-macos-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="bf1616fc44ac49f1cb2067fedfa127a3ae65d6ec6d634efbb3098cfa355e5555" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="sfw-free-windows-x86_64.exe" ; SFW_BIN="$SFW_DIR/sfw.exe" ; EXPECTED_SHA256="c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + if [ ! -x "$SFW_BIN" ]; then + mkdir -p "$SFW_DIR" + DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ + --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" + curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" + ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$SFW_BIN" + exit 1 + fi + chmod +x "$SFW_BIN" + fi + echo "SFW_BIN=$SFW_BIN" >> "${GITHUB_ENV:-/dev/null}" + + - name: Create sfw shims + shell: bash + run: | # zizmor: ignore[github-env] + SHIM_DIR="${RUNNER_TEMP:-/tmp}/sfw-shim" + rm -rf "$SHIM_DIR" + mkdir -p "$SHIM_DIR" + IS_WINDOWS=false + [[ "$OSTYPE" == msys* || "$OSTYPE" == cygwin* ]] && IS_WINDOWS=true + msys_to_win_path() { + if $IS_WINDOWS && [[ "$1" =~ ^/([a-zA-Z])/(.*) ]]; then + echo "${BASH_REMATCH[1]^^}:\\${BASH_REMATCH[2]//\//\\}" + else + echo "$1" + fi + } + strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } + CLEAN_PATH="$(strip_shim_dir)" + for CMD in npm yarn pnpm pip uv cargo; do + REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" + [ -z "$REAL" ] && continue + REAL="$(msys_to_win_path "$REAL")" + printf '%s\n' \ + '#!/bin/bash' \ + "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ + > "$SHIM_DIR/$CMD" + chmod +x "$SHIM_DIR/$CMD" + if $IS_WINDOWS; then + printf '@echo off\r\nset "PATH=;%%PATH%%;"\r\nset "PATH=%%PATH:;%s;=;%%"\r\nset "PATH=%%PATH:~1,-1%%"\r\n"%s" "%s" %%*\r\n' \ + "$SHIM_DIR" "$SFW_BIN" "$REAL" > "$SHIM_DIR/$CMD.cmd" + fi + done + echo "$SHIM_DIR" >> "${GITHUB_PATH:-/dev/null}" + echo "SFW_SHIM_DIR=$SHIM_DIR" >> "${GITHUB_ENV:-/dev/null}" + + - name: Install dependencies + run: pnpm install --loglevel error - name: Build and run unit tests run: pnpm test-ci diff --git a/.github/workflows/claude-auto-review.yml b/.github/workflows/claude-auto-review.yml deleted file mode 100644 index 3c9208efe..000000000 --- a/.github/workflows/claude-auto-review.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Claude Auto Review - -on: - pull_request: - types: [opened] - workflow_dispatch: - -permissions: - contents: read - id-token: write - pull-requests: read - -jobs: - auto-review: - uses: SocketDev/socket-registry/.github/workflows/claude-auto-review.yml@main - secrets: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml deleted file mode 100644 index ebec7a215..000000000 --- a/.github/workflows/claude.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Claude Code - -on: - issue_comment: - types: [created] - pull_request_review_comment: - types: [created] - issues: - types: [opened, assigned] - pull_request_review: - types: [submitted] - workflow_dispatch: - -permissions: - contents: read - id-token: write - issues: write - pull-requests: write - -jobs: - claude: - uses: SocketDev/socket-registry/.github/workflows/claude.yml@main - secrets: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 8ffad2fe2..f5e88a338 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,9 +1,6 @@ name: E2E Tests on: - push: - branches: [main] - tags: ['*'] pull_request: branches: [main, v1.x] workflow_dispatch: @@ -22,10 +19,87 @@ jobs: os: [ubuntu-latest] # os: [ubuntu-latest, windows-latest] - Windows tests disbaled (see project https://linear.app/socketdev/project/autofixes-windows-support-fc2f2a45f759) steps: - - uses: SocketDev/socket-registry/.github/actions/setup-and-install@51be85d39d3b4a42dd9d4712948b9d30a2e04794 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} + - name: Download sfw-free + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | # zizmor: ignore[github-env] + SFW_DIR="${RUNNER_TEMP:-/tmp}/sfw-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="sfw-free-linux-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff" ;; + Linux-aarch64) ASSET="sfw-free-linux-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1" ;; + Darwin-x86_64) ASSET="sfw-free-macos-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="724ccea19d847b79db8cc8e38f5f18ce2dd32336007f42b11bed7d2e5f4a2566" ;; + Darwin-arm64) ASSET="sfw-free-macos-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="bf1616fc44ac49f1cb2067fedfa127a3ae65d6ec6d634efbb3098cfa355e5555" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="sfw-free-windows-x86_64.exe" ; SFW_BIN="$SFW_DIR/sfw.exe" ; EXPECTED_SHA256="c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + if [ ! -x "$SFW_BIN" ]; then + mkdir -p "$SFW_DIR" + DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ + --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" + curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" + ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$SFW_BIN" + exit 1 + fi + chmod +x "$SFW_BIN" + fi + echo "SFW_BIN=$SFW_BIN" >> "${GITHUB_ENV:-/dev/null}" + + - name: Create sfw shims + shell: bash + run: | # zizmor: ignore[github-env] + SHIM_DIR="${RUNNER_TEMP:-/tmp}/sfw-shim" + rm -rf "$SHIM_DIR" + mkdir -p "$SHIM_DIR" + IS_WINDOWS=false + [[ "$OSTYPE" == msys* || "$OSTYPE" == cygwin* ]] && IS_WINDOWS=true + msys_to_win_path() { + if $IS_WINDOWS && [[ "$1" =~ ^/([a-zA-Z])/(.*) ]]; then + echo "${BASH_REMATCH[1]^^}:\\${BASH_REMATCH[2]//\//\\}" + else + echo "$1" + fi + } + strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } + CLEAN_PATH="$(strip_shim_dir)" + for CMD in npm yarn pnpm pip uv cargo; do + REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" + [ -z "$REAL" ] && continue + REAL="$(msys_to_win_path "$REAL")" + printf '%s\n' \ + '#!/bin/bash' \ + "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ + > "$SHIM_DIR/$CMD" + chmod +x "$SHIM_DIR/$CMD" + if $IS_WINDOWS; then + printf '@echo off\r\nset "PATH=;%%PATH%%;"\r\nset "PATH=%%PATH:;%s;=;%%"\r\nset "PATH=%%PATH:~1,-1%%"\r\n"%s" "%s" %%*\r\n' \ + "$SHIM_DIR" "$SFW_BIN" "$REAL" > "$SHIM_DIR/$CMD.cmd" + fi + done + echo "$SHIM_DIR" >> "${GITHUB_PATH:-/dev/null}" + echo "SFW_SHIM_DIR=$SHIM_DIR" >> "${GITHUB_ENV:-/dev/null}" + + - name: Install dependencies + run: pnpm install --loglevel error + - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | sh diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index aee73c2fc..d088d2f8b 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -25,31 +25,112 @@ jobs: id-token: write steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: SocketDev/socket-registry/.github/actions/setup@1543e937143cf84e5161ad18c04cbd99c8a4c6d8 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: + persist-credentials: false + + - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: 24 + cache: pnpm + registry-url: https://registry.npmjs.org scope: '@socketsecurity' - - run: npm install -g npm@latest - - run: pnpm install + + - name: Download sfw-free + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | # zizmor: ignore[github-env] + SFW_DIR="${RUNNER_TEMP:-/tmp}/sfw-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="sfw-free-linux-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff" ;; + Linux-aarch64) ASSET="sfw-free-linux-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1" ;; + Darwin-x86_64) ASSET="sfw-free-macos-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="724ccea19d847b79db8cc8e38f5f18ce2dd32336007f42b11bed7d2e5f4a2566" ;; + Darwin-arm64) ASSET="sfw-free-macos-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="bf1616fc44ac49f1cb2067fedfa127a3ae65d6ec6d634efbb3098cfa355e5555" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="sfw-free-windows-x86_64.exe" ; SFW_BIN="$SFW_DIR/sfw.exe" ; EXPECTED_SHA256="c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + if [ ! -x "$SFW_BIN" ]; then + mkdir -p "$SFW_DIR" + DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ + --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" + curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" + ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$SFW_BIN" + exit 1 + fi + chmod +x "$SFW_BIN" + fi + echo "SFW_BIN=$SFW_BIN" >> "${GITHUB_ENV:-/dev/null}" + + - name: Create sfw shims + shell: bash + run: | # zizmor: ignore[github-env] + SHIM_DIR="${RUNNER_TEMP:-/tmp}/sfw-shim" + rm -rf "$SHIM_DIR" + mkdir -p "$SHIM_DIR" + IS_WINDOWS=false + [[ "$OSTYPE" == msys* || "$OSTYPE" == cygwin* ]] && IS_WINDOWS=true + msys_to_win_path() { + if $IS_WINDOWS && [[ "$1" =~ ^/([a-zA-Z])/(.*) ]]; then + echo "${BASH_REMATCH[1]^^}:\\${BASH_REMATCH[2]//\//\\}" + else + echo "$1" + fi + } + strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } + CLEAN_PATH="$(strip_shim_dir)" + for CMD in npm yarn pnpm pip uv cargo; do + REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" + [ -z "$REAL" ] && continue + REAL="$(msys_to_win_path "$REAL")" + printf '%s\n' \ + '#!/bin/bash' \ + "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ + > "$SHIM_DIR/$CMD" + chmod +x "$SHIM_DIR/$CMD" + if $IS_WINDOWS; then + printf '@echo off\r\nset "PATH=;%%PATH%%;"\r\nset "PATH=%%PATH:;%s;=;%%"\r\nset "PATH=%%PATH:~1,-1%%"\r\n"%s" "%s" %%*\r\n' \ + "$SHIM_DIR" "$SFW_BIN" "$REAL" > "$SHIM_DIR/$CMD.cmd" + fi + done + echo "$SHIM_DIR" >> "${GITHUB_PATH:-/dev/null}" + echo "SFW_SHIM_DIR=$SHIM_DIR" >> "${GITHUB_ENV:-/dev/null}" + + - name: Install dependencies + run: pnpm install --loglevel error + - run: INLINED_SOCKET_CLI_PUBLISHED_BUILD=1 pnpm run build:dist - - run: npm publish --provenance --access public --tag ${{ inputs.dist-tag }} + - run: npm publish --provenance --access public --tag "${NPM_DIST_TAG}" continue-on-error: true env: + NPM_DIST_TAG: ${{ inputs.dist-tag }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} SOCKET_CLI_DEBUG: ${{ inputs.debug }} - run: INLINED_SOCKET_CLI_PUBLISHED_BUILD=1 INLINED_SOCKET_CLI_LEGACY_BUILD=1 pnpm run build:dist env: SOCKET_CLI_DEBUG: ${{ inputs.debug }} - - run: npm publish --provenance --access public --tag ${{ inputs.dist-tag }} + - run: npm publish --provenance --access public --tag "${NPM_DIST_TAG}" continue-on-error: true env: + NPM_DIST_TAG: ${{ inputs.dist-tag }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} SOCKET_CLI_DEBUG: ${{ inputs.debug }} - run: INLINED_SOCKET_CLI_PUBLISHED_BUILD=1 INLINED_SOCKET_CLI_SENTRY_BUILD=1 pnpm run build:dist env: SOCKET_CLI_DEBUG: ${{ inputs.debug }} - - run: npm publish --provenance --access public --tag ${{ inputs.dist-tag }} + - run: npm publish --provenance --access public --tag "${NPM_DIST_TAG}" continue-on-error: true env: + NPM_DIST_TAG: ${{ inputs.dist-tag }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} SOCKET_CLI_DEBUG: ${{ inputs.debug }} diff --git a/.github/workflows/socket-auto-pr.yml b/.github/workflows/socket-auto-pr.yml deleted file mode 100644 index ed775a058..000000000 --- a/.github/workflows/socket-auto-pr.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Socket Fix Auto Pull Request - -on: - schedule: - - cron: '0 0 * * *' # Run daily at midnight UTC - - cron: '0 12 * * *' # Run daily at noon UTC - workflow_dispatch: - inputs: - debug: - description: 'Enable debug output' - required: false - default: '0' - type: string - options: - - '0' - - '1' - -permissions: - contents: write - pull-requests: write - -jobs: - socket-auto-pr: - uses: SocketDev/socket-registry/.github/workflows/socket-auto-pr.yml@main - with: - debug: ${{ inputs.debug }} - autopilot: true - secrets: - socket_cli_api_token: ${{ secrets.SOCKET_CLI_API_TOKEN }} - gh_token: ${{ secrets.GITHUB_TOKEN }} From da170bc3798083e5953b53ecb9164e12fe585418 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 11:01:22 -0400 Subject: [PATCH 02/10] fix(ci): replace pnpm/action-setup with inline binary download Replace the pnpm/action-setup third-party action with a direct download of the pnpm standalone binary from GitHub releases, matching the same pattern used for sfw-free and zizmor. The pnpm binary (v10.33.0) is downloaded, checksum-verified against a SHA-256 hash, and symlinked as "pnpm" on PATH. This removes the last third-party action dependency beyond actions/checkout and actions/setup-node. --- .github/workflows/ci.yml | 96 +++++++++++++++++++++++++++++++- .github/workflows/e2e-tests.yml | 32 ++++++++++- .github/workflows/provenance.yml | 32 ++++++++++- 3 files changed, 155 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 768c63ec6..2b6eb790d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,37 @@ jobs: zizmor .github --gh-token "${GITHUB_TOKEN}" --min-severity medium fi - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + - name: Install pnpm + shell: bash + run: | # zizmor: ignore[github-env] + PNPM_VERSION="10.33.0" + PNPM_DIR="${RUNNER_TEMP:-/tmp}/pnpm-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="pnpm-linux-x64" ; EXPECTED_SHA256="8d4e8f7d778e8ac482022e2577011706a872542f6f6f233e795a4d9f978ea8b5" ;; + Linux-aarch64) ASSET="pnpm-linux-arm64" ; EXPECTED_SHA256="06755ad2817548b84317d857d5c8003dc6e9e28416a3ea7467256c49ab400d48" ;; + Darwin-x86_64) ASSET="pnpm-macos-x64" ; EXPECTED_SHA256="c31e29554b0e3f4e03f4617195c949595e4dca36085922003de4896c3ca4057d" ;; + Darwin-arm64) ASSET="pnpm-macos-arm64" ; EXPECTED_SHA256="ed8a1f140f4de457b01ebe0be3ae28e9a7e28863315dcd53d22ff1e5a32d63ae" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="pnpm-win-x64.exe" ; EXPECTED_SHA256="afc96009dc39fe23a835d65192049e6a995f342496b175585dc2beda7d42d33f" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + PNPM_BIN="$PNPM_DIR/$ASSET" + if [ ! -x "$PNPM_BIN" ]; then + mkdir -p "$PNPM_DIR" + curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" + ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$PNPM_BIN" + exit 1 + fi + chmod +x "$PNPM_BIN" + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi + echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: @@ -155,7 +185,37 @@ jobs: with: persist-credentials: false - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + - name: Install pnpm + shell: bash + run: | # zizmor: ignore[github-env] + PNPM_VERSION="10.33.0" + PNPM_DIR="${RUNNER_TEMP:-/tmp}/pnpm-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="pnpm-linux-x64" ; EXPECTED_SHA256="8d4e8f7d778e8ac482022e2577011706a872542f6f6f233e795a4d9f978ea8b5" ;; + Linux-aarch64) ASSET="pnpm-linux-arm64" ; EXPECTED_SHA256="06755ad2817548b84317d857d5c8003dc6e9e28416a3ea7467256c49ab400d48" ;; + Darwin-x86_64) ASSET="pnpm-macos-x64" ; EXPECTED_SHA256="c31e29554b0e3f4e03f4617195c949595e4dca36085922003de4896c3ca4057d" ;; + Darwin-arm64) ASSET="pnpm-macos-arm64" ; EXPECTED_SHA256="ed8a1f140f4de457b01ebe0be3ae28e9a7e28863315dcd53d22ff1e5a32d63ae" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="pnpm-win-x64.exe" ; EXPECTED_SHA256="afc96009dc39fe23a835d65192049e6a995f342496b175585dc2beda7d42d33f" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + PNPM_BIN="$PNPM_DIR/$ASSET" + if [ ! -x "$PNPM_BIN" ]; then + mkdir -p "$PNPM_DIR" + curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" + ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$PNPM_BIN" + exit 1 + fi + chmod +x "$PNPM_BIN" + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi + echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: @@ -249,7 +309,37 @@ jobs: with: persist-credentials: false - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + - name: Install pnpm + shell: bash + run: | # zizmor: ignore[github-env] + PNPM_VERSION="10.33.0" + PNPM_DIR="${RUNNER_TEMP:-/tmp}/pnpm-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="pnpm-linux-x64" ; EXPECTED_SHA256="8d4e8f7d778e8ac482022e2577011706a872542f6f6f233e795a4d9f978ea8b5" ;; + Linux-aarch64) ASSET="pnpm-linux-arm64" ; EXPECTED_SHA256="06755ad2817548b84317d857d5c8003dc6e9e28416a3ea7467256c49ab400d48" ;; + Darwin-x86_64) ASSET="pnpm-macos-x64" ; EXPECTED_SHA256="c31e29554b0e3f4e03f4617195c949595e4dca36085922003de4896c3ca4057d" ;; + Darwin-arm64) ASSET="pnpm-macos-arm64" ; EXPECTED_SHA256="ed8a1f140f4de457b01ebe0be3ae28e9a7e28863315dcd53d22ff1e5a32d63ae" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="pnpm-win-x64.exe" ; EXPECTED_SHA256="afc96009dc39fe23a835d65192049e6a995f342496b175585dc2beda7d42d33f" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + PNPM_BIN="$PNPM_DIR/$ASSET" + if [ ! -x "$PNPM_BIN" ]; then + mkdir -p "$PNPM_DIR" + curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" + ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$PNPM_BIN" + exit 1 + fi + chmod +x "$PNPM_BIN" + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi + echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index f5e88a338..a0b54b2ba 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -23,7 +23,37 @@ jobs: with: persist-credentials: false - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + - name: Install pnpm + shell: bash + run: | # zizmor: ignore[github-env] + PNPM_VERSION="10.33.0" + PNPM_DIR="${RUNNER_TEMP:-/tmp}/pnpm-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="pnpm-linux-x64" ; EXPECTED_SHA256="8d4e8f7d778e8ac482022e2577011706a872542f6f6f233e795a4d9f978ea8b5" ;; + Linux-aarch64) ASSET="pnpm-linux-arm64" ; EXPECTED_SHA256="06755ad2817548b84317d857d5c8003dc6e9e28416a3ea7467256c49ab400d48" ;; + Darwin-x86_64) ASSET="pnpm-macos-x64" ; EXPECTED_SHA256="c31e29554b0e3f4e03f4617195c949595e4dca36085922003de4896c3ca4057d" ;; + Darwin-arm64) ASSET="pnpm-macos-arm64" ; EXPECTED_SHA256="ed8a1f140f4de457b01ebe0be3ae28e9a7e28863315dcd53d22ff1e5a32d63ae" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="pnpm-win-x64.exe" ; EXPECTED_SHA256="afc96009dc39fe23a835d65192049e6a995f342496b175585dc2beda7d42d33f" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + PNPM_BIN="$PNPM_DIR/$ASSET" + if [ ! -x "$PNPM_BIN" ]; then + mkdir -p "$PNPM_DIR" + curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" + ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$PNPM_BIN" + exit 1 + fi + chmod +x "$PNPM_BIN" + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi + echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index d088d2f8b..58ed41012 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -29,7 +29,37 @@ jobs: with: persist-credentials: false - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + - name: Install pnpm + shell: bash + run: | # zizmor: ignore[github-env] + PNPM_VERSION="10.33.0" + PNPM_DIR="${RUNNER_TEMP:-/tmp}/pnpm-bin" + KERNEL="$(uname -s | cut -d- -f1)" + ARCH="$(uname -m)" + case "${KERNEL}-${ARCH}" in + Linux-x86_64) ASSET="pnpm-linux-x64" ; EXPECTED_SHA256="8d4e8f7d778e8ac482022e2577011706a872542f6f6f233e795a4d9f978ea8b5" ;; + Linux-aarch64) ASSET="pnpm-linux-arm64" ; EXPECTED_SHA256="06755ad2817548b84317d857d5c8003dc6e9e28416a3ea7467256c49ab400d48" ;; + Darwin-x86_64) ASSET="pnpm-macos-x64" ; EXPECTED_SHA256="c31e29554b0e3f4e03f4617195c949595e4dca36085922003de4896c3ca4057d" ;; + Darwin-arm64) ASSET="pnpm-macos-arm64" ; EXPECTED_SHA256="ed8a1f140f4de457b01ebe0be3ae28e9a7e28863315dcd53d22ff1e5a32d63ae" ;; + MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="pnpm-win-x64.exe" ; EXPECTED_SHA256="afc96009dc39fe23a835d65192049e6a995f342496b175585dc2beda7d42d33f" ;; + *) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;; + esac + PNPM_BIN="$PNPM_DIR/$ASSET" + if [ ! -x "$PNPM_BIN" ]; then + mkdir -p "$PNPM_DIR" + curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" + ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then + echo "Checksum mismatch for ${ASSET}!" >&2 + echo " Expected: ${EXPECTED_SHA256}" >&2 + echo " Actual: ${ACTUAL_SHA256}" >&2 + rm -f "$PNPM_BIN" + exit 1 + fi + chmod +x "$PNPM_BIN" + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi + echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: From 1340ac6ffa3f44ff1000658e0e705c79d8cb0d63 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 11:04:00 -0400 Subject: [PATCH 03/10] chore: add packageManager field for pnpm 10.33.0 Aligns socket-cli with all other Socket repos which already declare packageManager in package.json. This lets corepack and tooling auto- detect the correct pnpm version. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 69fd7bad5..e126a4202 100644 --- a/package.json +++ b/package.json @@ -196,6 +196,7 @@ "node": ">=18", "pnpm": ">=10.16.0" }, + "packageManager": "pnpm@10.33.0", "files": [ "bin/**", "dist/**", From e25f21a91216e0613ee2bc9272d8ad2b9b51f2cf Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 11:10:29 -0400 Subject: [PATCH 04/10] fix(ci): allow zizmor warnings (exit 13) in audit step Zizmor exits 13 for warnings-only and 14 for errors. The secrets-outside-env warnings are expected (requires GitHub environment configuration) so we allow exit code 13 while still failing on actual errors. --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b6eb790d..b401960a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,11 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: | if [ -d .github ]; then - zizmor .github --gh-token "${GITHUB_TOKEN}" --min-severity medium + # Exit 0 = clean, 13 = warnings only, 14+ = errors. + zizmor .github --gh-token "${GITHUB_TOKEN}" --min-severity medium || { + exit_code=$? + if [ "$exit_code" -ne 13 ]; then exit "$exit_code"; fi + } fi - name: Install pnpm From 065df8283c89068994b88b6945cba98ab1c0c37d Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 12:19:12 -0400 Subject: [PATCH 05/10] chore: use Node 25.9.0 for lint, typecheck, and provenance --- .github/workflows/ci.yml | 4 ++-- .github/workflows/provenance.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b401960a1..ddc202f39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version: 22 + node-version: 25.9.0 cache: pnpm - name: Download sfw-free @@ -223,7 +223,7 @@ jobs: - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version: 22 + node-version: 25.9.0 cache: pnpm - name: Download sfw-free diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 58ed41012..49a6a4629 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -63,7 +63,7 @@ jobs: - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version: 24 + node-version: 25.9.0 cache: pnpm registry-url: https://registry.npmjs.org scope: '@socketsecurity' From 7c6bdcedb32a38e92605bf4781adb46834182a03 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 12:25:56 -0400 Subject: [PATCH 06/10] chore: add sfw-free ecosystem docs link to shim loops --- .github/workflows/ci.yml | 3 +++ .github/workflows/e2e-tests.yml | 1 + .github/workflows/provenance.yml | 1 + 3 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ddc202f39..8e7ace35b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,6 +157,7 @@ jobs: } strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } CLEAN_PATH="$(strip_shim_dir)" + # https://docs.socket.dev/docs/socket-firewall-free#what-ecosystems-and-package-managers-are-supported for CMD in npm yarn pnpm pip uv cargo; do REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" [ -z "$REAL" ] && continue @@ -276,6 +277,7 @@ jobs: } strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } CLEAN_PATH="$(strip_shim_dir)" + # https://docs.socket.dev/docs/socket-firewall-free#what-ecosystems-and-package-managers-are-supported for CMD in npm yarn pnpm pip uv cargo; do REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" [ -z "$REAL" ] && continue @@ -400,6 +402,7 @@ jobs: } strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } CLEAN_PATH="$(strip_shim_dir)" + # https://docs.socket.dev/docs/socket-firewall-free#what-ecosystems-and-package-managers-are-supported for CMD in npm yarn pnpm pip uv cargo; do REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" [ -z "$REAL" ] && continue diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index a0b54b2ba..c886d99a0 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -109,6 +109,7 @@ jobs: } strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } CLEAN_PATH="$(strip_shim_dir)" + # https://docs.socket.dev/docs/socket-firewall-free#what-ecosystems-and-package-managers-are-supported for CMD in npm yarn pnpm pip uv cargo; do REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" [ -z "$REAL" ] && continue diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 49a6a4629..b3abdaeb0 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -118,6 +118,7 @@ jobs: } strip_shim_dir() { echo "$PATH" | tr ':' '\n' | grep -vxF "$SHIM_DIR" | paste -sd: -; } CLEAN_PATH="$(strip_shim_dir)" + # https://docs.socket.dev/docs/socket-firewall-free#what-ecosystems-and-package-managers-are-supported for CMD in npm yarn pnpm pip uv cargo; do REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)" [ -z "$REAL" ] && continue From 13fc68029b1657951a93b7e30cc14b491645d522 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 12:38:46 -0400 Subject: [PATCH 07/10] fix(ci): work around sfw-free missing GIT_SSL_CAINFO --- .github/workflows/ci.yml | 3 +++ .github/workflows/e2e-tests.yml | 1 + .github/workflows/provenance.yml | 1 + 3 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e7ace35b..70727a2f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,6 +165,7 @@ jobs: printf '%s\n' \ '#!/bin/bash' \ "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + 'export GIT_SSL_NO_VERIFY=true # Workaround: sfw-free does not yet set GIT_SSL_CAINFO.' \ "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ > "$SHIM_DIR/$CMD" chmod +x "$SHIM_DIR/$CMD" @@ -285,6 +286,7 @@ jobs: printf '%s\n' \ '#!/bin/bash' \ "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + 'export GIT_SSL_NO_VERIFY=true # Workaround: sfw-free does not yet set GIT_SSL_CAINFO.' \ "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ > "$SHIM_DIR/$CMD" chmod +x "$SHIM_DIR/$CMD" @@ -410,6 +412,7 @@ jobs: printf '%s\n' \ '#!/bin/bash' \ "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + 'export GIT_SSL_NO_VERIFY=true # Workaround: sfw-free does not yet set GIT_SSL_CAINFO.' \ "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ > "$SHIM_DIR/$CMD" chmod +x "$SHIM_DIR/$CMD" diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index c886d99a0..6b59aa839 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -117,6 +117,7 @@ jobs: printf '%s\n' \ '#!/bin/bash' \ "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + 'export GIT_SSL_NO_VERIFY=true # Workaround: sfw-free does not yet set GIT_SSL_CAINFO.' \ "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ > "$SHIM_DIR/$CMD" chmod +x "$SHIM_DIR/$CMD" diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index b3abdaeb0..1b75e6c8f 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -126,6 +126,7 @@ jobs: printf '%s\n' \ '#!/bin/bash' \ "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"" \ + 'export GIT_SSL_NO_VERIFY=true # Workaround: sfw-free does not yet set GIT_SSL_CAINFO.' \ "exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"" \ > "$SHIM_DIR/$CMD" chmod +x "$SHIM_DIR/$CMD" From 18c1a9b93d2454174facfc8c49bad97c7c51be14 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 13:10:00 -0400 Subject: [PATCH 08/10] fix(ci): use sha256sum with shasum fallback for Windows compatibility --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/e2e-tests.yml | 4 ++-- .github/workflows/provenance.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70727a2f3..4d4ae525f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: DOWNLOAD_URL="https://github.com/woodruffw/zizmor/releases/download/v${ZIZMOR_VERSION}/${ASSET}" DOWNLOAD_FILE="${ZIZMOR_DIR}/${ASSET}" curl -fsSL -o "$DOWNLOAD_FILE" "$DOWNLOAD_URL" - ACTUAL_SHA256="$(shasum -a 256 "$DOWNLOAD_FILE" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$DOWNLOAD_FILE" 2>/dev/null || shasum -a 256 "$DOWNLOAD_FILE") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -89,7 +89,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -128,7 +128,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -210,7 +210,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -249,7 +249,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -336,7 +336,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -375,7 +375,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 6b59aa839..fb98da63e 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -42,7 +42,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -80,7 +80,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 1b75e6c8f..85c9dfdee 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -48,7 +48,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$(shasum -a 256 "$PNPM_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -89,7 +89,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$(shasum -a 256 "$SFW_BIN" | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 From e11aafc3210604a1352fd5ab07fa9cbe264045f4 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 13:29:02 -0400 Subject: [PATCH 09/10] fix(ci): strip backslash prefix from sha256sum output on Windows --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/e2e-tests.yml | 4 ++-- .github/workflows/provenance.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d4ae525f..375ef380e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: DOWNLOAD_URL="https://github.com/woodruffw/zizmor/releases/download/v${ZIZMOR_VERSION}/${ASSET}" DOWNLOAD_FILE="${ZIZMOR_DIR}/${ASSET}" curl -fsSL -o "$DOWNLOAD_FILE" "$DOWNLOAD_URL" - ACTUAL_SHA256="$( (sha256sum "$DOWNLOAD_FILE" 2>/dev/null || shasum -a 256 "$DOWNLOAD_FILE") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$DOWNLOAD_FILE" 2>/dev/null || shasum -a 256 "$DOWNLOAD_FILE") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -89,7 +89,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -128,7 +128,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -210,7 +210,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -249,7 +249,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -336,7 +336,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -375,7 +375,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index fb98da63e..38b9a5e7b 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -42,7 +42,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -80,7 +80,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 85c9dfdee..655ccae93 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -48,7 +48,7 @@ jobs: if [ ! -x "$PNPM_BIN" ]; then mkdir -p "$PNPM_DIR" curl -fsSL -o "$PNPM_BIN" "https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/${ASSET}" - ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$PNPM_BIN" 2>/dev/null || shasum -a 256 "$PNPM_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 @@ -89,7 +89,7 @@ jobs: DOWNLOAD_URL="$(gh api repos/SocketDev/sfw-free/releases/latest \ --jq ".assets[] | select(.name == \"$ASSET\") | .browser_download_url")" curl -fsSL -o "$SFW_BIN" "$DOWNLOAD_URL" - ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1)" + ACTUAL_SHA256="$( (sha256sum "$SFW_BIN" 2>/dev/null || shasum -a 256 "$SFW_BIN") | cut -d' ' -f1 | tr -d '\\')" if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "Checksum mismatch for ${ASSET}!" >&2 echo " Expected: ${EXPECTED_SHA256}" >&2 From dfa83984f1c8326e7c6d2a79885ba18b18c20c6d Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 8 Apr 2026 13:48:22 -0400 Subject: [PATCH 10/10] fix(ci): copy pnpm binary as pnpm.exe on Windows instead of symlink --- .github/workflows/ci.yml | 21 ++++++++++++++++++--- .github/workflows/e2e-tests.yml | 7 ++++++- .github/workflows/provenance.yml | 7 ++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 375ef380e..7c3a5886c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,7 +98,12 @@ jobs: exit 1 fi chmod +x "$PNPM_BIN" - ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + # Create pnpm alias. Windows needs a .exe copy; Unix uses a symlink. + if [[ "$ASSET" == *.exe ]]; then + cp "$PNPM_BIN" "$PNPM_DIR/pnpm.exe" + else + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi fi echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" @@ -219,7 +224,12 @@ jobs: exit 1 fi chmod +x "$PNPM_BIN" - ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + # Create pnpm alias. Windows needs a .exe copy; Unix uses a symlink. + if [[ "$ASSET" == *.exe ]]; then + cp "$PNPM_BIN" "$PNPM_DIR/pnpm.exe" + else + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi fi echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" @@ -345,7 +355,12 @@ jobs: exit 1 fi chmod +x "$PNPM_BIN" - ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + # Create pnpm alias. Windows needs a .exe copy; Unix uses a symlink. + if [[ "$ASSET" == *.exe ]]; then + cp "$PNPM_BIN" "$PNPM_DIR/pnpm.exe" + else + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi fi echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 38b9a5e7b..e9aa2294a 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -51,7 +51,12 @@ jobs: exit 1 fi chmod +x "$PNPM_BIN" - ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + # Create pnpm alias. Windows needs a .exe copy; Unix uses a symlink. + if [[ "$ASSET" == *.exe ]]; then + cp "$PNPM_BIN" "$PNPM_DIR/pnpm.exe" + else + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi fi echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}" diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 655ccae93..796491618 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -57,7 +57,12 @@ jobs: exit 1 fi chmod +x "$PNPM_BIN" - ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + # Create pnpm alias. Windows needs a .exe copy; Unix uses a symlink. + if [[ "$ASSET" == *.exe ]]; then + cp "$PNPM_BIN" "$PNPM_DIR/pnpm.exe" + else + ln -sf "$PNPM_BIN" "$PNPM_DIR/pnpm" + fi fi echo "$PNPM_DIR" >> "${GITHUB_PATH:-/dev/null}"