| # ADR-0014 — CI security scan (dependencies, static analysis, secrets, image). | |
| # | |
| # NOTE ON THIS REPO'S DEPLOY MODEL: DecoupleRpy_Agent's `origin` is the | |
| # HuggingFace Space (git push builds the Space); HuggingFace does not run GitHub | |
| # Actions. This workflow therefore executes ONLY if the repo is also mirrored to | |
| # GitHub (or `biodata-registry`, which reuses this same file). In the HF-only | |
| # path the enforced check is the pre-push hook (`make install-hooks`) running the | |
| # identical scripts/security_scan.sh, plus the scheduled unattended run. Keeping | |
| # the workflow here means adding a GitHub mirror is zero extra work and the scan | |
| # definition never diverges between the two paths. | |
| name: security | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| schedule: | |
| - cron: "0 6 * * 1" # weekly, Monday 06:00 UTC — catches newly disclosed CVEs | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| scan: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 # gitleaks needs full history | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install scanners | |
| run: | | |
| python -m pip install --upgrade pip | |
| # uv drives the CycloneDX SBOM stage; without it that stage SKIPs, which | |
| # is a failure under SECURITY_SCAN_STRICT=1. | |
| pip install pip-audit bandit uv | |
| # gitleaks + trivy via their official installers | |
| curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b "$HOME/.local/bin" | |
| curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz | tar -xz -C "$HOME/.local/bin" gitleaks | |
| echo "$HOME/.local/bin" >> "$GITHUB_PATH" | |
| - name: Run shared security scan | |
| env: | |
| SECURITY_SCAN_STRICT: "1" # in CI every scanner is present; a skip is a bug | |
| # The GitHub runner has no R; rpy2 in API mode refuses to build without it, | |
| # which breaks pip-audit's dependency resolve. ABI mode builds without R. | |
| RPY2_CFFI_MODE: ABI | |
| run: make security-scan | |
| - name: Upload scan artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: security-scan-${{ github.run_id }} | |
| path: security/ | |
| retention-days: 90 | |