Skip to content

fix(ci): do not persist the job token in .git/config in the public-repo guard - #27

Closed
yakimoto wants to merge 1 commit into
mainfrom
fix/1870-persist-credentials-false
Closed

fix(ci): do not persist the job token in .git/config in the public-repo guard#27
yakimoto wants to merge 1 commit into
mainfrom
fix/1870-persist-credentials-false

Conversation

@yakimoto

@yakimoto yakimoto commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Why

actions/checkout without persist-credentials: false writes the job's GITHUB_TOKEN into
.git/config, where any later step — or anything those steps execute — can read it. This is the
security gate that DOWNLOADS AND EXECUTES the gitleaks binary, and the workflow's own comment
already reasons about tampered downloads ("so a tampered or MITM'd download can never execute
inside the security gate"), so the threat model is written down and only the credential half of
the mitigation is missing. Found by zizmor as warning[artipacked]: credential persistence through GitHub Actions artifacts.

Safety

Verified this job only: checks out, installs gitleaks (pinned + checksum), runs
gitleaks detect --no-git, installs ripgrep, runs content-policy.sh. permissions: contents: read. Nothing pushes, calls gh, or reads GITHUB_TOKEN/GH_TOKEN, so the token was never needed
in .git/config in the first place.

Refs wave-av/claude-workstation#1870.


Note

Low Risk
Single workflow security hardening with no change to scan logic or permissions; reduces credential exposure without affecting functionality.

Overview
Hardens the public-repo-guard workflow by setting persist-credentials: false on actions/checkout, so the job token is not stored in .git/config for later steps or anything they run.

This aligns with the workflow’s existing threat model (pinned, checksum-verified gitleaks download): the job only reads the tree and runs scans with contents: read, so persisted credentials were unnecessary exposure.

Reviewed by Cursor Bugbot for commit 92dd382. Configure here.

Review in cubic

…po guard

actions/checkout without persist-credentials:false leaves GITHUB_TOKEN readable
in .git/config for every later step — including the one that downloads and
executes the gitleaks binary. Nothing in this job uses the credential
(contents:read, gitleaks runs --no-git, no gh/push steps). Refs #1870.
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_cc717a75-e326-47d6-9e26-23f80138a922)

@macroscopeapp

macroscopeapp Bot commented Aug 6, 2026

Copy link
Copy Markdown

Approvability

Verdict: Approved 92dd382

Minor CI/CD security hardening that adds persist-credentials: false to prevent job token persistence in .git/config. Self-contained change to a workflow file owned by the author.

You can customize Macroscope's approvability policy. Learn more.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Harden public-repo-guard checkout by disabling credential persistence

🐞 Bug fix ⚙️ Configuration changes 🕐 Less than 5 minutes

Grey Divider

AI Description

• Disable persisted checkout credentials to keep GITHUB_TOKEN out of .git/config
• Reduce exposure for later steps that download and execute third-party binaries
Diagram

graph TD
  GH["GitHub Actions runner"] --> CO["actions/checkout"] --> CFG[".git/config"]
  CO -->|"persist-credentials: false"| CFG
  GH --> SCAN["Guard steps"]
  SCAN -->|"read repo"| CO
  subgraph Legend
    direction LR
    _proc["Step/Job"] ~~~ _file["File"]
  end
Loading
High-Level Assessment

Setting persist-credentials: false on actions/checkout is the most direct and standard mitigation to prevent GITHUB_TOKEN from being written to .git/config. Alternatives (e.g., deleting .git/config entries later or relying on step hygiene) are weaker and more error-prone than preventing persistence at the source.

Files changed (1) +2 / -0

Other (1) +2 / -0
public-repo-guard.ymlDisable checkout credential persistence for public-repo-guard +2/-0

Disable checkout credential persistence for public-repo-guard

• Adds 'persist-credentials: false' to the 'actions/checkout' step so the job GITHUB_TOKEN is not stored in '.git/config'. This reduces the blast radius of subsequent steps that download and execute tooling while preserving the job’s read-only behavior.

.github/workflows/public-repo-guard.yml

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

Open in Devin Review

Comment on lines +46 to +47
with:
persist-credentials: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Shared copy of the security-gate workflow still leaves the job credential on disk

The hardening step that stops the job's credential from being written to disk (persist-credentials: false at .github/workflows/public-repo-guard.yml:46-47) was added only to this repo's own copy and not to the shared template other repositories install from, so every repo that copies the gate keeps the old, unhardened behavior.
Impact: Repos adopting the published guard template continue to expose the build credential to later steps, so the fix does not actually reach the repos it was meant to protect.

Divergence between the live workflow and the vendored workflow template

workflow-templates/public-repo-guard.yml is the copy the org's "install on a new repo" flow uses (the header at .github/workflows/public-repo-guard.yml:16-19 instructs copying the workflow file alongside .gitleaks.toml and scripts/public-repo-guard/content-policy.sh). A diff of the two files shows the only difference is the two newly added lines; workflow-templates/public-repo-guard.yml:45 still has a bare - uses: actions/checkout@... with no with: block.

Prompt for agents
The PR adds `with: persist-credentials: false` to the checkout step in .github/workflows/public-repo-guard.yml but the identical vendored copy at workflow-templates/public-repo-guard.yml (the file other repos install) was not updated. Apply the same change there so the two stay in sync; also consider whether the other workflow templates that call actions/checkout need the same hardening.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 45 to +47
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
persist-credentials: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Same hardening missing on other org workflows using checkout

A repo-wide grep shows persist-credentials appears only in the file changed by this PR. Other workflows (.github/workflows/issue-ops-triage.yml, .github/workflows/ticket-hygiene.yml) and several workflow-templates/*.yml also use actions/checkout without it. Some of those legitimately need the token, but a follow-up sweep would make the hardening consistent org-wide.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +46 to +47
with:
persist-credentials: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Distributed guard workflow template still persists the job credential in .git/config

The hardening (persist-credentials: false) was applied only to .github/workflows/public-repo-guard.yml:46-47; the vendored copy at workflow-templates/public-repo-guard.yml:45, which is the version other repositories install, still checks out with credentials persisted. Any repo using that template continues to leave GITHUB_TOKEN readable in .git/config for subsequent steps, including the step that downloads and executes the gitleaks binary.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

No findings are available for this PR yet. Findings appear here once Qodo has reviewed the PR.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file

Confidence score: 3/5

  • In workflow-templates/public-repo-guard.yml, the persist-credentials: false hardening is still missing, so repositories that install from this template could inherit the old behavior and unintentionally expose checkout credentials in CI runs—mirror the fix from .github/workflows/public-repo-guard.yml into the vendored template to prevent propagation.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/public-repo-guard.yml">

<violation number="1" location=".github/workflows/public-repo-guard.yml:47">
P2: The credential-persistence fix (persist-credentials: false) was added here but the vendored template at workflow-templates/public-repo-guard.yml, which other repositories copy when installing this guard, still has a bare `actions/checkout` step with no `with:` block. Repos that install from that template will continue to leave GITHUB_TOKEN in `.git/config` for the same gitleaks-download step this PR is hardening. Apply the same `persist-credentials: false` change to workflow-templates/public-repo-guard.yml.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
persist-credentials: false

@cubic-dev-ai cubic-dev-ai Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The credential-persistence fix (persist-credentials: false) was added here but the vendored template at workflow-templates/public-repo-guard.yml, which other repositories copy when installing this guard, still has a bare actions/checkout step with no with: block. Repos that install from that template will continue to leave GITHUB_TOKEN in .git/config for the same gitleaks-download step this PR is hardening. Apply the same persist-credentials: false change to workflow-templates/public-repo-guard.yml.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/public-repo-guard.yml, line 47:

<comment>The credential-persistence fix (persist-credentials: false) was added here but the vendored template at workflow-templates/public-repo-guard.yml, which other repositories copy when installing this guard, still has a bare `actions/checkout` step with no `with:` block. Repos that install from that template will continue to leave GITHUB_TOKEN in `.git/config` for the same gitleaks-download step this PR is hardening. Apply the same `persist-credentials: false` change to workflow-templates/public-repo-guard.yml.</comment>

<file context>
@@ -43,6 +43,8 @@ jobs:
     steps:
       - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd  # v5.0.1
+        with:
+          persist-credentials: false
 
       # gitleaks' GitHub Action requires a paid license for organizations; the CLI
</file context>
Fix with cubic

@yakimoto

yakimoto commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

This PR is redundant with #23 (chore/guard-canonical-sync), which is already open and already contains this exact change.

Evidence — #23's diff to .github/workflows/public-repo-guard.yml includes:

+          # tree. Nothing here pushes -- the scan is `--no-git` over the working tree --
+          # so no step needs authenticated Git; drop it. (zizmor: artipacked)
+          persist-credentials: false

#23 is also broader than this PR: it syncs the whole vendored public-repo-guard trio to
the canonical source (wave-foundation/scaffolder/public-repo-guard) byte-for-byte, verified by
git blob SHA, rather than adding this one line in isolation.

Closing as redundant. This duplicate exists because the fan-out that opened this PR
(refs claude-workstation#1870) did not check for in-flight PRs touching the same file before
going out — #23 was already open. Merge #23 instead.

@yakimoto yakimoto closed this Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant