Nightly traffic digest, on by default #908
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: security | |
| on: | |
| pull_request: | |
| branches: [master, main] | |
| push: | |
| branches: [master, main] | |
| schedule: | |
| - cron: "11 6 * * 1" | |
| jobs: | |
| semgrep: | |
| name: semgrep | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| # Skip on cross-repo fork PRs — they can't write annotations. | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # OSS scan only (no SaaS upload, no token). Block only on ERROR-severity | |
| # findings — anything WARNING / INFO is logged but doesn't fail the build. | |
| - run: | | |
| semgrep scan --error --severity ERROR \ | |
| --exclude-rule dockerfile.security.missing-user.missing-user \ | |
| --exclude-rule dockerfile.security.missing-user-entrypoint.missing-user-entrypoint \ | |
| --config p/javascript \ | |
| --config p/typescript \ | |
| --config p/react \ | |
| --config p/nextjs \ | |
| --config p/owasp-top-ten \ | |
| --config p/secrets | |
| npm-audit: | |
| name: npm audit | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Audit (skip when no package.json) | |
| run: | | |
| if [ -f package.json ]; then | |
| (npm ci --no-audit --no-fund 2>/dev/null || npm install --no-audit --no-fund) | |
| # --omit=dev: prod runtime ships browsers via Docker image; the | |
| # playwright advisory is for the npm-install download path, which | |
| # we don't use at runtime. Dev-only tooling vulns don't ship. | |
| npm audit --audit-level=critical --omit=dev | |
| else | |
| echo "no package.json — skipping npm audit" | |
| fi | |
| gitleaks: | |
| name: gitleaks | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| # OSS binary — no license shakedown for org-owned repos. | |
| - name: Install gitleaks | |
| run: | | |
| VERSION=8.21.2 | |
| curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${VERSION}/gitleaks_${VERSION}_linux_x64.tar.gz" \ | |
| | tar -xz -C /usr/local/bin gitleaks | |
| gitleaks version | |
| # A pull request is gated on what IT introduces. Scanning full history | |
| # here failed every PR in the repo on the same historical blob, no matter | |
| # what the PR touched — and a check that is red on arrival is a check | |
| # nobody reads. The history is still scanned, on master and on the weekly | |
| # cron below, so a finding cannot be merged out of sight. | |
| - name: Scan pull request commits | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| gitleaks detect --source . --redact --verbose --no-banner --exit-code 1 \ | |
| --log-opts="--no-merges ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" | |
| # push to master + schedule: everything, forever. This is what surfaces | |
| # credentials already committed; it stays red until they are rotated and | |
| # the blob is purged from history. | |
| - name: Scan history | |
| if: github.event_name != 'pull_request' | |
| run: gitleaks detect --source . --redact --verbose --no-banner --exit-code 1 |