Skip to content
Merged
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
57 changes: 47 additions & 10 deletions .github/workflows/dependency-audit.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Dependency vulnerability audit
# Copy to .github/workflows/dependency-audit.yml
#
# Auto-detects ecosystems present in the repository and runs the appropriate
# audit tool. Fails the build if any dependency has a known security advisory.
#
# Add "dependency-audit" as a required status check in branch protection.
#
# Pinned tool versions (update deliberately):
# govulncheck v1.1.4 | cargo-audit 0.21.1 | pip-audit 2.9.0
# govulncheck v1.1.4 | cargo-audit 0.22.1 | pip-audit 2.9.0
name: Dependency audit

on:
Expand All @@ -24,11 +25,12 @@ jobs:
runs-on: ubuntu-latest
outputs:
npm: ${{ steps.check.outputs.npm }}
pnpm: ${{ steps.check.outputs.pnpm }}
gomod: ${{ steps.check.outputs.gomod }}
cargo: ${{ steps.check.outputs.cargo }}
pip: ${{ steps.check.outputs.pip }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Detect package ecosystems
id: check
Expand All @@ -40,6 +42,13 @@ jobs:
echo "npm=false" >> "$GITHUB_OUTPUT"
fi

# pnpm — look for pnpm-lock.yaml anywhere
if find . -name 'pnpm-lock.yaml' -not -path '*/node_modules/*' | grep -q .; then
echo "pnpm=true" >> "$GITHUB_OUTPUT"
else
echo "pnpm=false" >> "$GITHUB_OUTPUT"
fi

# Go modules — detect via go.mod (not go.sum, which may not exist)
if find . -name 'go.mod' -not -path '*/vendor/*' | grep -q .; then
echo "gomod=true" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -68,9 +77,9 @@ jobs:
if: needs.detect.outputs.npm == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "lts/*"

Expand All @@ -87,15 +96,42 @@ jobs:
done < <(find . -name 'package-lock.json' -not -path '*/node_modules/*' -exec dirname {} \;)
exit $status

audit-pnpm:
name: pnpm audit
needs: detect
if: needs.detect.outputs.pnpm == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4

- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "lts/*"

- name: Audit pnpm dependencies
run: |
# Audit each pnpm-lock.yaml found in the repo
status=0
while IFS= read -r dir; do
echo "::group::pnpm audit $dir"
if ! (cd "$dir" && pnpm audit --audit-level low); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'pnpm-lock.yaml' -not -path '*/node_modules/*' -exec dirname {} \;)
exit $status

audit-go:
name: govulncheck
needs: detect
if: needs.detect.outputs.gomod == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v5
with:
go-version: "stable"

Expand All @@ -120,12 +156,13 @@ jobs:
if: needs.detect.outputs.cargo == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: dtolnay/rust-toolchain@stable
- name: Install Rust stable toolchain
run: rustup toolchain install stable --profile minimal

- name: Install cargo-audit
run: cargo install cargo-audit@0.21.1 --locked
run: cargo install cargo-audit@0.22.1 --locked

- name: Audit Cargo dependencies
run: |
Comment on lines 167 to 168

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside the Audit Cargo dependencies script (below this run: |), the subshell uses cd "$dir" && cargo generate-lockfile ...; cargo audit—because of the ;, cargo audit will still run even if the cd fails (auditing the wrong directory). Consider chaining cargo audit with && (or otherwise explicitly handling failures) to ensure the audit only runs in the intended directory.

Copilot uses AI. Check for mistakes.
Expand All @@ -147,7 +184,7 @@ jobs:
if: needs.detect.outputs.pip == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
Expand Down
Loading