/ .github / workflows / workflow-linter.yml
workflow-linter.yml
 1  # SPDX-License-Identifier: AGPL-3.0-or-later
 2  # Prevention workflow - validates all workflows have proper security config
 3  name: Workflow Security Linter
 4  
 5  on:
 6    pull_request:
 7      paths:
 8        - '.github/workflows/**'
 9    push:
10      paths:
11        - '.github/workflows/**'
12  
13  permissions: read-all
14  
15  jobs:
16    lint-workflows:
17      runs-on: ubuntu-latest
18      steps:
19        - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
20  
21        - name: Check SPDX headers
22          run: |
23            errors=0
24            for f in .github/workflows/*.yml .github/workflows/*.yaml; do
25              [ -f "$f" ] || continue
26              if ! head -1 "$f" | grep -q "SPDX-License-Identifier"; then
27                echo "ERROR: $f missing SPDX header"
28                errors=$((errors + 1))
29              fi
30            done
31            exit $errors
32  
33        - name: Check permissions declaration
34          run: |
35            errors=0
36            for f in .github/workflows/*.yml .github/workflows/*.yaml; do
37              [ -f "$f" ] || continue
38              if ! grep -q "^permissions:" "$f"; then
39                echo "ERROR: $f missing permissions declaration"
40                errors=$((errors + 1))
41              fi
42            done
43            exit $errors
44  
45        - name: Check pinned actions
46          run: |
47            errors=0
48            for f in .github/workflows/*.yml .github/workflows/*.yaml; do
49              [ -f "$f" ] || continue
50              # Look for uses: without SHA
51              if grep -E "uses:.*@v[0-9]" "$f" | grep -v "#"; then
52                echo "WARNING: $f has unpinned actions (missing SHA comment)"
53              fi
54            done