main
yml 125 lines 4.82 KB
Raw
1 # Consolidated Security Scanning
2 #
3 # This workflow combines all security scanners into a single pipeline:
4 # - Bandit: Python SAST scanning for security issues in source code.
5 # - zizmor: Focuses on GitHub Actions-specific supply-chain risks such as
6 # template injection and dangerous triggers.
7 #
8 # All jobs run in parallel and upload SARIF results to GitHub Code Scanning.
9
10 name: Security Scanning
11
12 on:
13 push:
14 branches:
15 - main
16 - dev
17 pull_request:
18 branches:
19 - main
20 - dev
21
22 permissions: {}
23
24 concurrency:
25 group: ${{ github.workflow }}-${{ github.ref }}
26 cancel-in-progress: true
27
28 jobs:
29 # ──────────────────────────────────────────────────────────────────────
30 # Bandit – Python SAST scanner
31 # ──────────────────────────────────────────────────────────────────────
32 bandit-scan:
33 name: Bandit Python security scan
34 runs-on: ubuntu-latest
35 permissions:
36 contents: read
37 security-events: write
38
39 steps:
40 - name: Checkout code
41 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
42 with:
43 persist-credentials: false
44
45 - name: Set up Python
46 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
47 with:
48 python-version: "3.12"
49
50 - name: Install Bandit
51 run: |
52 python -m pip install --upgrade pip
53 pip install bandit[sarif]
54
55 - name: Run Bandit scan
56 run: |
57 # Run bandit with configuration from .bandit.yaml
58 # -r: recursive scan
59 # -f sarif: output SARIF format for GitHub Code Scanning
60 # -o: output file
61 # Exits non-zero on findings — this is intentional so security
62 # issues block merges (required status check)
63 bandit -c .bandit.yaml -r . -f sarif -o bandit-results.sarif
64
65 - name: Upload SARIF to GitHub Code Scanning
66 if: always()
67 uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
68 with:
69 sarif_file: bandit-results.sarif
70 category: bandit
71
72 - name: Upload SARIF as artifact
73 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
74 if: always()
75 with:
76 name: bandit-sarif
77 path: bandit-results.sarif
78 retention-days: 30
79
80 # ──────────────────────────────────────────────────────────────────────
81 # zizmor – GitHub Actions supply-chain security scanner
82 # Covers: template injection, dangerous triggers, unpinned actions
83 # ──────────────────────────────────────────────────────────────────────
84 zizmor-scan:
85 name: GitHub Actions Security Scan (zizmor)
86 runs-on: ubuntu-latest
87 permissions:
88 contents: read
89 security-events: write
90 actions: read
91 # Phase C (DevSecOps Guardrails epic, issue #545): BLOCKING.
92 # continue-on-error has been dropped so zizmor findings (default persona)
93 # fail the build. The Phase B baseline (#543) is clean on the default
94 # persona, so this gate is green today and catches new findings going
95 # forward. See docs/devsecops/zizmor-baseline.md.
96 steps:
97 - name: Checkout repository
98 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
99 with:
100 persist-credentials: false
101
102 - name: Collect zizmor workflow inputs
103 id: zizmor-inputs
104 run: |
105 {
106 echo "inputs<<EOF"
107 find .github/workflows -maxdepth 1 -type f \
108 \( -name "*.yml" -o -name "*.yaml" \) \
109 ! -name "squad-*.yml" \
110 ! -name "squad-*.yaml" \
111 ! -name "sync-squad-labels.yml" \
112 ! -name "sync-squad-labels.yaml" \
113 | sort
114 echo "EOF"
115 } >> "$GITHUB_OUTPUT"
116
117 - name: Run zizmor security scan
118 uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
119 with:
120 # Squad workflows are generated upstream; scan all repository-owned
121 # workflows while excluding generated Squad workflow files.
122 inputs: ${{ steps.zizmor-inputs.outputs.inputs }}
123 # SARIF output automatically uploaded to GitHub Code Scanning
124 # Focuses on P0 findings: template-injection and dangerous-triggers
125 advanced-security: true