Skip to content

Commit f130dd3

Browse files
EliahKaganclaude
andcommitted
ci: fail if any actions/checkout step persists credentials
Every `actions/checkout` step now sets `persist-credentials: false`. zizmor reports any that do not as `artipacked`, but only as code scanning alerts: it does not fail CI. A checkout that persists the `GITHUB_TOKEN` should fail CI, because it is riskier in this repository than in most. GitPython performs Git operations, and its test suite reads, clones, and runs Git commands against the repository it is tested in. That coupling may be intended or not, and it can let a test or library bug use or expose a persisted token. Add a `check-no-persist-credentials` job to the `Lint` workflow. It sparse-checks out `.github/workflows`, without persisting credentials itself, and uses `yq` to list every step in every workflow file that uses `actions/checkout` without `persist-credentials: false`. This includes a step with no `with:` block, a `with:` block without the input, and any other value. The job fails if anything is listed and prints each match as `file:line: name`. This is the same code as the job of the same name in gitoxide's CI (`.github/workflows/ci.yml`), copied from its current version. The only change is indentation, to match the step style of `lint.yml`. gitoxide's job also gates its `tests-pass` job, but this repository has no such aggregate job. The check does not replace zizmor's `artipacked` audit, which also looks for ways persisted credentials could end up in uploaded artifacts, and whose findings are tracked as code scanning alerts. Run locally with `yq` 4.54.1, the scan reports nothing for the workflows in this commit. In a scratch copy, removing the setting from both checkouts in `pythonpackage.yml` (one with other inputs and one with no `with:` block) and setting it to `true` in `lint.yml` made it report exactly those four steps and fail. A quoted `"false"` is not reported, which is correct, since action inputs are strings and `actions/checkout` treats it the same as `false`. `actionlint` reports two `info`-level SC2086 notes from `shellcheck`, for the unquoted `$GLOB`. Pathname expansion there is intended, as the inline comments say, so they are left as they are in gitoxide. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 63f42c9 commit f130dd3

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

‎.github/workflows/lint.yml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,30 @@ jobs:
2323
python-version: "3.x"
2424

2525
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
26+
27+
# Check that all `actions/checkout` in CI jobs have `persist-credentials: false`.
28+
check-no-persist-credentials:
29+
runs-on: ubuntu-slim
30+
31+
env:
32+
GLOB: .github/workflows/*.@(yaml|yml)
33+
34+
steps:
35+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
36+
with:
37+
persist-credentials: false
38+
sparse-checkout: ".github/workflows"
39+
- name: List workflows to be scanned
40+
run: |
41+
shopt -s extglob
42+
printf '%s\n' $GLOB # Pathname expansion in $GLOB intended.
43+
- name: Scan workflows
44+
run: |
45+
shopt -s extglob
46+
yq '.jobs.*.steps[]
47+
| select(.uses == "actions/checkout@*" and .with.["persist-credentials"]? != false)
48+
| {"file": filename, "line": line, "name": (.name // .uses)}
49+
| .file + ":" + (.line | tostring) + ": " + .name
50+
' -- $GLOB >query-output.txt # Pathname expansion in $GLOB intended.
51+
cat query-output.txt
52+
test -z "$(<query-output.txt)" # Report failure if we found anything.

0 commit comments

Comments
 (0)