Skip to content

Dependency Vulnerability Scan #61

Dependency Vulnerability Scan

Dependency Vulnerability Scan #61

name: Dependency Vulnerability Scan
on:
push:
branches: [main, "release/*"]
pull_request:
branches: [main]
schedule:
- cron: "0 6 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
DEPLOY_CHANNEL: ${{ github.ref_name == 'main' && 'stable' || 'canary' }}
jobs:
pnpm-audit:
name: pnpm audit
runs-on: ubuntu-latest
timeout-minutes: 8
continue-on-error: true
outputs:
exit_code: ${{ steps.audit.outputs.exit_code }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10.25.0
run_install: false
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: pnpm audit (direct dependencies)
id: audit
shell: bash
run: |
set +e
pnpm audit --audit-level=high 2>&1 | tee pnpm-audit-output.txt
echo "exit_code=${PIPESTATUS[0]}" >> "$GITHUB_OUTPUT"
exit 0
- name: Upload pnpm audit artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: pnpm-audit-report
path: pnpm-audit-output.txt
retention-days: 30
npm-audit:
name: npm audit fallback
runs-on: ubuntu-latest
timeout-minutes: 8
continue-on-error: true
outputs:
exit_code: ${{ steps.audit.outputs.exit_code }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- name: npm audit (fallback scanner)
id: audit
shell: bash
run: |
set +e
npm audit --audit-level=high 2>&1 | tee npm-audit-output.txt
echo "exit_code=${PIPESTATUS[0]}" >> "$GITHUB_OUTPUT"
exit 0
- name: Upload npm audit artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: npm-audit-report
path: npm-audit-output.txt
retention-days: 30
osv-scan:
name: OSV transitive scan
runs-on: ubuntu-latest
timeout-minutes: 8
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v4
- name: OSV-Scanner (transitive dependencies)
uses: google/osv-scanner-action/osv-scanner-action@v2.3.8
with:
scan-args: |-
--lockfile=pnpm-lock.yaml
--format=json
--output=osv-results.json
- name: Upload OSV artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: osv-scan-report
path: osv-results.json
retention-days: 30
sbom:
name: Generate SBOM
runs-on: ubuntu-latest
timeout-minutes: 8
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- name: Generate SBOM
run: npx @cyclonedx/cyclonedx-npm --output-file sbom.json
- name: Upload SBOM artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: sbom-report
path: sbom.json
retention-days: 30
gate:
name: Aggregate results and gate
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [pnpm-audit, npm-audit, osv-scan, sbom]
if: always()
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download scan artifacts
uses: actions/download-artifact@v4
with:
path: scan-artifacts
merge-multiple: true
- name: Aggregate results and gate
run: node scripts/check-deployment-gate.mjs
env:
DEPLOY_CHANNEL: ${{ env.DEPLOY_CHANNEL }}
PNPM_AUDIT_EXIT_CODE: ${{ needs.pnpm-audit.outputs.exit_code || '0' }}
NPM_AUDIT_EXIT_CODE: ${{ needs.npm-audit.outputs.exit_code || '0' }}
OSV_RESULTS_FILE: scan-artifacts/osv-results.json
- name: Upload consolidated vulnerability report
if: always()
uses: actions/upload-artifact@v4
with:
name: vulnerability-report
path: |
scan-artifacts/pnpm-audit-output.txt
scan-artifacts/npm-audit-output.txt
scan-artifacts/osv-results.json
scan-artifacts/sbom.json
gate-result.json
retention-days: 30
- name: Post scan summary
if: always()
run: |
echo "## Dependency Vulnerability Scan Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- pnpm audit exit code: ${{ needs.pnpm-audit.outputs.exit_code || '0' }}" >> $GITHUB_STEP_SUMMARY
echo "- npm audit exit code: ${{ needs.npm-audit.outputs.exit_code || '0' }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f gate-result.json ]; then
echo '```json' >> $GITHUB_STEP_SUMMARY
cat gate-result.json >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi