mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-23 19:49:14 +09:00
CONTRIBUTING asks contributors to target dev, but every workflow only triggered on PRs into main, so contributor PRs merged with no checks and failures surfaced only after the push to dev.
144 lines
5.7 KiB
YAML
144 lines
5.7 KiB
YAML
name: Security Scan
|
|
|
|
on:
|
|
push:
|
|
branches: [dev]
|
|
paths:
|
|
- 'backend/**'
|
|
- 'builtin-extensions/**'
|
|
- '**/requirements*.txt'
|
|
- 'frontend/package*.json'
|
|
- 'scripts/check-bandit-report.py'
|
|
- 'scripts/security/**'
|
|
- '.github/workflows/security-scan.yml'
|
|
pull_request:
|
|
branches: [main, dev]
|
|
paths:
|
|
- 'backend/**'
|
|
- 'builtin-extensions/**'
|
|
- '**/requirements*.txt'
|
|
- 'frontend/package*.json'
|
|
- 'scripts/check-bandit-report.py'
|
|
- 'scripts/security/**'
|
|
- '.github/workflows/security-scan.yml'
|
|
schedule:
|
|
- cron: '17 9 * * 1' # Weekly; advisories change even without repository changes.
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# Job 1: Bandit — static analysis for Python security issues
|
|
# ──────────────────────────────────────────────────────────────────
|
|
bandit:
|
|
name: Bandit SAST
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Install Bandit
|
|
run: pip install bandit==1.9.3
|
|
|
|
- name: Run Bandit scan
|
|
run: |
|
|
python -m unittest discover -s scripts/security -p 'test_*.py'
|
|
bandit -r backend/app builtin-extensions -f json -o bandit-report.json --exit-zero
|
|
python scripts/check-bandit-report.py bandit-report.json
|
|
|
|
- name: Upload full Bandit report
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: bandit-report
|
|
path: bandit-report.json
|
|
if-no-files-found: warn
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# Job 2: pip-audit — dependency vulnerability scanning (the gate)
|
|
#
|
|
# This is the blocking check. Unlike the Safety job below it needs no
|
|
# account, no API key and no network-fetched policy: it resolves the pinned
|
|
# requirements against the PyPI Advisory Database and fails on anything it
|
|
# finds. Every suppression therefore has to live in THIS file, in a diff a
|
|
# reviewer can see — which is the whole point. Safety was reporting
|
|
# "No issues found" while its Platform-side policy silently ignored four
|
|
# advisories, one of them a real, fixable CVE in a directly pinned package.
|
|
# ──────────────────────────────────────────────────────────────────
|
|
pip-audit:
|
|
name: pip-audit Dependency Scan
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Install pip-audit
|
|
run: pip install pip-audit
|
|
|
|
# No --ignore-vuln entries today. If one is ever needed, add it here with
|
|
# a comment saying which advisory, why it does not apply, and when to
|
|
# revisit — never by silencing the scanner globally.
|
|
- name: Audit backend requirements
|
|
run: pip-audit -r backend/requirements.txt --progress-spinner off
|
|
|
|
- name: Audit test-harness requirements
|
|
run: pip-audit -r scripts/test/harness/requirements.txt --progress-spinner off
|
|
|
|
- name: Audit extension requirements
|
|
shell: bash
|
|
run: |
|
|
while IFS= read -r -d '' requirements; do
|
|
pip-audit -r "$requirements" --progress-spinner off
|
|
done < <(find builtin-extensions -type f -name 'requirements*.txt' -print0)
|
|
|
|
npm-audit:
|
|
name: Frontend Production Dependency Scan
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
cache: npm
|
|
cache-dependency-path: frontend/package-lock.json
|
|
- name: Audit production dependency lockfile
|
|
working-directory: frontend
|
|
# No installation or package scripts are needed to audit the lockfile.
|
|
run: npm audit --package-lock-only --omit=dev --audit-level=high
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# Job 3: Safety — advisory only
|
|
#
|
|
# Kept for the Safety Platform dashboard, but deliberately NOT a gate.
|
|
# The action shells out to a hosted service, and a service-side failure
|
|
# there (results upload erroring with "Sorry, something went wrong" while
|
|
# the scan itself reported clean) took CI red on 2026-07-20 with no repo
|
|
# change behind it — requirements had not moved since 2026-07-04. An
|
|
# outage at a third party should not block merges; pip-audit above is the
|
|
# check that actually has to pass.
|
|
# ──────────────────────────────────────────────────────────────────
|
|
safety:
|
|
name: Safety Dependency Scan (advisory)
|
|
runs-on: ubuntu-latest
|
|
continue-on-error: true
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Run Safety CLI to check for vulnerabilities
|
|
continue-on-error: true
|
|
uses: pyupio/safety-action@v1
|
|
with:
|
|
api-key: ${{ secrets.SAFETY_API_KEY }}
|
|
args: --full-report
|