mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-09 21:43:05 +09:00
These five workflows triggered on both `push: [dev, main]` and `pull_request: [dev, main]`, so one change was validated up to three times: on the dev push, again on the dev->main PR, and a third time on the post-merge push to main. Narrow them to `push: [dev]` + `pull_request: [main]`: - `pull_request: [dev]` was dead config. Every PR this repo has had targets main (checked back through #77, dependabot's included), so it never produced a run. - `push: [main]` was redundant for release-smoke: release.yml's build-release job runs that same scripts/build-release.sh for real, on the same commit, moments later. Also drops test-system-utils' `unit-tests` job. It ran `pytest tests/test_utils_system.py` (44 tests) that Backend CI's bare `pytest` already collects — there is no pytest.ini, addopts or collect_ignore narrowing collection. The distro matrix and the raw-subprocess audit stay; those are the parts Backend CI genuinely cannot do. Coverage of main is unchanged: a pull_request run tests the merge result, and release.yml still gates itself on the full backend suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
115 lines
4.7 KiB
YAML
115 lines
4.7 KiB
YAML
name: Security Scan
|
|
|
|
on:
|
|
push:
|
|
branches: [dev]
|
|
paths:
|
|
- 'backend/**'
|
|
- '.github/workflows/security-scan.yml'
|
|
pull_request:
|
|
branches: [main]
|
|
paths:
|
|
- 'backend/**'
|
|
- '.github/workflows/security-scan.yml'
|
|
|
|
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
|
|
|
|
- name: Run Bandit scan
|
|
working-directory: backend
|
|
run: |
|
|
echo "## Full report (MEDIUM+ severity, MEDIUM+ confidence)"
|
|
echo ""
|
|
bandit -r app/ \
|
|
--severity-level medium \
|
|
--confidence-level medium \
|
|
-f txt \
|
|
--exit-zero
|
|
echo ""
|
|
echo "---"
|
|
echo ""
|
|
echo "## Strict gate (HIGH severity, HIGH confidence, new issues only)"
|
|
echo "Known accepts: B602 (shell=True for build/deploy scripts),"
|
|
echo " B402/B321 (FTP management feature), B202 (tarfile for backups)"
|
|
echo ""
|
|
bandit -r app/ \
|
|
--severity-level high \
|
|
--confidence-level high \
|
|
--skip B602,B402,B321,B202 \
|
|
-f txt
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 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
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 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
|