-
Notifications
You must be signed in to change notification settings - Fork 1
81 lines (69 loc) · 3.22 KB
/
Copy pathsecurity.yml
File metadata and controls
81 lines (69 loc) · 3.22 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
# Focused OSS security workflow: secret scan (gitleaks) + Python SAST (bandit)
# + dependency audit (pip-audit). Runs on every push to main and every PR so a
# regression is caught before merge. Least-privilege by default: this workflow
# only reads the repository — it publishes nothing and needs no write scopes.
#
# Third-party (and official actions/*) actions are pinned to a full commit SHA
# with a human-readable version comment, so a moved tag cannot alter what runs.
name: security
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
concurrency:
group: security-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
PYTHON_VERSION: "3.14"
jobs:
# ------------------------------------------------------------------- #
# Secret scan: full history via gitleaks, using the repo .gitleaks.toml #
# ------------------------------------------------------------------- #
secrets:
name: secrets (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0 # full history for gitleaks
# The gitleaks GitHub Action requires a paid license for ORGANIZATION
# repos; run the pinned binary directly instead (MIT, no license needed).
- name: gitleaks (binary, no org license)
run: |
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz" \
| tar -xz -C /tmp gitleaks
/tmp/gitleaks detect --source . --config .gitleaks.toml --redact --no-banner
# ------------------------------------------------------------------- #
# Python SAST + dependency audit: bandit (high/critical gate) and #
# pip-audit against the frozen, resolved workspace requirements. #
# ------------------------------------------------------------------- #
python:
name: python (bandit + pip-audit)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Install uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: true
- name: Set up Python
run: uv python install ${{ env.PYTHON_VERSION }}
- name: Sync workspace
run: uv sync --all-packages
# SAST: config (exclusions + skips) lives in pyproject.toml. Fails the
# build on high-severity findings; accepted risk is triaged elsewhere.
- name: Bandit gate (high/critical)
run: uv run bandit -c pyproject.toml -r packages apps --severity-level high -q
# Dependency audit against the fully-resolved, frozen requirements set.
# PYSEC-2026-2132: command injection in click.edit(). Forge never imports
# click, so the vulnerable path is unreachable; click<8.2 is pinned by the
# semgrep dev/CI dependency, so click>=8.3.3 is not resolvable. Revisit and
# drop this ignore once semgrep lifts the click<8.2 cap (dependabot #1).
- name: pip-audit
run: >-
uv export --frozen --format requirements-txt --no-emit-workspace
| uv run pip-audit -r /dev/stdin --strict
--ignore-vuln PYSEC-2026-2132