Skip to content
Open
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
223 changes: 19 additions & 204 deletions .github/workflows/dependency-audit.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
# Dependency vulnerability audit.
# Detects ecosystems and runs appropriate audit tools (npm, pnpm, Go, Rust, Python).
# Standard: https://github.com/petry-projects/.github/blob/main/standards/dependabot-policy.md#vulnerability-audit-ci-check
# ─────────────────────────────────────────────────────────────────────────────
# SOURCE OF TRUTH: petry-projects/.github/standards/workflows/dependency-audit.yml
# Standard: petry-projects/.github/standards/ci-standards.md#5-dependency-audit-dependency-auditym
# Reusable: petry-projects/.github/.github/workflows/dependency-audit-reusable.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.
# AGENTS — READ BEFORE EDITING:
# • This file is a THIN CALLER STUB. All ecosystem-detection and audit logic
# lives in the reusable workflow above.
# • You MAY change: nothing in this file in normal use. Adopt verbatim.
# • You MUST NOT change: trigger events, the `uses:` line, or job name
# (used as a required status check).
# • If you need different behaviour (new ecosystem, tool version bump),
# open a PR against the reusable in the central repo.
# ─────────────────────────────────────────────────────────────────────────────
#
# Add "dependency-audit" as a required status check in branch protection.
#
# Pinned tool versions (update deliberately):
# govulncheck v1.1.4 | cargo-audit 0.22.1 | pip-audit 2.9.0
# Dependency vulnerability audit — thin caller for the org-level reusable.
# To adopt: copy this file to .github/workflows/dependency-audit.yml in your repo.
# Add "dependency-audit / Detect ecosystems" as a required status check
# in branch protection.
name: Dependency audit

on:
Expand All @@ -21,198 +29,5 @@ permissions:
contents: read

jobs:
detect:
name: Detect ecosystems
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

- name: Detect package ecosystems
id: check
run: |
# npm — look for package-lock.json anywhere (excluding node_modules)
if find . -name 'package-lock.json' -not -path '*/node_modules/*' | grep -q .; then
echo "npm=true" >> "$GITHUB_OUTPUT"
else
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"
else
echo "gomod=false" >> "$GITHUB_OUTPUT"
fi

# Cargo — detect via Cargo.toml anywhere (lockfile may not exist for libraries)
if find . -name 'Cargo.toml' -not -path '*/target/*' | grep -q .; then
echo "cargo=true" >> "$GITHUB_OUTPUT"
else
echo "cargo=false" >> "$GITHUB_OUTPUT"
fi

# Python — detect pyproject.toml or requirements.txt anywhere
if find . -name 'pyproject.toml' -not -path '*/.venv/*' -not -path '*/venv/*' | grep -q . || \
find . -name 'requirements.txt' -not -path '*/.venv/*' -not -path '*/venv/*' | grep -q .; then
echo "pip=true" >> "$GITHUB_OUTPUT"
else
echo "pip=false" >> "$GITHUB_OUTPUT"
fi

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

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "lts/*"

- name: Audit npm dependencies
run: |
# Audit each package-lock.json found in the repo
status=0
while IFS= read -r dir; do
echo "::group::npm audit $dir"
if ! (cd "$dir" && npm audit --audit-level=low); then
status=1
fi
echo "::endgroup::"
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 # v4

- uses: pnpm/action-setup@91ab88e2619ed1f46221f0ba42d1492c02baf788 # v4

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

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

- name: Install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4

- name: Audit Go dependencies
run: |
status=0
while IFS= read -r dir; do
echo "::group::govulncheck $dir"
if ! (cd "$dir" && govulncheck ./...); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'go.mod' -not -path '*/vendor/*' -exec dirname {} \;)
exit $status

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

- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable

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

- name: Audit Cargo dependencies
run: |
# cargo audit operates on Cargo.lock at workspace root
# For workspaces, a single audit at root covers all crates
status=0
while IFS= read -r dir; do
echo "::group::cargo audit $dir"
if ! (cd "$dir" && cargo generate-lockfile 2>/dev/null; cargo audit); then
status=1
fi
echo "::endgroup::"
done < <(find . -name 'Cargo.toml' -not -path '*/target/*' -exec dirname {} \; | sort -u)
exit $status

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

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.x"

- name: Install pip-audit
run: pip install pip-audit==2.9.0

- name: Audit Python dependencies
run: |
status=0
# Audit each Python project found in the repo
while IFS= read -r dir; do
echo "::group::pip-audit $dir"
if [ -f "$dir/pyproject.toml" ]; then
if ! pip-audit "$dir"; then
status=1
fi
elif [ -f "$dir/requirements.txt" ]; then
if ! pip-audit -r "$dir/requirements.txt"; then
status=1
fi
fi
echo "::endgroup::"
done < <(
{
find . -name 'pyproject.toml' -not -path '*/.venv/*' -not -path '*/venv/*' -exec dirname {} \;
find . -name 'requirements.txt' -not -path '*/.venv/*' -not -path '*/venv/*' -exec dirname {} \;
} | sort -u
)
exit $status
dependency-audit:
uses: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@v1
Comment on lines +32 to +33
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Resolve the commit SHA that the v1 tag on petry-projects/.github currently points to.
# This SHA is what the upstream template and, subsequently, this caller should use.
gh api repos/petry-projects/.github/git/refs/tags/v1 \
  --jq '{tag: .ref, sha: .object.sha, type: .object.type}'

# If v1 is an annotated tag (type == "tag"), also resolve the underlying commit SHA:
gh api repos/petry-projects/.github/git/refs/tags/v1 \
  --jq '.object | select(.type=="tag") | .sha' \
  | xargs -I{} gh api repos/petry-projects/.github/git/tags/{} --jq '.object.sha'

Repository: petry-projects/.github

Length of output: 154


Pin the reusable workflow reference to its commit SHA rather than the mutable v1 tag.

The uses: reference on line 33 uses @v1, a floating tag that can be silently repointed. The coding guideline requires: "SHAs for action pinning must be looked up via the GitHub API — never guessed." This applies to reusable workflow references as well.

The v1 tag currently resolves to commit 0cb4bba11d7563bf197ad805f12fb8639e4879e4. Since this file is copied verbatim from the upstream template in petry-projects/.github/standards/workflows/dependency-audit.yml, the fix should be made upstream first, then re-synced here:

Suggested fix (upstream template)
-    uses: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@v1
+    uses: petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@0cb4bba11d7563bf197ad805f12fb8639e4879e4

Without this change, the compliance audit will continue to flag this file for unpinned action references, leaving Issue #106 unresolved.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dependency-audit.yml around lines 32 - 33, Update the
reusable workflow reference for the dependency-audit job so it uses the exact
commit SHA instead of the floating tag; locate the "dependency-audit" job and
replace the uses:
petry-projects/.github/.github/workflows/dependency-audit-reusable.yml@v1
reference with the corresponding commit SHA (the one resolved via the GitHub
API, e.g., 0cb4bba11d7563bf197ad805f12fb8639e4879e4) — make this change first in
the upstream template (petry-projects/.github) and then sync the updated file
into this repository so the workflow here points to the pinned SHA.

Comment on lines 31 to +33