Skip to content

Security Main Branch #69

Security Main Branch

Security Main Branch #69

Workflow file for this run

name: Security Main Branch
on:
push:
branches: [main]
schedule:
# Run daily at 02:00 UTC
- cron: '0 2 * * *'
workflow_dispatch:
permissions:
contents: read
jobs:
# Detect changes (skip for scheduled runs)
changes:
runs-on: ubuntu-latest
if: github.event_name != 'schedule'
permissions:
pull-requests: read
outputs:
security: ${{ steps.filter.outputs.security }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: filter
with:
filters: |
security:
- 'package.json'
- 'package-lock.json'
- 'src/**'
- '.github/workflows/**'
# NPM audit (production only)
npm-audit:
needs: changes
if: |
always() &&
(needs.changes.result == 'skipped' || needs.changes.outputs.security == 'true')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Create package-lock.json if missing
run: |
if [ ! -f package-lock.json ]; then
echo "package-lock.json not found, running npm install to create it"
npm install --package-lock-only --ignore-scripts
fi
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: 'npm'
- name: Install dependencies
run: npm ci --omit=dev --ignore-scripts
- name: Run npm audit
run: npm audit --production --audit-level=moderate
continue-on-error: false
# Generate SBOM
sbom:
needs: changes
if: |
always() &&
(needs.changes.result == 'skipped' || needs.changes.outputs.security == 'true')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Create package-lock.json if missing
run: |
if [ ! -f package-lock.json ]; then
echo "package-lock.json not found, running npm install to create it"
npm install --package-lock-only --ignore-scripts
fi
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Generate SBOM (CycloneDX)
run: npx @cyclonedx/cyclonedx-npm --output-file sbom.json
- name: Upload SBOM
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: sbom-main
path: sbom.json
retention-days: 90
# CodeQL Analysis
codeql:
needs: changes
if: |
always() &&
(needs.changes.result == 'skipped' || needs.changes.outputs.security == 'true')
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with:
languages: javascript-typescript
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with:
category: "/language:javascript-typescript"
# OpenSSF Scorecard
scorecard:
needs: changes
if: |
always() &&
(needs.changes.result == 'skipped' || needs.changes.outputs.security == 'true')
runs-on: ubuntu-latest
permissions:
security-events: write
id-token: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false
- name: Run OpenSSF Scorecard
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with:
sarif_file: results.sarif
# License compliance
license-check:
needs: changes
if: |
always() &&
(needs.changes.result == 'skipped' || needs.changes.outputs.security == 'true')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Create package-lock.json if missing
run: |
if [ ! -f package-lock.json ]; then
echo "package-lock.json not found, running npm install to create it"
npm install --package-lock-only --ignore-scripts
fi
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check licenses
run: npx license-checker --summary
# Summary
security-summary:
needs: [npm-audit, sbom, codeql, scorecard, license-check]
runs-on: ubuntu-latest
if: always()
steps:
- name: Security Summary
run: |
{
echo "## Security Main Branch Summary"
echo ""
echo "- NPM Audit: ${{ needs.npm-audit.result }}"
echo "- SBOM Generation: ${{ needs.sbom.result }}"
echo "- CodeQL Analysis: ${{ needs.codeql.result }}"
echo "- OpenSSF Scorecard: ${{ needs.scorecard.result }}"
echo "- License Check: ${{ needs.license-check.result }}"
} >> "$GITHUB_STEP_SUMMARY"