Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/actions/install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: 'Install'
description: 'Install pnpm dependencies (sfw shims are set up by the setup action)'

inputs:
frozen-lockfile:
description: 'Pass --frozen-lockfile to pnpm install'
required: false
default: 'false'
working-directory:
description: 'Working directory'
required: false
default: '.'

runs:
using: 'composite'
steps:
- name: Install dependencies
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
if [ -z "$SFW_BIN" ] || [ ! -x "$SFW_BIN" ]; then
echo "Error: sfw is not installed — run SocketDev/workflows/.github/actions/setup first" >&2
exit 1
fi
pnpm install --loglevel error ${{ inputs.frozen-lockfile == 'true' && '--frozen-lockfile' || '' }}
57 changes: 57 additions & 0 deletions .github/actions/setup-and-install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: 'Setup and Install'
description: 'Aggregate: checkout + setup environment + install dependencies'

# Dependencies:
# - actions/checkout@v6.0.2
# - SocketDev/workflows/.github/actions/setup
# - actions/setup-node@v6.3.0
# - SocketDev/workflows/.github/actions/install

inputs:
checkout:
description: 'Whether to checkout code'
required: false
default: 'true'
checkout-fetch-depth:
description: 'Number of commits to fetch (0 = full history)'
required: false
default: '100'
checkout-ref:
description: 'Git ref to checkout'
required: false
default: ''
node-version:
description: 'Node.js version to use'
required: false
default: '25.9.0'
socket-api-key:
description: 'Socket API key — when provided, uses sfw-enterprise instead of sfw-free'
required: false
default: ''
working-directory:
description: 'Working directory'
required: false
default: '.'

runs:
using: 'composite'
steps:
- name: Checkout
if: inputs.checkout == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: ${{ inputs.checkout-fetch-depth }}
ref: ${{ inputs.checkout-ref }}
path: ${{ inputs.working-directory != '.' && inputs.working-directory || '' }}
persist-credentials: false

- name: Setup environment
uses: SocketDev/workflows/.github/actions/setup@feat/setup-and-install-workflow # zizmor: ignore[unpinned-uses]
with:
node-version: ${{ inputs.node-version }}
socket-api-key: ${{ inputs.socket-api-key }}

- name: Install dependencies
uses: SocketDev/workflows/.github/actions/install@feat/setup-and-install-workflow # zizmor: ignore[unpinned-uses]
with:
working-directory: ${{ inputs.working-directory }}
171 changes: 171 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: 'Setup'
description: 'Setup Node.js, pnpm, and Socket firewall shims'

# Dependencies:
# - actions/setup-node@v6.3.0

inputs:
node-version:
description: 'Node.js version'
required: false
default: '25.9.0'
socket-api-key:
description: 'Socket API key — when provided, uses sfw-enterprise instead of sfw-free'
required: false
default: ''

runs:
using: 'composite'
steps:
- 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="$( (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
echo " Actual: ${ACTUAL_SHA256}" >&2
rm -f "$PNPM_BIN"
exit 1
fi
chmod +x "$PNPM_BIN"
# 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}"

- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ inputs.node-version }}

- name: Download sfw
shell: bash
env:
GH_TOKEN: ${{ github.token }}
SOCKET_API_KEY: ${{ inputs.socket-api-key }}
run: | # zizmor: ignore[github-env]
SFW_DIR="${RUNNER_TEMP:-/tmp}/sfw-bin"
KERNEL="$(uname -s | cut -d- -f1)"
ARCH="$(uname -m)"
USE_ENTERPRISE=false
if [ -n "$SOCKET_API_KEY" ]; then
USE_ENTERPRISE=true
fi
if $USE_ENTERPRISE; then
REPO="SocketDev/firewall-release"
case "${KERNEL}-${ARCH}" in
Linux-x86_64) ASSET="sfw-linux-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="9115b4ca8021eb173eb9e9c3627deb7f1066f8debd48c5c9d9f3caabb2a26a4b" ;;
Linux-aarch64) ASSET="sfw-linux-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="671270231617142404a1564e52672f79b806f9df3f232fcc7606329c0246da55" ;;
Darwin-x86_64) ASSET="sfw-macos-x86_64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="01d64d40effda35c31f8d8ee1fed1388aac0a11aba40d47fba8a36024b77500c" ;;
Darwin-arm64) ASSET="sfw-macos-arm64" ; SFW_BIN="$SFW_DIR/sfw" ; EXPECTED_SHA256="acad0b517601bb7408e2e611c9226f47dcccbd83333d7fc5157f1d32ed2b953d" ;;
MINGW64_NT-x86_64|MSYS_NT-x86_64) ASSET="sfw-windows-x86_64.exe" ; SFW_BIN="$SFW_DIR/sfw.exe" ; EXPECTED_SHA256="9a50e1ddaf038138c3f85418dc5df0113bbe6fc884f5abe158beaa9aea18d70a" ;;
*) echo "Unsupported platform: ${KERNEL}-${ARCH}" >&2; exit 1 ;;
esac
else
REPO="SocketDev/sfw-free"
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
fi
if [ ! -x "$SFW_BIN" ]; then
mkdir -p "$SFW_DIR"
DOWNLOAD_URL="$(gh api "repos/${REPO}/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 | tr -d '\\')"
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}"
echo "SFW_IS_ENTERPRISE=$USE_ENTERPRISE" >> "${GITHUB_ENV:-/dev/null}"
if $USE_ENTERPRISE; then
echo "SOCKET_API_KEY=$SOCKET_API_KEY" >> "${GITHUB_ENV:-/dev/null}"
fi

- name: Create sfw shims
shell: bash
run: | # zizmor: ignore[github-env]
# Shim supported package managers so their commands route through sfw.
#
# Wrapper mode ecosystems (sfw-free):
# JavaScript/TypeScript: npm, yarn, pnpm
# Python: pip, uv
# Rust: cargo
# https://github.com/SocketDev/sfw-free?tab=readme-ov-file#supported-package-managers
#
# Additional wrapper mode ecosystems (sfw-enterprise):
# Ruby: gem, bundler
# .NET: nuget
# Go: go (Linux only)
# https://github.com/SocketDev/firewall-release/wiki#support-matrix
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)"
SSL_WORKAROUND=""
SHIM_CMDS="npm yarn pnpm pip uv cargo"
if [ "$SFW_IS_ENTERPRISE" = "true" ]; then
SHIM_CMDS="npm yarn pnpm pip uv cargo gem bundler nuget"
# Go wrapper mode is only supported on Linux.
[[ "$OSTYPE" == linux* ]] && SHIM_CMDS="$SHIM_CMDS go"
else
SSL_WORKAROUND='export GIT_SSL_NO_VERIFY=true # Workaround: sfw-free does not yet set GIT_SSL_CAINFO.'
fi
for CMD in $SHIM_CMDS; do
REAL="$(PATH="$CLEAN_PATH" command -v "$CMD" 2>/dev/null || true)"
[ -z "$REAL" ] && continue
REAL="$(msys_to_win_path "$REAL")"
SHIM_LINES=('#!/bin/bash' "export PATH=\"\$(echo \"\$PATH\" | tr ':' '\n' | grep -vxF '${SHIM_DIR}' | paste -sd: -)\"")
[ -n "$SSL_WORKAROUND" ] && SHIM_LINES+=("$SSL_WORKAROUND")
SHIM_LINES+=("exec \"${SFW_BIN}\" \"${REAL}\" \"\$@\"")
printf '%s\n' "${SHIM_LINES[@]}" > "$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}"
40 changes: 38 additions & 2 deletions .github/workflows/audit-gha-workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,46 @@ jobs:
with:
persist-credentials: false
- name: Install zizmor
run: pip install zizmor==1.23.1
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="$( (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
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: Run zizmor
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
run: |
if [ -d .github ]; then
zizmor .github --gh-token "${GITHUB_TOKEN}" --min-severity medium
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/setup-and-install.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Setup and Install
on:
workflow_call:
inputs:
node-version:
description: 'Node.js version'
required: false
type: string
default: '25.9.0'
working-directory:
description: 'Working directory for pnpm install'
required: false
type: string
default: '.'
secrets:
SOCKET_API_KEY:
description: 'Socket API key — when provided, uses sfw-enterprise instead of sfw-free'
required: false
jobs:
setup-and-install:
runs-on: ubuntu-latest
steps:
- uses: SocketDev/workflows/.github/actions/setup-and-install@feat/setup-and-install-workflow # zizmor: ignore[unpinned-uses]
with:
node-version: ${{ inputs.node-version }}
socket-api-key: ${{ secrets.SOCKET_API_KEY }} # zizmor: ignore[secrets-outside-env]
working-directory: ${{ inputs.working-directory }}