github-security-report 0.19.1__tar.gz → 0.20.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {github_security_report-0.19.1 → github_security_report-0.20.0}/PKG-INFO +341 -29
- {github_security_report-0.19.1 → github_security_report-0.20.0}/README.md +340 -28
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/_version.py +2 -2
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/categories/keys.py +4 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/categories/tables.py +102 -3
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/app.py +92 -51
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/boundary.py +23 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/modes.py +132 -167
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/options.py +42 -1
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/outputs.py +44 -5
- github_security_report-0.20.0/src/github_security_report/cli/progress.py +356 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/publish.py +4 -0
- github_security_report-0.20.0/src/github_security_report/cli/remediation.py +172 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/serialise.py +16 -0
- github_security_report-0.20.0/src/github_security_report/cli/summary.py +167 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/__init__.py +6 -1
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/accounting.py +103 -7
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/alerts.py +2 -2
- github_security_report-0.20.0/src/github_security_report/client/analyses.py +231 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/batch_errors.py +30 -20
- github_security_report-0.20.0/src/github_security_report/client/events.py +71 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/org_reads.py +15 -54
- github_security_report-0.20.0/src/github_security_report/client/paging.py +200 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/parsers.py +17 -14
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/queries.py +40 -2
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/reads.py +11 -122
- github_security_report-0.20.0/src/github_security_report/client/repo_parser.py +54 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/transport.py +84 -39
- github_security_report-0.20.0/src/github_security_report/client/workflow_runs.py +295 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/writes.py +7 -6
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/codeql/__init__.py +2 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/codeql/cleanup.py +41 -5
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/codeql/facts.py +24 -8
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/codeql/tables.py +39 -4
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/__init__.py +6 -0
- github_security_report-0.20.0/src/github_security_report/collect/context.py +309 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/extras.py +87 -27
- github_security_report-0.20.0/src/github_security_report/collect/graph.py +48 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/org.py +65 -25
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/protocols.py +28 -0
- github_security_report-0.20.0/src/github_security_report/collect/run_sync.py +319 -0
- github_security_report-0.20.0/src/github_security_report/collect/workflow_runs.py +320 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/config/__init__.py +11 -2
- github_security_report-0.19.1/src/github_security_report/config/loader.py → github_security_report-0.20.0/src/github_security_report/config/blocks.py +60 -186
- github_security_report-0.20.0/src/github_security_report/config/loader.py +213 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/config/models.py +96 -6
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/config/order.py +8 -4
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/config/schema.py +47 -0
- github_security_report-0.20.0/src/github_security_report/issue_presentation.py +186 -0
- github_security_report-0.20.0/src/github_security_report/issues.py +380 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/layout.py +26 -14
- github_security_report-0.20.0/src/github_security_report/malware.py +168 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/models.py +19 -5
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/remediate/__init__.py +9 -1
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/remediate/codeql.py +25 -4
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/remediate/model.py +11 -2
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/html.py +19 -1
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/markdown.py +33 -2
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/slack.py +29 -175
- github_security_report-0.20.0/src/github_security_report/render/slack_text.py +221 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/terminal.py +23 -12
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/report/__init__.py +4 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/report/aggregate.py +43 -2
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/report/display.py +18 -1
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/report/tables.py +25 -1
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/templates/report.html.j2 +1 -1
- github_security_report-0.20.0/src/github_security_report/workflow_runs/__init__.py +74 -0
- github_security_report-0.20.0/src/github_security_report/workflow_runs/aggregate.py +405 -0
- github_security_report-0.20.0/src/github_security_report/workflow_runs/models.py +184 -0
- github_security_report-0.20.0/src/github_security_report/workflow_runs/store.py +340 -0
- github_security_report-0.20.0/src/github_security_report/workflow_runs/store_codec.py +116 -0
- github_security_report-0.20.0/src/github_security_report/workflow_runs/tables.py +334 -0
- github_security_report-0.19.1/src/github_security_report/collect/context.py +0 -85
- github_security_report-0.19.1/src/github_security_report/collect/graph.py +0 -106
- github_security_report-0.19.1/src/github_security_report/issues.py +0 -370
- {github_security_report-0.19.1 → github_security_report-0.20.0}/.gitignore +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/LICENSE +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/LICENSES/Apache-2.0.txt +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/pyproject.toml +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/scripts/README.md +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/__init__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/authors.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/categories/__init__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/categories/signals.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/classify.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/__init__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/cli/__main__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/codeql_parsers.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/copilot.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/endpoints.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/errors.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/failures.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/client/reviews.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/code_quality.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/codeql.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/repo.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/collect/scoping.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/gating.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/gitctx.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/ordering.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/posture/__init__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/posture/enablement.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/posture/facts.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/posture/quality.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/posture/releases.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/pulls/__init__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/pulls/columns.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/pulls/counting.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/pulls/presentation.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/pulls/table.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/py.typed +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/ranking.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/__init__.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/slack_limits.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/render/terminal_notices.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/report/signals.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/rulesets.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/runner.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/scope.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/secret_patterns.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/severity.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/summary.py +0 -0
- {github_security_report-0.19.1 → github_security_report-0.20.0}/src/github_security_report/templates/index.html.j2 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: github-security-report
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: Security and quality reporting across GitHub organisations
|
|
5
5
|
Project-URL: Homepage, https://github.com/lfreleng-actions/github-security-report-action
|
|
6
6
|
Project-URL: Repository, https://github.com/lfreleng-actions/github-security-report-action
|
|
@@ -114,11 +114,14 @@ tables (org mode):
|
|
|
114
114
|
repository), the language, the last *successful* scan, and the cause:
|
|
115
115
|
analyses failing (a run that errors still uploads, but its results do not
|
|
116
116
|
count as a scan), default setup switched off, a workflow removed or
|
|
117
|
-
disabled,
|
|
117
|
+
disabled, an advanced workflow
|
|
118
118
|
**superseded** by default setup (GitHub rejects advanced CodeQL uploads
|
|
119
|
-
while default setup is on)
|
|
120
|
-
|
|
121
|
-
language
|
|
119
|
+
while default setup is on), or a configuration **superseded within its
|
|
120
|
+
workflow**: the workflow file still runs, but a change to its job id or
|
|
121
|
+
language matrix moved the language to another category, which a current
|
|
122
|
+
configuration from that same file now scans. An *orphaned* configuration
|
|
123
|
+
will never scan again; delete it from the tool status page once the live
|
|
124
|
+
setup covers its language.
|
|
122
125
|
- **Language Coverage** lists repositories where GitHub detects a
|
|
123
126
|
CodeQL-supported language that no current configuration scans — typically
|
|
124
127
|
an advanced workflow whose language matrix omits one the repository
|
|
@@ -156,6 +159,28 @@ tables (org mode):
|
|
|
156
159
|
window a reviewed dependency update sits in while the vulnerability it fixes
|
|
157
160
|
stays unpatched. Read from the batched GraphQL prefetch, so it costs no extra
|
|
158
161
|
request; hide it with the `auto_merge` render toggle.
|
|
162
|
+
- **Dependabot: Malware Findings** — one row per open Dependabot alert whose
|
|
163
|
+
advisory GitHub classifies as
|
|
164
|
+
[malware](https://docs.github.com/en/code-security/concepts/supply-chain-security/malware-alerts)
|
|
165
|
+
rather than a vulnerability: a dependency to remove, not upgrade. Each row
|
|
166
|
+
names the package (linked to the alert), its ecosystem and manifest, the
|
|
167
|
+
severity and the alert's age, most severe and then oldest first. The alerts
|
|
168
|
+
come from the organisation-wide Dependabot sweep the alerts signal already
|
|
169
|
+
makes, so the table costs no extra request. The footer counts repositories:
|
|
170
|
+
a repository with Dependabot alerts off, or whose state could not be read,
|
|
171
|
+
cannot raise one and counts as **Alerts off or unreadable**, never as
|
|
172
|
+
**No findings**. When the sweep is incomplete, the malware it did return is
|
|
173
|
+
still listed and fails its repository; only the repositories with none in
|
|
174
|
+
hand are unknown. GitHub's API does not expose whether the malware alerts
|
|
175
|
+
feature itself is switched on, neither per repository nor in a code-security
|
|
176
|
+
configuration, so a repository without findings has no malicious package
|
|
177
|
+
reported, which does not confirm coverage: the feature may be off. The
|
|
178
|
+
footer says so on every surface, and `remediate` cannot enable it. To switch
|
|
179
|
+
it on for every repository now, create or edit a custom security
|
|
180
|
+
configuration in the organisation's settings with *Dependabot → Malware
|
|
181
|
+
alerts: Enabled* and apply it to all repositories. The report cannot verify
|
|
182
|
+
the result. See [ADR-0008](docs/adr/0008-dependabot-malware-alerts.md); hide
|
|
183
|
+
the table with the `malware_findings` render toggle.
|
|
159
184
|
- **Code Quality** — repositories where
|
|
160
185
|
[GitHub Code Quality](https://docs.github.com/en/code-security/concepts/code-quality/code-quality)
|
|
161
186
|
is **Disabled**, or **Partial**: configured, but without a language the
|
|
@@ -176,6 +201,43 @@ tables (org mode):
|
|
|
176
201
|
`python 30/32 · go 5/5 · javascript-typescript 10/12`. See
|
|
177
202
|
[ADR-0006](docs/adr/0006-github-code-quality.md); hide it with the
|
|
178
203
|
`code_quality` render toggle.
|
|
204
|
+
- **Workflow Failures** — repositories whose GitHub Actions workflows failed
|
|
205
|
+
in the window, ranked by failed runs. The motivating case is the bulk
|
|
206
|
+
Dependabot merge whose integration tests need credentials, so they run
|
|
207
|
+
only once merged and never fail on the pull request; the table exists to
|
|
208
|
+
show which workflows fail, how often, and (in the detail table) whether a
|
|
209
|
+
pull request could have caught them. Each row gives **Failed** (runs that
|
|
210
|
+
concluded `failure`, `startup_failure`, `timed_out` or `action_required`),
|
|
211
|
+
**Runs** (every concluded run of every workflow in the repository),
|
|
212
|
+
**Fail %** (failed over failed *plus passed*, so skips never dilute it),
|
|
213
|
+
**Skipped** (skipped, cancelled, neutral and stale runs — a cancelled run
|
|
214
|
+
reached no verdict, and a bulk-merge round cancels hundreds of superseded
|
|
215
|
+
ones), **Retried** (runs that passed on a later attempt, a direct sign of
|
|
216
|
+
flakiness), **Workflows** (how many distinct workflows failed) and **Worst
|
|
217
|
+
workflow** (the one with the most failures, linked to its run history).
|
|
218
|
+
GitHub-managed workflows with no file in the repository to fix (Dependabot
|
|
219
|
+
updates, default-setup CodeQL, Copilot review) are left out unless
|
|
220
|
+
`workflow_runs.include_dynamic` is set. There is one table per time
|
|
221
|
+
window: seven days on the terminal and in Slack, and 7, 30 and 90 days on
|
|
222
|
+
GitHub Pages, where the later windows nest beneath the first. A repository
|
|
223
|
+
whose run listing could not be read this run (a token without Actions
|
|
224
|
+
read, a `5xx`) counts as **Unreadable**, never as failure-free, and a
|
|
225
|
+
footer note says when a window reaches further back than the stored
|
|
226
|
+
history does. The run history behind the table lives in a per-user
|
|
227
|
+
**run store**, so the first report against an organisation backfills the
|
|
228
|
+
longest window once and every later one asks GitHub only for what is new
|
|
229
|
+
— an unchanged repository costs a single conditional request that GitHub
|
|
230
|
+
answers `304` and does not charge. See
|
|
231
|
+
[Workflow run windows and store](#workflow-run-windows-and-store) and
|
|
232
|
+
[ADR-0007](docs/adr/0007-workflow-failures.md); hide it with the
|
|
233
|
+
`workflow_failures` render toggle. A per-workflow **detail** table
|
|
234
|
+
(`workflow_failures_detail`: workflow, file, failing job linked to its
|
|
235
|
+
newest log, pattern *persistent*/*intermittent*/*insufficient*, failing
|
|
236
|
+
triggers, and a **Reading** of *post-merge only*, *no PR runs*,
|
|
237
|
+
*everywhere* or *other*) is collected on every run but rendered nowhere
|
|
238
|
+
until `categories.workflow_failures_detail.enabled: true`; it stays off
|
|
239
|
+
Slack even then, being too wide for a chat digest, and is absent from
|
|
240
|
+
`report.json` while disabled.
|
|
179
241
|
|
|
180
242
|
The four enablement categories count the repositories with and without the
|
|
181
243
|
feature (plus any whose state could not be read), and by default name whichever
|
|
@@ -251,7 +313,7 @@ organisation and **Repository access** set to *All repositories*, then grant:
|
|
|
251
313
|
| Secret scanning alerts | Open secret-scanning alerts, across every GitHub pattern category |
|
|
252
314
|
| Issues | Open issues and their labels (GitHub Issues table) |
|
|
253
315
|
| Administration | Dependabot enablement + security-updates status, and effective branch rules. *Optional* **write** reads the Code Quality setup, which GitHub gates behind write |
|
|
254
|
-
| Actions | Workflow state behind a stale CodeQL configuration |
|
|
316
|
+
| Actions | Workflow state behind a stale CodeQL configuration, and the workflow run history behind the Workflow Failures tables (the run listing, single-run re-reads, and the GraphQL read of a failed run's check suite) |
|
|
255
317
|
|
|
256
318
|
**Organization permissions:**
|
|
257
319
|
|
|
@@ -271,7 +333,7 @@ organisations. Grant these scopes:
|
|
|
271
333
|
|
|
272
334
|
| Scope | Used for |
|
|
273
335
|
| ----- | -------- |
|
|
274
|
-
| `repo` | Repository data, including private repositories |
|
|
336
|
+
| `repo` | Repository data, including private repositories, and the workflow run history behind the Workflow Failures tables |
|
|
275
337
|
| `security_events` | Code scanning, secret scanning, and Dependabot alerts (org-bulk and per-repo) |
|
|
276
338
|
| `read:org` | Listing organisation repositories, and GitHub's secret-scanning pattern inventory (see below) |
|
|
277
339
|
| `admin:org` | *Optional* — reading organisation rulesets for ruleset-based tool coverage. GitHub gates `GET /orgs/{org}/rulesets` behind the full `admin:org` scope; `read:org` and `write:org` return 404. Omit it to skip that one signal; everything else is unaffected. |
|
|
@@ -377,6 +439,9 @@ environment-variable name, never embedded.
|
|
|
377
439
|
"issue_age_error_days": 60,
|
|
378
440
|
"graph_batch": 10,
|
|
379
441
|
"concurrency": 9,
|
|
442
|
+
"workflow_runs": {
|
|
443
|
+
"windows": { "cli": [7], "report": [7, 30, 90], "slack": [7] }
|
|
444
|
+
},
|
|
380
445
|
"order": { "style": "auto" }
|
|
381
446
|
},
|
|
382
447
|
"organizations": [
|
|
@@ -492,8 +557,10 @@ Pages output. The valid category keys are: `codeql`,
|
|
|
492
557
|
`zizmor`, `aislop`, `dependabot_alerts`, `secret_scanning`,
|
|
493
558
|
`dependabot_alerts_enabled`, `dependabot_updates_enabled`,
|
|
494
559
|
`dependabot_cooldown`, `releases`, `mutable_releases`,
|
|
495
|
-
`private_vulnerability_reporting`, `auto_merge`, `
|
|
496
|
-
`
|
|
560
|
+
`private_vulnerability_reporting`, `auto_merge`, `malware_findings`,
|
|
561
|
+
`code_quality`, `workflow_failures`, `workflow_failures_detail`, `github_issues`,
|
|
562
|
+
`github_issues_assigned`, `pull_requests`, `pull_requests_assigned`. Like the
|
|
563
|
+
other
|
|
497
564
|
`report` settings, `categories` can be set globally and overridden per
|
|
498
565
|
organisation (overrides merge key-by-key, so flipping one output leaves the
|
|
499
566
|
rest untouched). The
|
|
@@ -695,9 +762,9 @@ By default the report sorts its sections into three bands:
|
|
|
695
762
|
|
|
696
763
|
| Band | Contains | Why |
|
|
697
764
|
| ---- | -------- | --- |
|
|
698
|
-
| **Priority** | Secret Scanning, Dependabot: Security Alerts, CodeQL, Mutable Releases | Findings worth acting on today |
|
|
765
|
+
| **Priority** | Secret Scanning, Dependabot: Malware Findings, Dependabot: Security Alerts, CodeQL, Mutable Releases | Findings worth acting on today |
|
|
699
766
|
| **Middle** | Everything else | Neither urgent nor constant |
|
|
700
|
-
| **BAU** | OpenSSF Scorecard, GitHub Issues, Pull Requests, Assigned to Me | Carry data every run, so none of it is news |
|
|
767
|
+
| **BAU** | OpenSSF Scorecard, GitHub Issues, GitHub Issues: Assigned to Me, Pull Requests, Pull Requests: Assigned to Me | Carry data every run, so none of it is news |
|
|
701
768
|
|
|
702
769
|
The bands are not fixed slots. **A band member with nothing to report moves
|
|
703
770
|
into the middle**: a clean priority category is noise at the top of a page, and
|
|
@@ -771,6 +838,8 @@ cooldown) are not independently placeable. They render beneath the Dependabot
|
|
|
771
838
|
Alerts signal on every surface and travel with it, since three near-identical
|
|
772
839
|
headings adrift in the report would not say which signal they qualified.
|
|
773
840
|
Naming one in an ordering list is rejected rather than accepted and ignored.
|
|
841
|
+
The later windows of the Workflow Failures tables (30 and 90 days on GitHub
|
|
842
|
+
Pages) nest beneath the 7-day table in the same way and share its position.
|
|
774
843
|
|
|
775
844
|
### GitHub Issues
|
|
776
845
|
|
|
@@ -1154,7 +1223,7 @@ scheduled run publishes this to Pages, whatever token it holds:
|
|
|
1154
1223
|
This is not a configurable toggle. A published `Mine` is not a preference but a
|
|
1155
1224
|
false statement, so there is nothing to opt into.
|
|
1156
1225
|
|
|
1157
|
-
### Assigned to Me
|
|
1226
|
+
### Pull Requests: Assigned to Me
|
|
1158
1227
|
|
|
1159
1228
|
The `pull_requests_assigned` category repeats the Pull Requests table narrowed
|
|
1160
1229
|
to pull requests assigned to the account the report ran as — the same columns
|
|
@@ -1194,6 +1263,35 @@ name the category as well: `--hide` outranks this toggle and cannot be
|
|
|
1194
1263
|
countermanded by it. The input is empty by default, so this only matters if you
|
|
1195
1264
|
have set it.
|
|
1196
1265
|
|
|
1266
|
+
### GitHub Issues: Assigned to Me
|
|
1267
|
+
|
|
1268
|
+
The `github_issues_assigned` category does the same for issues: the GitHub
|
|
1269
|
+
Issues table narrowed to the open issues assigned to the account the report ran
|
|
1270
|
+
as, with the same columns. Everything above applies unchanged: "mine" follows
|
|
1271
|
+
the token, not a configured name; a bot or App token leaves the section absent;
|
|
1272
|
+
and it is **terminal-only by default**, so publishing it takes the same
|
|
1273
|
+
deliberate opt-in:
|
|
1274
|
+
|
|
1275
|
+
```json
|
|
1276
|
+
{
|
|
1277
|
+
"report": {
|
|
1278
|
+
"categories": {
|
|
1279
|
+
"github_issues_assigned": { "outputs": { "html": true } }
|
|
1280
|
+
}
|
|
1281
|
+
},
|
|
1282
|
+
"organizations": [{ "name": "lfreleng-actions" }]
|
|
1283
|
+
}
|
|
1284
|
+
```
|
|
1285
|
+
|
|
1286
|
+
The table reads the same window of each repository's oldest 25 open issues as
|
|
1287
|
+
GitHub Issues, so an issue assigned to you beyond that window, in a repository
|
|
1288
|
+
with a larger backlog, is not counted. Total is therefore the count of your
|
|
1289
|
+
issues *within* the window rather than GitHub's exact total, and a repository
|
|
1290
|
+
whose backlog exceeds the window with none of yours inside it counts as unknown
|
|
1291
|
+
rather than clean. `Oldest` reads `unknown` when an issue the run could not read
|
|
1292
|
+
precedes your oldest one in the window, since the unread issue may be older and
|
|
1293
|
+
yours.
|
|
1294
|
+
|
|
1197
1295
|
### Hiding a category for one run
|
|
1198
1296
|
|
|
1199
1297
|
`--hide <category>` (repeatable) suppresses a category on **every** output for
|
|
@@ -1212,9 +1310,10 @@ The Action exposes the same control through a `hide` input:
|
|
|
1212
1310
|
```
|
|
1213
1311
|
|
|
1214
1312
|
It is **empty by default**, and does not need setting to keep the personal
|
|
1215
|
-
|
|
1216
|
-
terminal only, so Pages,
|
|
1217
|
-
|
|
1313
|
+
queues out of shared artifacts — `pull_requests_assigned` and
|
|
1314
|
+
`github_issues_assigned` already default to the terminal only, so Pages,
|
|
1315
|
+
Markdown and Slack never render them, and `report.json` omits them for the same
|
|
1316
|
+
reason (see below). Leaving the input empty also keeps the
|
|
1218
1317
|
Action compatible with whichever published version the runtime pin installs: a
|
|
1219
1318
|
non-empty default would be passed to releases predating the flag, which reject
|
|
1220
1319
|
it outright.
|
|
@@ -1463,13 +1562,20 @@ one line of what the run cost, for example
|
|
|
1463
1562
|
<!-- markdownlint-disable MD013 -->
|
|
1464
1563
|
|
|
1465
1564
|
```text
|
|
1466
|
-
GitHub API for lfreleng-actions: 1402 requests (0 retries), 822 core points, 64 graphql points, 41.3 MiB received, 102.5 s
|
|
1565
|
+
GitHub API for lfreleng-actions: 1402 requests (REST 1338, GraphQL 64; 0 retries; 0 not modified), 822 core points, 64 graphql points, 0 rate-limit backoffs (0 s), 41.3 MiB received, 102.5 s
|
|
1467
1566
|
```
|
|
1468
1567
|
|
|
1469
1568
|
<!-- markdownlint-enable MD013 -->
|
|
1470
1569
|
|
|
1471
1570
|
The request count is every request the tool issued, including retries and
|
|
1472
|
-
attempts that never got an answer
|
|
1571
|
+
attempts that never got an answer; the split names what was asked (a REST
|
|
1572
|
+
endpoint, the GraphQL endpoint, or the external Scorecard API), and `not
|
|
1573
|
+
modified` is how many conditional reads the run store made that GitHub
|
|
1574
|
+
answered `304` at no cost. The backoffs are the pauses GitHub's rate limiting
|
|
1575
|
+
forced, with the seconds slept for them. The same figures appear in the run
|
|
1576
|
+
summary printed before each report (see
|
|
1577
|
+
[Progress and run summary](#progress-and-run-summary)). The points come from
|
|
1578
|
+
GitHub's own
|
|
1473
1579
|
`x-ratelimit-*` response headers rather than from counting: GitHub meters a
|
|
1474
1580
|
token across more than one bucket per resource (alike requests seconds apart
|
|
1475
1581
|
can carry different `x-ratelimit-reset` values with independent counters), so
|
|
@@ -1481,6 +1587,150 @@ bill. Nothing of this line reaches the rendered report or the step summary.
|
|
|
1481
1587
|
> As with `graph_batch`, an empty input is not passed to the tool, so set
|
|
1482
1588
|
> `GSR_CONCURRENCY` only once the pinned release supports `--concurrency`.
|
|
1483
1589
|
|
|
1590
|
+
### Workflow run windows and store
|
|
1591
|
+
|
|
1592
|
+
The Workflow Failures tables are the one part of the report built from
|
|
1593
|
+
history rather than from a repository's current state, so they have their
|
|
1594
|
+
own block, `report.workflow_runs`, settable globally or per organisation
|
|
1595
|
+
like every other `report` key. Every key with its default:
|
|
1596
|
+
|
|
1597
|
+
```json
|
|
1598
|
+
{
|
|
1599
|
+
"report": {
|
|
1600
|
+
"workflow_runs": {
|
|
1601
|
+
"windows": { "cli": [7], "report": [7, 30, 90], "slack": [7] },
|
|
1602
|
+
"retention_days": 90,
|
|
1603
|
+
"backfill_days": 90,
|
|
1604
|
+
"include_dynamic": false,
|
|
1605
|
+
"exclude_workflows": [],
|
|
1606
|
+
"collapse_matrix": true,
|
|
1607
|
+
"persistent_threshold": 0.9,
|
|
1608
|
+
"min_runs": 3,
|
|
1609
|
+
"cache": true
|
|
1610
|
+
}
|
|
1611
|
+
},
|
|
1612
|
+
"organizations": [{ "name": "lfreleng-actions" }]
|
|
1613
|
+
}
|
|
1614
|
+
```
|
|
1615
|
+
|
|
1616
|
+
`windows` maps each surface to the windows it shows, in days: `cli` is the
|
|
1617
|
+
terminal, `report` the GitHub Pages Markdown and HTML, and `slack` the
|
|
1618
|
+
digest. The terminal and Slack get the week; the published report adds the
|
|
1619
|
+
month and the quarter, where a reader has room to compare them. A table is
|
|
1620
|
+
built for every window any surface names, titled with its window (`Workflow
|
|
1621
|
+
Failures (30 days)`), and each surface draws its own. The map merges **per
|
|
1622
|
+
surface**, so an organisation that narrows the Slack windows keeps the
|
|
1623
|
+
inherited `report` ones; a list replaces the inherited list for that surface
|
|
1624
|
+
rather than adding to it.
|
|
1625
|
+
|
|
1626
|
+
`retention_days` is how long the run store keeps a record and
|
|
1627
|
+
`backfill_days` how far back a repository never seen before is read. Both
|
|
1628
|
+
default to the **longest configured window** (90 days with the default
|
|
1629
|
+
windows), which is the most any table can use; `backfill_days` is bounded by
|
|
1630
|
+
the retention. A `retention_days` shorter than the longest window is
|
|
1631
|
+
**rejected** at load time rather than accepted: the store would prune
|
|
1632
|
+
records a table still shows, and the window would quietly cover less than
|
|
1633
|
+
its title claims.
|
|
1634
|
+
|
|
1635
|
+
`include_dynamic` admits the GitHub-managed workflows (Dependabot updates,
|
|
1636
|
+
default-setup CodeQL, Copilot review), whose runs carry a `dynamic/` path
|
|
1637
|
+
and no file in the repository; they are left out by default because nobody
|
|
1638
|
+
can edit them. `exclude_workflows` is a list of globs matched against the
|
|
1639
|
+
workflow path (`.github/workflows/experimental-*.yaml`) for workflows whose
|
|
1640
|
+
failures are expected, such as a deliberately failing canary.
|
|
1641
|
+
`collapse_matrix` folds matrix legs (`Build (ubuntu-22.04)` and
|
|
1642
|
+
`Build (ubuntu-24.04)`) into one job name in the detail table.
|
|
1643
|
+
`persistent_threshold` and `min_runs` feed the detail table's **Pattern**
|
|
1644
|
+
column: a workflow failing at or above the threshold is *persistent* (fix
|
|
1645
|
+
the root cause), below it *intermittent* (harden the workflow), and with
|
|
1646
|
+
fewer than `min_runs` runs that reached a verdict *insufficient* to say. Both
|
|
1647
|
+
judge the same pass-or-fail population that Fail % does, so skips count
|
|
1648
|
+
towards neither.
|
|
1649
|
+
|
|
1650
|
+
`cache` and `cache_dir` govern the **run store**, a SQLite file per
|
|
1651
|
+
organisation at
|
|
1652
|
+
|
|
1653
|
+
```text
|
|
1654
|
+
$XDG_CACHE_HOME/github-security-report/<api-host>/<org>/runs.sqlite
|
|
1655
|
+
# or, when XDG_CACHE_HOME is unset:
|
|
1656
|
+
~/.cache/github-security-report/<api-host>/<org>/runs.sqlite
|
|
1657
|
+
```
|
|
1658
|
+
|
|
1659
|
+
keyed by API host as well as organisation, since the same name can exist on
|
|
1660
|
+
github.com and on an enterprise instance. The store is a cache, never a
|
|
1661
|
+
source of truth: everything in it can be rebuilt from GitHub, a schema
|
|
1662
|
+
change between releases drops and recreates it rather than migrating it,
|
|
1663
|
+
and deleting the file costs exactly one backfill. `cache: false` keeps the
|
|
1664
|
+
store in memory for the run alone, so every window is re-read from GitHub
|
|
1665
|
+
and nothing is left behind; `cache_dir` relocates it.
|
|
1666
|
+
|
|
1667
|
+
Four flags adjust this for one run, each mirrored as an action input:
|
|
1668
|
+
|
|
1669
|
+
<!-- markdownlint-disable MD013 -->
|
|
1670
|
+
|
|
1671
|
+
| Flag | Input | Effect |
|
|
1672
|
+
| ---- | ----- | ------ |
|
|
1673
|
+
| `--run-windows 7,30,90` | `run_windows` | Replaces the windows of **every** surface with one list, the shape a one-off investigation wants ("show me 14 days") |
|
|
1674
|
+
| `--no-run-cache` | `no_run_cache` | Keeps the store in memory for this run (`cache: false`) |
|
|
1675
|
+
| `--run-cache-dir PATH` | `run_cache_dir` | Relocates the store (`cache_dir`) |
|
|
1676
|
+
| `--refresh-runs` | `refresh_runs` | Ignores what the store holds and re-reads every repository for the longest window, at the cost of one backfill |
|
|
1677
|
+
|
|
1678
|
+
<!-- markdownlint-enable MD013 -->
|
|
1679
|
+
|
|
1680
|
+
Repo mode reads one repository's runs afresh each time into an in-memory
|
|
1681
|
+
store, and reads the `cli` windows alone (a week, by default) rather than the
|
|
1682
|
+
published report's quarter: a pull request's CI or a developer's shell should
|
|
1683
|
+
leave nothing behind, and a 90-day backfill for one table nobody publishes
|
|
1684
|
+
from that mode would be waste. `--run-windows` applies there; the three store
|
|
1685
|
+
flags are refused rather than accepted and ignored.
|
|
1686
|
+
|
|
1687
|
+
In GitHub Actions the runner's home directory is discarded with the job, so
|
|
1688
|
+
the bundled `reporting.yaml` keeps the store in the Actions cache between
|
|
1689
|
+
runs, under a key unique to the run (`gsr-runs-${{ github.run_id }}`) with a
|
|
1690
|
+
`gsr-runs-` restore prefix that picks up the newest earlier store. A daily
|
|
1691
|
+
schedule keeps the entry inside GitHub's seven-day cache eviction. The save
|
|
1692
|
+
runs whatever the report step's outcome, because the store is written in
|
|
1693
|
+
transactions: a run that aborted part-way still leaves it consistent, and
|
|
1694
|
+
the repositories it did sync need not be re-read.
|
|
1695
|
+
|
|
1696
|
+
The store is cached **encrypted**. It names every in-scope repository's
|
|
1697
|
+
branches, workflow files and failing jobs, private repositories included
|
|
1698
|
+
when the token can read them, and GitHub lets a pull request from a fork
|
|
1699
|
+
restore any cache saved on the default branch, which the `production`
|
|
1700
|
+
environment's protection rules do not cover. The workflow therefore
|
|
1701
|
+
encrypts the store with `openssl enc -aes-256-cbc -pbkdf2` under a key held
|
|
1702
|
+
in the environment's secret `GSR_RUN_STORE_KEY` (any long random string;
|
|
1703
|
+
`openssl rand -base64 48` makes one) before saving, and decrypts it after
|
|
1704
|
+
restoring. Without the secret the store is neither restored nor saved, a
|
|
1705
|
+
notice says so, and each run reads its windows from GitHub again — correct,
|
|
1706
|
+
only slower and dearer. A store that fails to decrypt, after a key rotation,
|
|
1707
|
+
is discarded with a warning and rebuilt. A caller's own workflow needs the
|
|
1708
|
+
same steps, or every scheduled run pays the backfill.
|
|
1709
|
+
|
|
1710
|
+
The point of the store is that repeated runs are nearly free. Each sync
|
|
1711
|
+
presents the listing's ETag, so an unchanged repository answers `304`, which
|
|
1712
|
+
GitHub does not count against the rate limit; a changed one is read newest
|
|
1713
|
+
first down to the last run already held. Re-runs keep their original
|
|
1714
|
+
timestamp and so never cross that watermark, which is why each sync also
|
|
1715
|
+
re-reads the window's failure list (conditionally, with its own ETag) when
|
|
1716
|
+
the listing moved and re-reads any stored failure missing from it — a run
|
|
1717
|
+
leaves that list when a retry passes, and the table's **Retried** column is
|
|
1718
|
+
built from exactly those. Runs stored while still in progress are re-read
|
|
1719
|
+
until they conclude, at most fifty single-run reads per repository per sync.
|
|
1720
|
+
The failing jobs of each failed run come from one GraphQL query per fifty
|
|
1721
|
+
runs, costing a point apiece.
|
|
1722
|
+
|
|
1723
|
+
Measured on `lfreleng-actions`, warm runs in the same hour: the full report
|
|
1724
|
+
cost 1,830 requests, 1,558 core rate-limit points and 116 s before this
|
|
1725
|
+
work; 1,130 requests, 849 points and 95 s once the code-scanning and
|
|
1726
|
+
repository-feature probes were consolidated onto pages the run already
|
|
1727
|
+
read; and 1,136 requests, 838 points and 82 s once the collection phases
|
|
1728
|
+
overlapped. The run store adds about one request per repository to a warm
|
|
1729
|
+
run, mostly free `304`s. A cold 90-day backfill, the first run against an
|
|
1730
|
+
organisation or any run without the cache, is about 1,500 requests, once;
|
|
1731
|
+
`--refresh-runs` and deleting the store each cost the same again. The store
|
|
1732
|
+
is about 25 MB for a 140-repository organisation.
|
|
1733
|
+
|
|
1484
1734
|
### Pass/fail severity cutoff
|
|
1485
1735
|
|
|
1486
1736
|
The severity-ranked signals (CodeQL, Scorecard, Zizmor, aislop, Dependabot
|
|
@@ -1560,6 +1810,11 @@ and the Slack **bot token** is consumed by the workflow, not the CLI.
|
|
|
1560
1810
|
| `hide` | No | `""` | Category keys to suppress on every output (space- or comma-separated). Overrides config, and is one-way: it cannot re-enable a disabled category |
|
|
1561
1811
|
| `graph_batch` | No | `""` | Repositories per batched GraphQL prefetch query (minimum `1`; default: config, else `10`). Pass a repository or organisation variable such as `${{ vars.GSR_GRAPH_BATCH }}` to adjust it from settings. A batch that still fails is halved automatically, so this sets the starting size (see [GraphQL prefetch batch size](#graphql-prefetch-batch-size)) |
|
|
1562
1812
|
| `concurrency` | No | `""` | Concurrent GitHub API requests per organisation (`1` to `32`; default: config, else `9`). Pass a repository or organisation variable such as `${{ vars.GSR_CONCURRENCY }}` to adjust it from settings (see [Client concurrency](#client-concurrency)) |
|
|
1813
|
+
| `run_windows` | No | `""` | Time windows, in days, for the Workflow Failures tables on every output (comma-separated, e.g. `7,30,90`; default: config, else `7` on the terminal and Slack and `7,30,90` on GitHub Pages; see [Workflow run windows and store](#workflow-run-windows-and-store)) |
|
|
1814
|
+
| `run_cache_dir` | No | `""` | Directory for the workflow-run store (default: `$XDG_CACHE_HOME/github-security-report`, i.e. `~/.cache/github-security-report` on a runner). Restore and save it with `actions/cache`, as the bundled `reporting.yaml` does, so each scheduled run reads only what is new |
|
|
1815
|
+
| `refresh_runs` | No | `false` | Re-read every repository's workflow runs for the longest window, ignoring what the run store already holds |
|
|
1816
|
+
| `no_run_cache` | No | `false` | Keep the workflow-run store in memory for this run instead of on disk, so every window is re-read from GitHub and nothing is left behind |
|
|
1817
|
+
| `no_progress` | No | `false` | Do not show the live progress line while collecting. The action runs under `CI`, where the line is already off; set this when running the CLI from the action's source on a terminal (see [Progress and run summary](#progress-and-run-summary)) |
|
|
1563
1818
|
| `tool_version` | No | `""` | Published PyPI version to install. Empty (the default) uses the Dependabot-managed pin in `.github/runtime-pin/requirements.txt`; set a specific version to override. Ignored on pull requests or when `use_local_source` is `true` (both run from source) |
|
|
1564
1819
|
| `use_local_source` | No | `false` | Run from the checked-out source instead of PyPI (for testing unreleased code from any event) |
|
|
1565
1820
|
|
|
@@ -1587,6 +1842,59 @@ uvx github-security-report report
|
|
|
1587
1842
|
uvx github-security-report report --org lfreleng-actions
|
|
1588
1843
|
```
|
|
1589
1844
|
|
|
1845
|
+
An org-mode run keeps its workflow-run store under
|
|
1846
|
+
`$XDG_CACHE_HOME/github-security-report` (`~/.cache/github-security-report`
|
|
1847
|
+
by default), so the first run against an organisation is slower than the
|
|
1848
|
+
rest; see [Workflow run windows and store](#workflow-run-windows-and-store).
|
|
1849
|
+
Repo mode leaves nothing behind.
|
|
1850
|
+
|
|
1851
|
+
### Progress and run summary
|
|
1852
|
+
|
|
1853
|
+
On an interactive terminal an org-mode run keeps one live line at the bottom
|
|
1854
|
+
of the screen while it collects: the organisation, the phase it is in, the
|
|
1855
|
+
repository count where the phase works per repository, the REST and GraphQL
|
|
1856
|
+
request counts with how many are in flight, and the elapsed time. A second
|
|
1857
|
+
line appears while GitHub has the run paused for a rate limit, and while the
|
|
1858
|
+
workflow-run store is being built for the first time, since that one-off
|
|
1859
|
+
dominates a cold run. Warnings logged in the meantime are held and replayed,
|
|
1860
|
+
in order, once the line comes down.
|
|
1861
|
+
|
|
1862
|
+
<!-- markdownlint-disable MD013 -->
|
|
1863
|
+
|
|
1864
|
+
```text
|
|
1865
|
+
⠧ lfreleng-actions · probing repositories · 41/120 repos · REST 812 (9 in flight) · GraphQL 24 · 38.2 s
|
|
1866
|
+
⏳ rate limited by GitHub (core); resuming in 42 s
|
|
1867
|
+
```
|
|
1868
|
+
|
|
1869
|
+
<!-- markdownlint-enable MD013 -->
|
|
1870
|
+
|
|
1871
|
+
Before each organisation's report, a dim three-line summary says what the
|
|
1872
|
+
run cost and what the store holds, so a slow run explains itself without
|
|
1873
|
+
`--verbose`:
|
|
1874
|
+
|
|
1875
|
+
<!-- markdownlint-disable MD013 -->
|
|
1876
|
+
|
|
1877
|
+
```text
|
|
1878
|
+
Run summary for lfreleng-actions
|
|
1879
|
+
requests: 1 234 requests (REST 1 100 · GraphQL 120 · external 14 · 300 not modified) · 12.3 MiB · 95.2 s
|
|
1880
|
+
rate limit: 980 core points · 230 graphql points · 0 backoffs
|
|
1881
|
+
workflow-run store: 4.2 MiB · 12 340 runs · 180 repositories · this run: 180 synced, 160 unchanged, 340 written
|
|
1882
|
+
```
|
|
1883
|
+
|
|
1884
|
+
<!-- markdownlint-enable MD013 -->
|
|
1885
|
+
|
|
1886
|
+
The rate-limit line turns yellow when a backoff happened or a resource's
|
|
1887
|
+
remaining budget fell under a tenth of its limit. A first-time build of the
|
|
1888
|
+
store on disk is marked `built (first run)`; a run with `--no-run-cache`
|
|
1889
|
+
reads `in memory (not cached)` and, since its store is empty every time, is
|
|
1890
|
+
never a first run. The summary is for the terminal only: nothing of it
|
|
1891
|
+
reaches the Markdown, HTML, JSON or Slack output.
|
|
1892
|
+
|
|
1893
|
+
The live line is off under `--no-progress`, when `CI` is set, when stdout is
|
|
1894
|
+
not a terminal, and with `--verbose`, whose log lines would fight it for the
|
|
1895
|
+
screen. The summary prints in every case. The same figures reach the log at
|
|
1896
|
+
`INFO` under `--verbose`.
|
|
1897
|
+
|
|
1590
1898
|
### GitHub Enterprise Server
|
|
1591
1899
|
|
|
1592
1900
|
The API endpoints honour the standard environment variables that GitHub
|
|
@@ -1696,7 +2004,10 @@ endpoint:
|
|
|
1696
2004
|
| `codeql_stale_configurations` | Stale CodeQL cleanup (named only; deletes) |
|
|
1697
2005
|
|
|
1698
2006
|
Qualitative findings (Scorecard, zizmor, open Dependabot alerts, cooldown,
|
|
1699
|
-
release freshness/mutability) are reported but not auto-remediated.
|
|
2007
|
+
release freshness/mutability) are reported but not auto-remediated. Dependabot
|
|
2008
|
+
malware alerts are not remediable either: GitHub exposes no API that reads or
|
|
2009
|
+
switches on the feature, so `remediate` leaves it out until one exists (see
|
|
2010
|
+
[ADR-0008](docs/adr/0008-dependabot-malware-alerts.md)). Remediation
|
|
1700
2011
|
is organisation-scoped (`--scope org`, the default and only supported scope).
|
|
1701
2012
|
|
|
1702
2013
|
The last two run **only when named** with `--category`, and the no-argument
|
|
@@ -1752,9 +2063,9 @@ cause:
|
|
|
1752
2063
|
|
|
1753
2064
|
| Cause | Action |
|
|
1754
2065
|
| ----- | ------ |
|
|
1755
|
-
| Default setup disabled; workflow removed; superseded by default setup; language removed from default setup | **Delete** the configuration: it can never upload again |
|
|
2066
|
+
| Default setup disabled; workflow removed; superseded by default setup; superseded within its workflow; language removed from default setup | **Delete** the configuration: it can never upload again |
|
|
1756
2067
|
| Workflow disabled after inactivity | **Re-enable** the workflow, restoring the scan |
|
|
1757
|
-
| Analyses failing, default setup changing state or not uploading, uploaded outside GitHub Actions, workflow disabled by hand, active but not uploading, or state unreadable |
|
|
2068
|
+
| Analyses failing, default setup changing state or not uploading, uploaded outside GitHub Actions, workflow disabled by hand, active but not uploading, or state unreadable | Listed as skipped, with its cause; needs a person |
|
|
1758
2069
|
|
|
1759
2070
|
<!-- markdownlint-enable MD013 -->
|
|
1760
2071
|
|
|
@@ -1773,15 +2084,16 @@ when:
|
|
|
1773
2084
|
blocks nothing;
|
|
1774
2085
|
- the repository's open alerts cannot be read.
|
|
1775
2086
|
|
|
1776
|
-
Refusals are listed beside the work done and do not fail the run.
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
the
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
2087
|
+
Refusals are listed beside the work done and do not fail the run. So is every
|
|
2088
|
+
row left for a person: each is listed as skipped, with its cause, so an
|
|
2089
|
+
operator can see what remains. Deletion is paced at one request a second
|
|
2090
|
+
across the whole run, as GitHub asks of mutating requests, and is resumable:
|
|
2091
|
+
an interrupted run's next pass picks up the remaining analyses. GitHub answers
|
|
2092
|
+
requests it will not authorise with `404`, so a deletion's `404` counts as
|
|
2093
|
+
already done only once the analysis also reads back as gone; a token that may
|
|
2094
|
+
not delete fails instead of reporting a cleanup that never happened. The token
|
|
2095
|
+
needs the classic `repo` scope. See
|
|
2096
|
+
[ADR-0005](docs/adr/0005-codeql-configuration-cleanup.md) for the reasoning.
|
|
1785
2097
|
|
|
1786
2098
|
## Bulk Remediation Scripts
|
|
1787
2099
|
|