Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .github/actions/supply-chain-lint/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ inputs:
description: "Path to a repo-specific allowlist file (relative to repository root). Entries are merged with the built-in allowlist."
required: false
default: ""
scan-local-actions:
description: "Scan composite actions under the repository's own .github/actions/ directory. Set to \"false\" to skip them."
required: false
default: "true"

outputs:
violations_found:
Expand All @@ -30,3 +34,4 @@ runs:
SCAN_ROOT: ${{ github.workspace }}
BUILTIN_ALLOWLIST_PATH: ${{ github.action_path }}/supply-chain-allowlist.yml
REPO_ALLOWLIST_PATH: ${{ inputs.allowlist-path && format('{0}/{1}', github.workspace, inputs.allowlist-path) || '' }}
SCAN_LOCAL_ACTIONS: ${{ inputs.scan-local-actions }}
21 changes: 19 additions & 2 deletions .github/actions/supply-chain-lint/supply-chain-lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
# Non-allowlisted violations cause exit 1.
#
# Environment variables (set by composite action, optional for direct use):
# SCAN_ROOT — directory to scan (defaults to parent of script dir)
# ALLOWLIST_PATH — path to allowlist YAML (defaults to $SCRIPT_DIR/supply-chain-allowlist.yml)
# SCAN_ROOT — directory to scan (defaults to parent of script dir)
# ALLOWLIST_PATH — path to allowlist YAML (defaults to $SCRIPT_DIR/supply-chain-allowlist.yml)
# SCAN_LOCAL_ACTIONS — scan the repo's own .github/actions/ (default: true; "false" to skip)

set -eo pipefail

Expand Down Expand Up @@ -156,6 +157,22 @@ find . -name ".git" -prune -o \( -name "action.yml" -o -name "action.yaml" \) -p
find "$(dirname "$f")" -maxdepth 3 -name "*.sh" 2>/dev/null
done | (grep -vE "/(${SKIP_DIRS})/" || true) | sed 's|^\./||' | self_exclude_filter | sort -u >> "$FILES_TO_SCAN"

# SKIP_DIRS above also excludes the repo's own composite actions under
# .github/actions/; add them back unless SCAN_LOCAL_ACTIONS=false. Test
# dirs nested inside them stay excluded.
if [[ "${SCAN_LOCAL_ACTIONS:-true}" != "false" && -d ".github/actions" ]]; then
LOCAL_SKIP_DIRS="\.git|__tests__|__test__|/tests/|/test/"

find ./.github/actions -name ".git" -prune -o \( -name "action.yml" -o -name "action.yaml" \) -print 2>/dev/null | \
(grep -vE "/(${LOCAL_SKIP_DIRS})/" || true) | sed 's|^\./||' | self_exclude_filter | sort >> "$FILES_TO_SCAN"

find ./.github/actions -name ".git" -prune -o \( -name "action.yml" -o -name "action.yaml" \) -print 2>/dev/null | \
(grep -vE "/(${LOCAL_SKIP_DIRS})/" || true) | while IFS= read -r f; do
[[ -z "$f" ]] && continue
find "$(dirname "$f")" -maxdepth 3 -name "*.sh" 2>/dev/null
done | (grep -vE "/(${LOCAL_SKIP_DIRS})/" || true) | sed 's|^\./||' | self_exclude_filter | sort -u >> "$FILES_TO_SCAN"
fi

FILE_COUNT=$(wc -l < "$FILES_TO_SCAN" | tr -d ' ')
info "Scanning ${FILE_COUNT} files..."
echo ""
Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/supply-chain-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ name: Supply chain lint

# Scans GitHub Actions (`action.yml`/`action.yaml` and sibling `.sh` scripts)
# for runtime supply-chain risks: `npm install` without `npm ci`, `curl | bash`,
# unpinned `@latest`, `--no-lockfile`, etc. The scanner skips `.github/` by
# design, so the vendored actions under `.github/actions/` are not scanned
# today — the gate acts as a tripwire for any vendored action added outside
# `.github/` later.
# unpinned `@latest`, `--no-lockfile`, etc. The scan covers this repo's own
# composite actions under `.github/actions/` (the lint always excludes its own
# directory, so the vendored copy does not flag itself).
#
# Triggers only on `.github/**` changes — everything the lint scans lives there.
#
# xpub-tool is a public repo, so it must not reference (or have access to) the
# private swan-bitcoin/actions repo. Like `check-linear-link`, the action is
# vendored into `.github/actions/supply-chain-lint` — a verbatim copy of
# swan/supply-chain-lint from swan-bitcoin/actions@63912e4cae62a3786793d1fd5d903e8a480685d5.
# swan/supply-chain-lint from swan-bitcoin/actions@b89206bcb5f662f9dffb57b8db8db0f1cdd2c403.
# It is a self-contained bash composite with no transitive `uses:`, so the copy
# has no external references to pin. Re-sync it from the actions repo when the
# upstream action changes.
Expand All @@ -20,8 +21,10 @@ name: Supply chain lint
on:
push:
branches: [master]
paths: ['.github/**']
pull_request:
types: [opened, synchronize]
paths: ['.github/**']
workflow_dispatch:

permissions:
Expand Down
Loading