-
-
Notifications
You must be signed in to change notification settings - Fork 11
166 lines (148 loc) · 5.64 KB
/
security-audit.yml
File metadata and controls
166 lines (148 loc) · 5.64 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
name: Security Audit
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop, 'feature/**']
schedule:
# Run weekly on Monday at 6:00 UTC
- cron: '0 6 * * 1'
workflow_dispatch:
inputs:
scan_history:
description: 'Scan git history (slower but more thorough)'
required: false
default: false
type: boolean
min_severity:
description: 'Minimum severity to report'
required: false
default: 'high'
type: choice
options:
- critical
- high
- medium
- low
# ============================================================================
# Security Scan Configuration
# Set to false to disable specific scanners
# ============================================================================
env:
# Secret Detection
SCAN_CKB_SECRETS: 'true'
SCAN_GITLEAKS: 'false'
SCAN_TRUFFLEHOG: 'true'
# SAST (language-specific run automatically based on detection)
SCAN_GOSEC: 'true'
SCAN_BANDIT: 'true'
SCAN_SEMGREP: 'true'
# Dependency Scanning
SCAN_TRIVY: 'true'
SCAN_GOVULNCHECK: 'true'
SCAN_OSV: 'true'
# Minimum severity
MIN_SEVERITY: 'high'
concurrency:
group: security-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name != 'schedule' }}
# Permissions inherited by reusable workflows
permissions:
contents: read
security-events: write
pull-requests: write
jobs:
# ============================================================================
# Step 1: Detect Languages
# ============================================================================
detect:
name: Detect Languages
uses: ./.github/workflows/security-detect.yml
# ============================================================================
# Step 2: Secret Detection
# ============================================================================
secrets:
name: Secrets
needs: detect
uses: ./.github/workflows/security-secrets.yml
with:
scan_ckb: true
scan_gitleaks: false
scan_trufflehog: true
min_severity: ${{ inputs.min_severity || 'high' }}
scan_history: ${{ inputs.scan_history || false }}
# ============================================================================
# Step 3: Language-Specific SAST
# ============================================================================
sast-go:
name: Go SAST
needs: detect
if: needs.detect.outputs.has_go == 'true'
uses: ./.github/workflows/security-sast-go.yml
with:
exclude_dirs: 'testdata,internal/secrets'
# Exclude low-signal rules:
# G104: Unhandled errors (defer close patterns)
# G301: Directory permissions (0755 is intentional for user access)
# G302: File permissions (0644 is standard for config/log files)
# G304: File path from variable (paths come from trusted sources)
# G306: File write permissions (same as G302)
# G703: Path traversal taint analysis (same as G304 but taint-based; all paths are internal)
exclude_rules: 'G104,G301,G302,G304,G306,G703'
sast-python:
name: Python SAST
needs: detect
if: needs.detect.outputs.has_python == 'true'
uses: ./.github/workflows/security-sast-python.yml
with:
exclude_dirs: 'tests,test,venv,.venv'
sast-common:
name: Common SAST
needs: detect
uses: ./.github/workflows/security-sast-common.yml
with:
config: 'p/security-audit'
extra_config: ${{ needs.detect.outputs.has_go == 'true' && 'p/golang' || '' }}
# ============================================================================
# Step 4: Dependency Scanning
# ============================================================================
dependencies:
name: Dependencies
needs: detect
uses: ./.github/workflows/security-dependencies.yml
with:
scan_trivy: true
scan_govulncheck: ${{ needs.detect.outputs.has_go == 'true' }}
scan_osv: true
has_go: ${{ needs.detect.outputs.has_go == 'true' }}
generate_sbom: true
# ============================================================================
# Step 5: Security Gate (aggregation + PR comment)
# ============================================================================
gate:
name: Security Gate
needs: [detect, secrets, sast-go, sast-python, sast-common, dependencies]
if: always()
uses: ./.github/workflows/security-gate.yml
with:
# Secrets
secret_findings: ${{ needs.secrets.outputs.total_findings || 0 }}
trufflehog_findings: ${{ needs.secrets.outputs.trufflehog_findings || 0 }}
# SAST
gosec_findings: ${{ needs.sast-go.outputs.findings || 0 }}
gosec_high: ${{ needs.sast-go.outputs.high || 0 }}
bandit_findings: ${{ needs.sast-python.outputs.findings || 0 }}
bandit_high: ${{ needs.sast-python.outputs.high || 0 }}
semgrep_findings: ${{ needs.sast-common.outputs.findings || 0 }}
# Dependencies
trivy_findings: ${{ needs.dependencies.outputs.trivy_findings || 0 }}
trivy_critical: ${{ needs.dependencies.outputs.trivy_critical || 0 }}
trivy_high: ${{ needs.dependencies.outputs.trivy_high || 0 }}
trivy_licenses: ${{ needs.dependencies.outputs.trivy_licenses || 0 }}
govulncheck_findings: ${{ needs.dependencies.outputs.govulncheck_findings || 0 }}
osv_findings: ${{ needs.dependencies.outputs.osv_findings || 0 }}
# Language flags
has_go: ${{ needs.detect.outputs.has_go == 'true' }}
has_python: ${{ needs.detect.outputs.has_python == 'true' }}
# Errors
secrets_errors: ${{ needs.secrets.outputs.errors || '' }}