Skip to content

Commit 3bb6b98

Browse files
author
hallelx2
committed
chore(standards): created local '.github/workflows/security.reusable.yml' from remote '.github/workflows/security.reusable.yml'
Synced AI-review standards from hallelx2/dev-standards.
1 parent e31bc2c commit 3bb6b98

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
name: security (reusable)
2+
3+
# Deterministic security scanners, written once and called by every repo via
4+
# `.github/workflows/security.yml`. The AI reviewers (Copilot agents + Jules) sit
5+
# on top of this. This layer catches the textbook vuln classes + real CVEs.
6+
# Layers: secrets, dependency CVEs (multi-ecosystem + Go-specific), SAST against
7+
# OWASP Top 10 / CWE Top 25, and infra/misconfig.
8+
9+
on:
10+
workflow_call: {}
11+
12+
permissions:
13+
contents: read
14+
pull-requests: read
15+
security-events: write
16+
17+
jobs:
18+
secret-scan:
19+
name: Secrets (gitleaks)
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0
25+
- uses: gitleaks/gitleaks-action@v2
26+
env:
27+
GITHUB_TOKEN: ${{ github.token }}
28+
29+
sast-semgrep:
30+
name: SAST — OWASP Top 10 + CWE Top 25 (Semgrep)
31+
runs-on: ubuntu-latest
32+
container:
33+
image: semgrep/semgrep
34+
steps:
35+
- uses: actions/checkout@v4
36+
- name: Semgrep scan (industry rulesets)
37+
run: |
38+
semgrep scan \
39+
--config p/owasp-top-ten \
40+
--config p/cwe-top-25 \
41+
--config p/secrets \
42+
--config p/javascript \
43+
--config p/typescript \
44+
--config p/python \
45+
--config p/github-actions \
46+
--sarif --output semgrep.sarif || true
47+
- name: Upload Semgrep SARIF
48+
if: always()
49+
uses: github/codeql-action/upload-sarif@v3
50+
with:
51+
sarif_file: semgrep.sarif
52+
continue-on-error: true
53+
54+
go-cves:
55+
name: Go CVEs (govulncheck)
56+
runs-on: ubuntu-latest
57+
steps:
58+
- uses: actions/checkout@v4
59+
- name: Detect Go module
60+
id: detect
61+
run: |
62+
if [ -f go.mod ]; then echo "is_go=true" >> "$GITHUB_OUTPUT"; else echo "is_go=false" >> "$GITHUB_OUTPUT"; fi
63+
- uses: actions/setup-go@v5
64+
if: steps.detect.outputs.is_go == 'true'
65+
with:
66+
go-version: stable
67+
- name: govulncheck (only CVEs that reach real call paths)
68+
if: steps.detect.outputs.is_go == 'true'
69+
run: |
70+
go install golang.org/x/vuln/cmd/govulncheck@latest
71+
govulncheck ./... || true
72+
73+
go-sast:
74+
name: Go SAST (gosec)
75+
runs-on: ubuntu-latest
76+
steps:
77+
- uses: actions/checkout@v4
78+
- name: Detect Go module
79+
id: detect
80+
run: |
81+
if [ -f go.mod ]; then echo "is_go=true" >> "$GITHUB_OUTPUT"; else echo "is_go=false" >> "$GITHUB_OUTPUT"; fi
82+
- name: gosec
83+
if: steps.detect.outputs.is_go == 'true'
84+
uses: securego/gosec@9e6a9843d7a4a6e3e9a8539b02612c8a4aa3f889 # v2.27.1
85+
with:
86+
args: -no-fail -fmt text ./...
87+
88+
node-cves:
89+
name: Node/TS deps (npm audit)
90+
runs-on: ubuntu-latest
91+
steps:
92+
- uses: actions/checkout@v4
93+
- name: Detect Node project
94+
id: detect
95+
run: |
96+
if [ -f package.json ]; then echo "is_node=true" >> "$GITHUB_OUTPUT"; else echo "is_node=false" >> "$GITHUB_OUTPUT"; fi
97+
- uses: actions/setup-node@v4
98+
if: steps.detect.outputs.is_node == 'true'
99+
with:
100+
node-version: '20'
101+
- name: npm audit (high + critical)
102+
if: steps.detect.outputs.is_node == 'true'
103+
run: |
104+
npm install --package-lock-only --ignore-scripts 2>/dev/null || true
105+
npm audit --audit-level=high || true
106+
107+
python-sast:
108+
name: Python deps + SAST (pip-audit + bandit)
109+
runs-on: ubuntu-latest
110+
steps:
111+
- uses: actions/checkout@v4
112+
- name: Detect Python project
113+
id: detect
114+
run: |
115+
if ls requirements*.txt pyproject.toml setup.py >/dev/null 2>&1; then echo "is_py=true" >> "$GITHUB_OUTPUT"; else echo "is_py=false" >> "$GITHUB_OUTPUT"; fi
116+
- uses: actions/setup-python@v5
117+
if: steps.detect.outputs.is_py == 'true'
118+
with:
119+
python-version: '3.x'
120+
- name: pip-audit (CVEs) + bandit (SAST)
121+
if: steps.detect.outputs.is_py == 'true'
122+
run: |
123+
pip install --quiet pip-audit bandit
124+
pip-audit || true
125+
bandit -r . -ll || true
126+
127+
infra-trivy:
128+
name: Vulns + misconfig (Trivy)
129+
runs-on: ubuntu-latest
130+
steps:
131+
- uses: actions/checkout@v4
132+
- name: Install Trivy (latest binary — avoids the action's broken setup-trivy pin)
133+
run: curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
134+
- name: Trivy filesystem scan
135+
run: trivy fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL --ignore-unfixed --exit-code 0 --no-progress .
136+
137+
# Deepest free SAST = CodeQL. It needs per-repo language detection, so enable it
138+
# per PUBLIC repo via Settings → Code security → Code scanning → Default setup (auto).
139+
# Private repos (control-plane, deploy) rely on the Semgrep + OSV + gosec jobs above.

0 commit comments

Comments
 (0)