|
| 1 | +name: Security |
| 2 | + |
| 3 | +# Supply-chain & secrets gates (#11): |
| 4 | +# - gitleaks: scan the full git history for committed secrets (tokens, credentials) on every |
| 5 | +# push and PR. |
| 6 | +# - zizmor: static-audit the GitHub Actions workflows themselves (template injection, over-broad |
| 7 | +# GITHUB_TOKEN, unpinned actions, credential persistence) AND cross-reference the actions we |
| 8 | +# pin against the GitHub Advisory Database (online audit). |
| 9 | +# Dependabot (github-actions) lives in .github/dependabot.yml; the matching gitleaks pre-commit |
| 10 | +# hook lives in .pre-commit-config.yaml. |
| 11 | + |
| 12 | +on: |
| 13 | + push: |
| 14 | + branches: [main] |
| 15 | + pull_request: |
| 16 | + # Re-audit on a schedule so a newly-published advisory against an action we pin trips the gate |
| 17 | + # even during quiet periods with no pushes — the online zizmor audit is time-varying by design. |
| 18 | + schedule: |
| 19 | + - cron: "0 7 * * 1" # Mondays 07:00 UTC |
| 20 | + |
| 21 | +# Both jobs only read the tree to scan it. Pin the floor to read-only (zizmor: excessive-permissions). |
| 22 | +permissions: |
| 23 | + contents: read |
| 24 | + |
| 25 | +jobs: |
| 26 | + gitleaks: |
| 27 | + name: Secret scan (gitleaks) |
| 28 | + runs-on: ubuntu-24.04 |
| 29 | + # The weekly tick exists for zizmor's advisory re-audit; history doesn't change between pushes, |
| 30 | + # so there's nothing new for gitleaks to scan on a schedule. |
| 31 | + if: github.event_name != 'schedule' |
| 32 | + env: |
| 33 | + # Pinned + checksum-verified — reproducible and immune to runner-image drift. Keep |
| 34 | + # GITLEAKS_VERSION in lockstep with .pre-commit-config.yaml. |
| 35 | + GITLEAKS_VERSION: "8.30.1" |
| 36 | + GITLEAKS_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb" |
| 37 | + steps: |
| 38 | + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 39 | + with: |
| 40 | + fetch-depth: 0 # scan EVERY commit, not just the tip — a secret is still a leak once pushed |
| 41 | + persist-credentials: false # zizmor: artipacked |
| 42 | + - name: Install pinned gitleaks |
| 43 | + run: | |
| 44 | + set -euo pipefail |
| 45 | + tarball="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" |
| 46 | + curl -fsSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${tarball}" -o "$tarball" |
| 47 | + echo "${GITLEAKS_SHA256} ${tarball}" | sha256sum -c - |
| 48 | + tar -xzf "$tarball" gitleaks |
| 49 | + sudo install gitleaks /usr/local/bin/gitleaks |
| 50 | + gitleaks version |
| 51 | + # Full-history scan with the built-in ruleset. --redact keeps any match out of the public logs; |
| 52 | + # the job still fails (non-zero exit) so a leak blocks the merge. |
| 53 | + - name: Scan git history for secrets |
| 54 | + run: gitleaks git . --redact --no-banner --verbose |
| 55 | + |
| 56 | + zizmor: |
| 57 | + name: Workflow audit (zizmor) |
| 58 | + runs-on: ubuntu-24.04 |
| 59 | + env: |
| 60 | + ZIZMOR_VERSION: "1.25.2" |
| 61 | + steps: |
| 62 | + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 63 | + with: |
| 64 | + persist-credentials: false # zizmor: artipacked |
| 65 | + # pipx is preinstalled on ubuntu-24.04. |
| 66 | + - name: Install pinned zizmor |
| 67 | + run: pipx install "zizmor==${ZIZMOR_VERSION}" |
| 68 | + # Online audits ON (zizmor's default): GH_TOKEN lets the `known-vulnerable-actions` audit query |
| 69 | + # the GitHub Advisory Database, so a CVE disclosed against an action we pin fails the gate. The |
| 70 | + # built-in token (read-only here) is enough — advisory data is public; it's only for API access. |
| 71 | + # This complements Dependabot: zizmor blocks the merge, Dependabot opens the bump. |
| 72 | + - name: Audit GitHub Actions workflows |
| 73 | + env: |
| 74 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 75 | + run: zizmor .github/workflows/ |
0 commit comments