docs: reference GEMINI_API_KEY env var in curl examples so gitleaks can be bumped - #1219
Conversation
Two Gemini `curl` snippets in the universal-automation-service prototype
notes embedded a scrubbed credential marker directly in an auth header:
-H 'X-goog-api-key: REDACTED_GOOGLE_API_KEY_ROTATE' \
That marker is a leftover from the secret purge, not a live key, but its
shape trips gitleaks' `curl-auth-header` rule. That rule does not exist in
the version CI currently pins (`GITLEAKS_VERSION=8.18.4` in
.github/workflows/secret-scan.yml), so the Secret Scan job is green today
and the problem is invisible -- it only detonates when somebody bumps the
pin, at which point Secret Scan fails on `main` for a reason unrelated to
their change.
Fix the cause rather than allowlisting the symptom: the snippets now read
the key from the environment, which both removes the trigger and is the
pattern the docs should be teaching. No entry is added to .gitleaks.toml,
so no future real credential is masked by this change.
The other ~18 `REDACTED_GOOGLE_API_KEY_ROTATE` occurrences in these docs
are `export GEMINI_API_KEY="..."` lines and historical incident notes.
They match no gitleaks rule and are left untouched.
Verified with both the pinned and a newer gitleaks:
gitleaks detect --no-git --config .gitleaks.toml --redact --exit-code 1
version before after
8.18.4 (CI pin) 0 leaks 0 leaks
8.30.0 2 leaks 0 leaks
Refs #1217
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
Agent Completion Truth Gate: NOT_APPLICABLEEvidence agrees. Machine-readable verdict{
"details": {},
"reasons": [],
"verdict": "not_applicable"
} |
There was a problem hiding this comment.
Pull request overview
Updates Gemini curl examples to source credentials from the environment, preventing newer gitleaks false positives and resolving #1217.
Changes:
- Replaces two redacted credential markers with
${GEMINI_API_KEY}. - Keeps secret scanning enabled without adding allowlists.
🟢 Merge-ready — awaiting human sign-offAutomated remediation pass (terminal-state record). Substantive state: this is a two-line documentation change ( Checks: combined commit status success on head One red remains — repo-wide, not this PR's fault: Terminal state: Accept the non-required Generated by Claude Code |
groupthinking
left a comment
There was a problem hiding this comment.
Review verdict: LGTM (posted as a comment — GitHub blocks approving one's own PR). Reviewed at head 2af0733.
This is a correct, minimal, low-risk fix. Verified:
- Diff is exactly as described: two
-Hlines indocs/knowledge_prototypes/universal-automation-service/TECHNICAL_NOTES.md, swapping theREDACTED_GOOGLE_API_KEY_ROTATEmarker for${GEMINI_API_KEY}. Docs-only — nothing under this path is imported by the Python package, built intoapps/web, or served by a route, so there is no runtime surface to regress. - Change is sound: the single→double quote switch is required for
${GEMINI_API_KEY}expansion in thecurlsnippets. Sourcing the key from the environment removes thecurl-auth-headershape that newer gitleaks matches on — precisely the CI-hygiene goal of #1217 — and is also better documentation than a pasted literal. - Scope discipline is right: leaving the ~18 other
export GEMINI_API_KEY="..."occurrences untouched is correct — they match no gitleaks rule at either version. Choosing not to add a.gitleaks.tomlallowlist is also the right call — an allowlist broad enough to cover this would mask a future real key pasted in the same shape. - CI: required checks are green (
build,test,lint-python,lint-frontend,bandit,trivy,CodeQL,gitleaks (working tree),dependency-review, security scans). The one failing check,Agent completion enforcement, is the pre-existing repo-wide fail-closed governance gate (empty trusted-publisher allowlist, tracked in #1160); it fires on every open PR and is not introduced by this diff. The neweragent-completion/truth-gatereportsnot_applicable / all rules passed, andmergeable_state: unstableis due to that non-required check, not a merge conflict.
Not merging from here: the publish decision belongs to a human. This PR carries only the documentation label (not automerge) and targets protected main, so the merge click stays with you. The follow-up GITLEAKS_VERSION bump this PR makes safe is likewise a separate, deliberate maintenance step.
Generated by Claude Code
|
Returned to draft during delivery control. The documentation-only change is linked to #1217, but no current execution receipt has been reconciled. Preserve the branch; do not advance until the focused unit and exact-head evidence are bound. |
Canonical issue
Closes #1217
Outcome
The
Secret Scanworkflow pinsGITLEAKS_VERSION="8.18.4"(.github/workflows/secret-scan.yml). Any bump past that pin fails onmain— not because a secret was introduced, but because newer gitleaks ships a defaultcurl-auth-headerrule that this repository's documentation trips.Two
curlsnippets in the universal-automation-service prototype notes embedded a scrubbed credential marker directly in an auth header:REDACTED_GOOGLE_API_KEY_ROTATEis a leftover marker from the credential purge, not a live key — butcurl-auth-headermatches on the shape of the invocation, not the value's entropy, so it fires regardless. Because the rule does not exist in 8.18.4, the failure is invisible today and only detonates for whoever bumps the pin, on a change unrelated to theirs.This PR removes the trigger at its source: the snippets now read the key from the environment.
That is a two-line change to a documentation file, and it is also simply better documentation — a runnable example that teaches sourcing the key from the environment rather than pasting it into a shell history.
Why not an allowlist
Adding a
.gitleaks.tomlentry was the obvious alternative and was rejected on three grounds:curl "https://..."line, not the-Hline — the rule matches across the multi-line invocation. The repo's single global[allowlist]block setsregexTarget = "line", so a regex written againstREDACTED_would be matched against a line that does not contain it. Making it work would mean a path allowlist fordocs/knowledge_prototypes/.*, retiring an entire docs tree from scanning.No
.gitleaks.tomlchange is included in this PR.Scope
-Hlines indocs/knowledge_prototypes/universal-automation-service/TECHNICAL_NOTES.md(lines 32 and 203). One file, two lines, no code.REDACTED_GOOGLE_API_KEY_ROTATEoccurrences acrossFINAL_STATUS.md,RUN_WITH_VENV.md,SETUP.md,COMPREHENSIVE_SYSTEMS_STATUS.mdand elsewhere in this file. I checked each: they areexport GEMINI_API_KEY="..."lines and historical incident notes, they match no gitleaks rule at either version, and rewriting them would turn a targeted CI fix into a sprawling docs diff with no security benefit.GITLEAKS_VERSIONitself. This PR proves the bump is safe; choosing the target version and re-pinning is a separate, deliberate maintenance decision that should not ride along with a docs change.Risk
docs/knowledge_prototypes/. No source, config, workflow, test, or dependency is touched; nothing is imported, built, or executed from this path.GEMINI_API_KEYexported and gets a 401 from Google instead of a 200. The previous snippet returned a 400/401 too, since the value it carried was a redaction marker rather than a working key, so the copy-paste experience is strictly improved, not degraded.git revertof a single documentation commit. No migration, no state, no coupling to any other change.GITLEAKS_VERSIONgets a redSecret Scanonmainand a false "we leaked a Google API key" signal, which is exactly the alarm-fatigue outcome a secret scanner must avoid.Verification
Run against head of this branch, using the exact command from
.github/workflows/secret-scan.yml:Both the currently pinned version and a much newer one were executed locally, before and after the change, giving a full 2×2 matrix rather than a one-sided claim:
no leaks found, exit 0no leaks found, exit 0RuleID: curl-auth-header,TECHNICAL_NOTES.mdlines 30 and 201no leaks found, exit 0mainproduced exactly the two findings described in Secret Scan will break on any gitleaks version bump: curl-auth-header flags placeholder in TECHNICAL_NOTES.md #1217, with the rule ID and both line numbers matching. The fix was written against a confirmed reproduction, not a hypothesis.no leaks foundand exits 0. This is the acceptance criterion in Secret Scan will break on any gitleaks version bump: curl-auth-header flags placeholder in TECHNICAL_NOTES.md #1217: the pin can be bumped without the scan going red.no leaks foundand exits 0, so today's CI is unaffected. The stashed-vs-restored runs above confirm 8.18.4 was green both before and after, isolating the change's effect to the newer version only.github.com/gitleaks/gitleaks/releases/download/v8.18.4/,gitleaks versionconfirms8.18.4, matching the pin byte-for-byte rather than assuming a locally-installed build behaves the same.git show --statconfirms the commit touches exactly one.mdfile, so no Python, TypeScript, or workflow code paths are reachable by this diff.Known-failing check, pre-existing and repo-wide: Agent completion enforcement requires a check run named
Agent Lock trusted publicationfrom a trusted GitHub App, and.github/agent-lock/trusted-publishers.jsonships with empty allowlists undercustom_role_policy: "fail_closed", with a note stating this "intentionally blocks". It fails on every open PR here (verified on #1122, #1207, #1216) and is tracked separately in #1160, which explicitly asks for a human decision.Production evidence
Not applicable as a runtime artifact, for a specific rather than blanket reason: the diff is confined to a Markdown file under
docs/knowledge_prototypes/, which is not imported by the Python package, not part of the Next.js build, and not served by any route. There is no deployed surface for this change to alter and therefore nothing to exercise in a preview environment.The evidence that matters for a CI-hygiene fix is the CI behaviour itself, and it is recorded above as real command output from two independently downloaded gitleaks binaries run against the real working tree — a genuine before/after reproduction rather than an assertion that the change "should" work.
Agent handoff
TECHNICAL_NOTES.mdor.gitleaks.tomlGITLEAKS_VERSIONbump. This PR makes it safe; it does not decide which version to move to.🤖 Generated with Copilot CLI
Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com