-
Notifications
You must be signed in to change notification settings - Fork 0
98 lines (92 loc) · 3.91 KB
/
Copy pathsecurity.yml
File metadata and controls
98 lines (92 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Security scanning (2026-07-16 standards sweep): SAST (Semgrep), secret scanning
# (gitleaks), and dependency audit (pip-audit against the locked uv environment —
# the same `make audit` a contributor runs locally). All jobs run automatically on
# push/PR plus a weekly sweep; none is dispatch-only.
name: security
on:
push:
branches: [main]
pull_request:
schedule:
- cron: "0 7 * * 0" # weekly, Sunday, staggered off ci.yml's push/PR runs
permissions:
contents: read
concurrency:
group: security-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
semgrep:
name: SAST (Semgrep, registry auto config)
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
container:
image: semgrep/semgrep@sha256:59fbed6127ea7c5dde3ba6a85142733bb20ea9aaa36120c953904f1539aaf66e # 1.168.0
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
# `semgrep scan`, not `semgrep ci`. On a pull_request event `semgrep ci`
# resolves a diff baseline and shells out to
# `git fetch origin --force --depth=1 <head-sha>`. This repository is
# private and the checkout above sets `persist-credentials: false`, so that
# fetch died with "could not read Username for 'https://github.com'",
# semgrep aborted before scanning anything, and its default
# `--suppress-errors` turned the aborted run into exit 0. Every pull request
# therefore got a green SAST check over zero scanned files, while the same
# config on a push to main ran the full scan and went red. `semgrep scan`
# needs no baseline and no credential, so both events now run the identical
# full scan. `--error` fails on findings; `--strict` fails on an analysis
# error, so a scan that cannot run can no longer report success.
- run: semgrep scan --config auto --error --strict
gitleaks:
name: secret scanning (gitleaks)
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
# gitleaks-action lists the PR's commits via the REST API on pull_request
# events to compute the scan range; without this it fails with a 403
# "Resource not accessible by integration" before scanning anything.
pull-requests: read
steps:
- name: Checkout (full history — gitleaks scans the diff/range)
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false
- name: Run gitleaks (fails the build on any finding; redacts secrets in logs)
uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# No GITLEAKS_LICENSE: this repo is under a personal account, not an
# organization, so gitleaks-action does not require a license key.
# No mute: default config, no .gitleaksignore, non-zero exit fails the job.
pip-audit:
name: dependency audit (pip-audit, locked env)
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
env:
UV_PYTHON: "3.12"
UV_PYTHON_DOWNLOADS: never
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
check-latest: false
- name: Set up uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
version: "0.11.28"
enable-cache: true
- name: pip-audit (same target as `make audit`)
run: |
uv sync --frozen
uv run pip-audit --skip-editable --cache-dir .cache/pip-audit