ci: declare workflow-level contents: read on 6 workflows#2042
ci: declare workflow-level contents: read on 6 workflows#2042arpitjain099 wants to merge 1 commit into
contents: read on 6 workflows#2042Conversation
Pins the default GITHUB_TOKEN to contents: read on the workflows in .github/workflows/ that don't call a GitHub API beyond the initial checkout. The other workflows in this directory are left implicit because they need write scopes that a maintainer is better placed to declare. Motivation: CVE-2025-30066 (March 2025 tj-actions/changed-files compromise) exfiltrated GITHUB_TOKEN from workflow logs. Per-workflow caps bound runtime authority irrespective of repo or org default, give drift protection if the default ever widens, and are credited per-file by the OpenSSF Scorecard Token-Permissions check. YAML validated locally with yaml.safe_load. Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Greptile SummaryThis PR pins the
|
| Filename | Overview |
|---|---|
| .github/workflows/ci-main.yml | Adds workflow-level permissions: contents: read; no functional changes. Pre-existing action mutable-tag references are the only concern. |
| .github/workflows/ci-pull-request.yml | Adds workflow-level permissions: contents: read; all downstream jobs only need checkout and Docker operations that use external credentials. |
| .github/workflows/docker-build-arm.yml | Adds workflow-level permissions: contents: read; pre-existing echo of secret into a file is a latent shell-interpolation concern unrelated to this PR's change. |
| .github/workflows/integration-test-library-mode.yml | Adds workflow-level permissions: contents: read; all steps are checkout, Python setup, and pytest against external NIM endpoints authenticated via secret env vars. |
| .github/workflows/retriever-unit-tests.yml | Adds workflow-level permissions: contents: read; only requires checkout and running unit tests locally. |
| .github/workflows/scheduled-nightly.yml | Adds workflow-level permissions: contents: read; Docker push and PyPI/Artifactory publish use external credentials (DOCKER_PASSWORD, ARTIFACTORY_*), not GITHUB_TOKEN, so the restricted scope does not break publishing. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
subgraph before["Before PR"]
BT["GITHUB_TOKEN\n(org/repo default permissions)"]
end
subgraph after["After PR — all 6 workflows"]
AT["GITHUB_TOKEN\ncontents: read only\n(all other scopes → none)"]
end
subgraph operations["Token-independent operations (unchanged)"]
D["Docker push\n(DOCKER_PASSWORD secret)"]
P["PyPI / Artifactory publish\n(ARTIFACTORY_* secrets)"]
A["Artifact upload/download\n(ACTIONS_RUNTIME_TOKEN)"]
C["Repository checkout\n(contents: read ✓)"]
end
after --> C
after -.->|"not needed"| D
after -.->|"not needed"| P
after -.->|"not needed"| A
Comments Outside Diff (2)
-
.github/workflows/ci-main.yml, line 17-22 (link)Third-party actions pinned to mutable version tags
All six modified workflows reference third-party actions using mutable tags (e.g.,
actions/checkout@v4,actions/setup-python@v3,pre-commit/action@v3.0.1,astral-sh/setup-uv@v6,docker/setup-qemu-action@v3) rather than immutable commit SHAs. A mutable tag can be force-pushed to point at a different — potentially malicious — commit at any time, which is exactly the supply-chain attack vector this PR is hardening against. The same pattern appears in the other five touched workflows (ci-pull-request.yml,docker-build-arm.yml,integration-test-library-mode.yml,retriever-unit-tests.yml,scheduled-nightly.yml). Each action reference should be pinned to a full 40-character SHA, e.g.actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2.Prompt To Fix With AI
This is a comment left during a code review. Path: .github/workflows/ci-main.yml Line: 17-22 Comment: **Third-party actions pinned to mutable version tags** All six modified workflows reference third-party actions using mutable tags (e.g., `actions/checkout@v4`, `actions/setup-python@v3`, `pre-commit/action@v3.0.1`, `astral-sh/setup-uv@v6`, `docker/setup-qemu-action@v3`) rather than immutable commit SHAs. A mutable tag can be force-pushed to point at a different — potentially malicious — commit at any time, which is exactly the supply-chain attack vector this PR is hardening against. The same pattern appears in the other five touched workflows (`ci-pull-request.yml`, `docker-build-arm.yml`, `integration-test-library-mode.yml`, `retriever-unit-tests.yml`, `scheduled-nightly.yml`). Each action reference should be pinned to a full 40-character SHA, e.g. `actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2`. How can I resolve this? If you propose a fix, please make it concise.
-
.github/workflows/docker-build-arm.yml, line 28-32 (link)Secret interpolated directly into shell via
echoecho "${{ secrets.HF_ACCESS_TOKEN }}" > filebakes the secret value into the shell command string at substitution time. If the token contains shell metacharacters or newline characters, this can produce unexpected behavior or partial exposure. Compare this toreusable-docker-build.yml(line 79-84) which correctly injects the secret as an environment variable (env: HF_ACCESS_TOKEN: ${{ secrets.HF_ACCESS_TOKEN }}) and then writes it withprintf '%s' "${HF_ACCESS_TOKEN}"— that approach keeps the secret out of the evaluated command and is immune to shell word-splitting.Prompt To Fix With AI
This is a comment left during a code review. Path: .github/workflows/docker-build-arm.yml Line: 28-32 Comment: **Secret interpolated directly into shell via `echo`** `echo "${{ secrets.HF_ACCESS_TOKEN }}" > file` bakes the secret value into the shell command string at substitution time. If the token contains shell metacharacters or newline characters, this can produce unexpected behavior or partial exposure. Compare this to `reusable-docker-build.yml` (line 79-84) which correctly injects the secret as an environment variable (`env: HF_ACCESS_TOKEN: ${{ secrets.HF_ACCESS_TOKEN }}`) and then writes it with `printf '%s' "${HF_ACCESS_TOKEN}"` — that approach keeps the secret out of the evaluated command and is immune to shell word-splitting. How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
.github/workflows/ci-main.yml:17-22
**Third-party actions pinned to mutable version tags**
All six modified workflows reference third-party actions using mutable tags (e.g., `actions/checkout@v4`, `actions/setup-python@v3`, `pre-commit/action@v3.0.1`, `astral-sh/setup-uv@v6`, `docker/setup-qemu-action@v3`) rather than immutable commit SHAs. A mutable tag can be force-pushed to point at a different — potentially malicious — commit at any time, which is exactly the supply-chain attack vector this PR is hardening against. The same pattern appears in the other five touched workflows (`ci-pull-request.yml`, `docker-build-arm.yml`, `integration-test-library-mode.yml`, `retriever-unit-tests.yml`, `scheduled-nightly.yml`). Each action reference should be pinned to a full 40-character SHA, e.g. `actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2`.
### Issue 2 of 2
.github/workflows/docker-build-arm.yml:28-32
**Secret interpolated directly into shell via `echo`**
`echo "${{ secrets.HF_ACCESS_TOKEN }}" > file` bakes the secret value into the shell command string at substitution time. If the token contains shell metacharacters or newline characters, this can produce unexpected behavior or partial exposure. Compare this to `reusable-docker-build.yml` (line 79-84) which correctly injects the secret as an environment variable (`env: HF_ACCESS_TOKEN: ${{ secrets.HF_ACCESS_TOKEN }}`) and then writes it with `printf '%s' "${HF_ACCESS_TOKEN}"` — that approach keeps the secret out of the evaluated command and is immune to shell word-splitting.
Reviews (1): Last reviewed commit: "ci: declare workflow-level contents: rea..." | Re-trigger Greptile
Pins the default
GITHUB_TOKENtocontents: readon 6 workflows in.github/workflows/that don't call a GitHub API beyond the initial checkout.Why
CVE-2025-30066 (March 2025
tj-actions/changed-filessupply-chain compromise) exfiltratedGITHUB_TOKENfrom workflow logs. Pinning per workflow caps runtime authority irrespective of the repo or org default, gives drift protection if the default ever widens, and is credited per-file by the OpenSSF ScorecardToken-Permissionscheck.YAML validated locally with
yaml.safe_loadon each touched file.