ci(security): SHA-pin GitHub Actions in publish.yml (SEC-06) - #3
Conversation
Pin actions/checkout, actions/setup-java, actions/setup-node to immutable commit SHAs per 26-02 §2c. Config-only change; no-release proof recorded in 28-04 (C1-C6 PASS, EXISTS=true). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe PR pins three GitHub Actions to specific commit SHAs in the publish workflow instead of using floating version tags: ChangesCI Workflow Security
Poem
🎯 1 (Trivial) | ⏱️ ~3 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/publish.yml:
- Around line 22-24: The checkout action is leaving the job auth token in git
config by default; in the workflow step that uses actions/checkout (the entry
referencing actions/checkout@34e1148...), add the input persist-credentials:
false to the step so credentials are not written to the repo git config; update
the checkout step where fetch-depth: 0 is set to include persist-credentials:
false to harden credential handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: de13ad82-ef01-4493-9b2a-3f44c0fbc801
📒 Files selected for processing (1)
.github/workflows/publish.yml
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 (v4.3.1) | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/publish.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE" >&2
exit 1
fi
echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,120p'
echo "== grep checkout =="
rg -n "uses:\s*actions/checkout|persist-credentials|GH_TOKEN|gh " "$FILE" || trueRepository: UltiKits/UltiSocial
Length of output: 166
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/publish.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE" >&2
exit 1
fi
echo "== File: $FILE (first 160 lines) =="
cat -n "$FILE" | sed -n '1,160p'
echo "== checkout-related lines =="
rg -n "actions/checkout|persist-credentials|fetch-depth|GH_TOKEN|gh " "$FILE" || true
echo "== git command usage around tokens =="
rg -n "(git (push|config|credential)|GH_TOKEN|GITHUB_TOKEN|persist-credentials)" "$FILE" || trueRepository: UltiKits/UltiSocial
Length of output: 4984
🌐 Web query:
actions/checkout v4 persist-credentials default value
💡 Result:
The default value for the persist-credentials input in actions/checkout v4 is true [1][2]. When set to true (the default), the action configures the authentication token or SSH key in the local git configuration, which allows subsequent steps in your workflow to execute authenticated git commands [3][4]. The token is automatically removed during the post-job cleanup phase [5][6]. You can set persist-credentials to false if you wish to opt out of this behavior [3][6].
Citations:
- 1: https://github.com/actions/checkout/blob/v4/action.yml
- 2: https://github.com/actions/checkout/blob/v4.1.1/action.yml
- 3: https://github.com/actions/checkout/blob/v4/README.md
- 4: https://github.com/actions/checkout/tree/v4
- 5: https://github.com/actions/checkout/?tab=readme-ov-file
- 6: https://github.com/actions/checkout/tree/releases/v4.0.0
Harden actions/checkout credential handling by disabling credential persistence.
actions/checkout v4 defaults persist-credentials: true, which writes the auth token into the local git config for the job. This workflow doesn’t perform authenticated git operations (release actions use gh via GH_TOKEN), so disable persistence to reduce token exposure during subsequent build steps.
Suggested patch
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 (v4.3.1)
with:
fetch-depth: 0
+ persist-credentials: false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 (v4.3.1) | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 (v4.3.1) | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false |
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 22-24: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/publish.yml around lines 22 - 24, The checkout action is
leaving the job auth token in git config by default; in the workflow step that
uses actions/checkout (the entry referencing actions/checkout@34e1148...), add
the input persist-credentials: false to the step so credentials are not written
to the repo git config; update the checkout step where fetch-depth: 0 is set to
include persist-credentials: false to harden credential handling.
Source: Linters/SAST tools
SHA-pin GitHub Actions in
publish.yml(SEC-06)This PR applies a
uses:-SHA-value-only pin to the three GitHub Actions in.github/workflows/publish.yml— pasting the canonical SHA values for the actions already referenced at@v4. No version bump (still# v4), no trigger /if:/with:/env:/needs:/ step-order change. Part of GSD phase 28 (batch-3 cohort, plan 28-04).actions/checkout@v434e114876b0b11c390a56381ad16ebd13914f8d5# v4 (v4.3.1)actions/setup-java@v4c1e323688fd81a25caa38c78aa6df2d33d3e20d9# v4 (v4.8.0)actions/setup-node@v449933ea5288caeca8642d1e84afbd3f7d6820020# v4 (v4.4.0)Before → after pin lines
UltiSocial — C1–C6 no-release proof verdict (Archetype C, SEC-06)
Proof recorded in the 28-04 proof artifact (Task 1, proof-before-edit). All checks PASS for this module.
uses:lines confirmed@v4onorigin/master— L22actions/checkout@v4, L27actions/setup-java@v4, L94actions/setup-node@v4— plus a trailing# v4 (vX.Y.Z)comment. Noon:/trigger, noif:, nowith:, noenv:, noneeds:, no step ordering or job logic changed. (Re-verified viagit diff origin/masterin Task 3 — exactly 3 changed lines.)on: push: branches: [master](withpaths-ignore) +workflow_dispatch. Neither event is produced by the pin edit itself: a SHA-pin commit on a feature branch targetingmastervia PR does not trigger thepush: branches: [master]path until merge, and at merge the existing-version guard (C5) intercepts before any publish step. Nopull_requesttrigger.release-and-publish(permissions: contents: write). Stepcheck(Check if release exists) runsif gh release view "v${VERSION}" ... EXISTS=true ... else EXISTS=false. Every subsequent publish step is gatedif: steps.check.outputs.EXISTS == 'false'.EXISTSguard (C3/C5) are byte-identical pre/post pin. The set of conditions under which any publish step runs is unchanged. The pin cannot alterpom.xml<version>nor the release state, so it cannot flipEXISTS.v1.0.0is published onUltiKits/UltiSocial(not draft, not prerelease); tagv1.0.0→353a9ea4....pom.xmlproject<version>matches the publishedv1.0.0tag, so the workflow's existing-version guard resolvesEXISTS=trueand short-circuits every publish step. A SHA-only pin on a feature branch cannot flipEXISTS.PASS — config-only pin, unreachable-to-publish.EXISTS=true evidence
836ed96(origin/master)publish.ymlpresent on master (EXISTS=true), sha25636728f84...v1.0.0(tagv1.0.0→353a9ea4...), not draft / prerelease.uses:refs on master: L22actions/checkout@v4, L27actions/setup-java@v4, L94actions/setup-node@v4.Reference: 28-04 proof artifact (batch-3 cohort), maintainer token
approve 28-04-cohort-batch-3.Must NOT be merged until the maintainer's per-PR token with proof PASS + CI confirming no release/tag/publish fired.
Summary by CodeRabbit