-
-
Notifications
You must be signed in to change notification settings - Fork 1
91 lines (78 loc) · 3.49 KB
/
Copy pathcodeql.yml
File metadata and controls
91 lines (78 loc) · 3.49 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
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: ['**']
schedule:
# Catches newly published rules against code nobody has touched this week.
- cron: '17 3 * * 1'
permissions:
contents: read
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
steps:
- name: Checkout repo
uses: actions/checkout@v7
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: javascript-typescript
# security-extended adds rules that are lower signal on their own but
# matter on an auth server, for example weak randomness and unsafe
# comparisons in token handling.
queries: security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@v4
with:
category: /language:javascript-typescript
# The gate. Every alert must end up fixed or dismissed with a written
# reason, so the steady state is zero open alerts and any open alert is
# actionable. The alternative, failing only on alerts a pull request
# introduces, leaves a baseline nobody owns and trains reviewers to scroll
# past the security tab.
#
# Dismissals are the pressure valve: a false positive is closed with its
# reasoning attached in the security tab, and the longer form lives in
# docs/security-posture.md.
- name: Assert the alert baseline is triaged
# A pull request from a fork gets a read-only token without
# security-events scope, so the query would fail as a permission error
# rather than a finding. Those land on main, where this still runs.
if: github.event.pull_request.head.repo.fork != true
env:
GH_TOKEN: ${{ github.token }}
REF: ${{ github.event_name == 'pull_request' &&
format('refs/pull/{0}/merge', github.event.pull_request.number) || github.ref }}
run: |
set -euo pipefail
# Fetch and parse are separate, and the response shape is checked
# before it is read. A gate that cannot see the alerts has to fail
# loudly; the shape that would otherwise slip through is an error
# object, which flattens to something that reads as an empty list.
if ! gh api --paginate --slurp \
"repos/${GITHUB_REPOSITORY}/code-scanning/alerts?state=open&ref=${REF}&per_page=100" \
> alerts.json; then
echo "::error::Could not read code scanning alerts for ${REF}."
exit 1
fi
if ! jq -e 'type == "array" and all(type == "array")' alerts.json > /dev/null; then
echo "::error::Unexpected response when reading code scanning alerts for ${REF}."
jq -c '.' alerts.json | head -c 500
exit 1
fi
count=$(jq '[.[][]] | length' alerts.json)
if [ "${count}" -ne 0 ]; then
jq -r '.[][] | " \(.rule.security_severity_level // .rule.severity)\t\(.rule.id)\t\(.most_recent_instance.location.path):\(.most_recent_instance.location.start_line)"' alerts.json
echo "::error::${count} open CodeQL alert(s) on ${REF}. Fix each one, or dismiss it in the security tab with a written reason. See docs/security-posture.md."
exit 1
fi
echo "No open CodeQL alerts on ${REF}."