-
Notifications
You must be signed in to change notification settings - Fork 0
167 lines (154 loc) · 6.63 KB
/
devsecops.yml
File metadata and controls
167 lines (154 loc) · 6.63 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# CAST — DevSecOps Pipeline for Python
# https://github.com/castops/cast
#
# Includes:
# 1. Secrets Detection — Gitleaks
# 2. SAST — Semgrep
# 3. SCA — pip-audit
# 4. Container Security — Trivy (skipped if no Dockerfile)
# 5. Code Quality — Ruff
# 6. Template Lint — yamllint on templates/**/*.yml
# 7. Security Gate — blocks merge on critical findings
name: CAST DevSecOps
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:
permissions:
contents: read
security-events: write # required for SARIF upload to GitHub Security tab
actions: read
jobs:
# ── 1. Secrets Detection ───────────────────────────────────────────────────
secrets:
name: Secrets Detection
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so Gitleaks can scan all commits
- name: Install Gitleaks
run: |
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.27.2/gitleaks_8.27.2_linux_x64.tar.gz \
-o /tmp/gitleaks.tar.gz
tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks
sudo mv /tmp/gitleaks /usr/local/bin/gitleaks
gitleaks version
- name: Gitleaks scan
run: gitleaks detect --source . --verbose --redact
# ── 2. SAST ────────────────────────────────────────────────────────────────
sast:
name: SAST
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- name: Semgrep scan
# SEMGREP_APP_TOKEN is optional — falls back to open-source rules
run: semgrep ci --sarif --output=semgrep.sarif || true
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- name: Ensure SARIF exists
if: always()
run: |
[ -f semgrep.sarif ] || echo '{"version":"2.1.0","$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json","runs":[]}' > semgrep.sarif
- name: Upload to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
continue-on-error: true # requires GitHub Advanced Security; skip gracefully if not enabled
with:
sarif_file: semgrep.sarif
# ── 3. SCA — Dependency Audit ──────────────────────────────────────────────
sca:
name: SCA
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
cache: pip
- name: pip-audit
run: |
pip install pip-audit
pip install -e ".[dev]"
# CVE-2026-4539: ReDoS in pygments AdlLexer — no fix released yet
# (https://github.com/advisories/GHSA-5239-wwwm-4pmq); re-enable once patched
pip-audit --ignore-vuln CVE-2026-4539
# ── 4. Container Security ──────────────────────────────────────────────────
container:
name: Container Security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for Dockerfile
id: check_dockerfile
run: |
if [ -f Dockerfile ]; then
echo "found=true" >> $GITHUB_OUTPUT
else
echo "No Dockerfile found — skipping container scan"
echo "found=false" >> $GITHUB_OUTPUT
fi
- name: Build image
if: steps.check_dockerfile.outputs.found == 'true'
run: docker build -t cast-scan:${{ github.sha }} .
- name: Trivy scan
if: steps.check_dockerfile.outputs.found == 'true'
uses: aquasecurity/trivy-action@master
with:
image-ref: cast-scan:${{ github.sha }}
format: sarif
output: trivy.sarif
severity: CRITICAL,HIGH
exit-code: "0" # gate handles blocking, not trivy directly
- name: Upload to GitHub Security tab
if: steps.check_dockerfile.outputs.found == 'true'
uses: github/codeql-action/upload-sarif@v3
continue-on-error: true # requires GitHub Advanced Security; skip gracefully if not enabled
with:
sarif_file: trivy.sarif
# ── 5. Code Quality ────────────────────────────────────────────────────────
quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v1
# ── 6. Template Lint ───────────────────────────────────────────────────────
template-lint:
name: Template Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install yamllint
run: pip install yamllint
- name: Lint workflow files
# Templates embed shell heredocs whose content is intentionally at column 1
# (required by bash heredoc syntax). GitHub Actions handles this correctly,
# but yamllint's YAML parser reports false-positive syntax errors for such files.
# Only lint pure workflow YAML files in .github/workflows/.
run: yamllint -d relaxed .github/workflows/*.yml
# ── 7. Security Gate ───────────────────────────────────────────────────────
gate:
name: Security Gate
runs-on: ubuntu-latest
needs: [secrets, sast, sca, quality]
if: always()
steps:
- name: Evaluate results
run: |
echo "secrets : ${{ needs.secrets.result }}"
echo "sast : ${{ needs.sast.result }}"
echo "sca : ${{ needs.sca.result }}"
echo "quality : ${{ needs.quality.result }}"
if [[ "${{ needs.secrets.result }}" == "failure" ||
"${{ needs.sast.result }}" == "failure" ||
"${{ needs.sca.result }}" == "failure" ]]; then
echo "❌ Security gate failed — merge blocked"
exit 1
fi
echo "✅ All checks passed — safe to merge"