Skip to content

feat(security): add gitleaks secret scanning — this repo had none - #31

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/secret-scanning
Aug 6, 2026
Merged

feat(security): add gitleaks secret scanning — this repo had none#31
hyperpolymath merged 1 commit into
mainfrom
feat/secret-scanning

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

An estate-wide audit of secret-scanning coverage found this repository has no leak detection of any kind — no gitleaks, no trufflehog, nothing.

Measured across all 424 repositories:

state count
gitleaks 170 (47%)
gitleaks + a leftover trufflehog step 73 (20%)
trufflehog only 33 (9%)
nothing at all 88 (24%) ← including this one

Adds a caller of the estate's shared secret-scanner reusable: gitleaks over the whole working tree with --no-git, exiting non-zero on a finding, alongside its rust-secrets and shell-secrets jobs.

Two details that would fail silently if left out

secrets: inherit is required. Without it the gitleaks action's inner secrets.GITHUB_TOKEN is empty and the scan degrades quietly — passing while checking less, which is the precise failure this campaign exists to remove.

Where an actions.lock exists it gains a hand-authored [] entry. gh actions-lock skips reusable-workflow callers, so without it the workflow is rejected as startup_failure with no log and no check run.

Expect findings — and read them carefully

A first run on a repository that has never been scanned may surface real secrets, and anything it finds has been exposed for as long as it has been committed. Rotate what it names; deleting the line is not enough.

But expect false positives too, and do not widen the scanner to silence them. Test fixtures, spec vectors and security documentation are deliberately full of credential-shaped strings — one estate repo produced 12 findings, all of them fixtures and doc examples. The cure there was a narrow, path-anchored .gitleaks.toml, verified by planting a real key to confirm the scanner still fired.

The sweep re-verified from this checkout that no scanner already existed before writing, rather than trusting the audit that selected the repo.

Found during the 2026-08-05 estate CI/CD census.

🤖 Generated with Claude Code

An estate-wide audit of secret-scanning coverage found this repository has no
leak detection of any kind: no gitleaks, no trufflehog, nothing.

Measured across all 424 repositories: 170 had gitleaks, 73 had gitleaks plus a
leftover trufflehog step, 33 had trufflehog only, and 88 — this one among them
— had nothing at all.

Adds a caller of the estate's shared secret-scanner reusable, which runs
gitleaks over the whole working tree with --no-git and exits non-zero on a
finding, alongside its rust-secrets and shell-secrets jobs.

Two details that would fail silently if left out:

  - `secrets: inherit` is REQUIRED. Without it the gitleaks action's inner
    secrets.GITHUB_TOKEN is empty and the scan degrades quietly — passing
    while checking less, which is the failure this campaign exists to remove.
  - Where an actions.lock exists it gains a hand-authored [] entry for this
    file. gh actions-lock SKIPS reusable-workflow callers, so without it the
    workflow is rejected as startup_failure with no log and no check run.

Expect findings. A first run on a repository that has never been scanned may
surface real secrets, and any it finds have been exposed for as long as they
have been committed. Treat a red first run as information, not as a fault in
this change — and rotate anything it names rather than only deleting it.

The sweep re-verified from this checkout that no scanner already existed
before writing, rather than trusting the audit that selected the repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@gitar-bot

gitar-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime.
Learn more

Code Review ✅ Approved

Adds gitleaks secret scanning via the shared reusable workflow with inherited secrets and actions-lock configuration. No issues were found.

Auto-approved and auto-merge armed: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria. — merges when pipeline and required approvals pass.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Important

Your trial ends in 5 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more.

Was this helpful? React with 👍 / 👎 | Gitar

@gitar-bot

gitar-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ Gitar auto-approved this PR but could not enable auto-merge: auto-merge is disabled for this repository — enable "Allow auto-merge" in the repository settings.

@gitar-bot gitar-bot 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.

Gitar has auto-approved this PR and enabled auto-merge (configure)

@gitar-bot gitar-bot Bot added the gitar-approved Added by Gitar label Aug 5, 2026
@hyperpolymath

Copy link
Copy Markdown
Owner Author

⛔ HELD — this repo has a live credential exposed publicly

Do not merge this until the token in deploy-repos.sh is rotated.

Running the scanner against this checkout before merging found, on line 5:

export CLOUDFLARE_API_TOKEN=<40-char url-safe base62 value>
export CLOUDFLARE_ACCOUNT_ID=<matches a REAL Cloudflare account>

Evidence it is a live credential rather than a placeholder:

  • the account id on line 6 matches an actual Cloudflare account on the owner’s credentials
  • the token is 40 characters, url-safe base62 — Cloudflare’s exact format
  • it contains none of your / xxx / example / changeme / placeholder
  • it is in git history, not only the working tree
  • this repository is public

Assume it is compromised. Public repositories are continuously scraped for exactly this pattern. Rotating it is the first action; removing it from the file changes nothing while the old token remains valid.

Why nothing caught this until now

Cloudflare tokens carry no distinctive prefix — no ghp_, no sk-, no glpat- — so prefix-matching scanners walk straight past them. Only generic-api-key entropy detection finds them.

This is the exact case the estate’s own secret-scanner-reusable.yml header already cites: "a real token in deploy-repos.sh which both trufflehog --only-verified and default gitleaks missed." And this repository had no secret scanner at all until this PR — it was one of 88 in that state.

The other 4 findings here are benign

  • avow-lib/ffi/zig/src/example.zig:24.token = "abc123def456...", // Would be real token
  • telegram-bot/deno.lock (4) — lockfile integrity hashes

Sequence

  1. Rotate the Cloudflare token, check that account’s audit log
  2. Merge this PR so the repo is scanned from here on
  3. Separate PR: replace the hardcoded export with a repository secret
  4. Git-history purge is a separate decision — a previous PAT purge was deliberately declined, so it is not assumed here

hyperpolymath added a commit that referenced this pull request Aug 6, 2026
…Auth (#32)

`deploy-repos.sh` exported a live `CLOUDFLARE_API_TOKEN` on line 5, **in
a public repository, and in git history**.

## The token was never necessary

This is a **local developer script** — it runs wrangler against
`$HOME/Documents/hyperpolymath-repos`, not in CI. `wrangler login`
(OAuth) covers it completely: the session lives in
`~/.config/.wrangler/`, no long-lived credential exists at all, and it
is revocable from the dashboard.

The token existed because `export TOKEN=…` needs no setup step and OAuth
needs one. **The cheapest option at authoring time became a published
credential** — and it survived because nothing scanned this repository
until yesterday.

So this **deletes** rather than relocates it. There is nothing to move
into a secret store, because nothing needs a secret.

## What is kept, and why

The **account id is not a secret**. Cloudflare treats it as an ordinary
identifier and it appears in dashboard URLs. It earns its place because
this login can see more than one account. A comment now says so — so
nobody "tidies" it into a secret store, and nobody reintroduces the
token beside it.

Also switched `deno run -A npm:wrangler` → `bunx wrangler`, per the
Bun-over-Deno ruling. Both runtimes are installed locally; one-word
change.

## The allowlist deliberately does not cover source or scripts

`.gitleaks.toml` handles the four remaining findings, all benign:

- `telegram-bot/deno.lock` — content-addressed integrity hashes
- `telegram-bot/README.md`, `NEXT-STEPS.md` — setup docs describing
*where* a bot token goes
- `avow-lib/ffi/zig/src/example.zig` — carries the literal `.token =
"abc123def456..."` next to the comment `// Would be real token`

**Verified in both directions:**

| | findings |
|---|---:|
| with the allowlist | **0** |
| after re-introducing a token into `deploy-repos.sh` | **1** — still
caught |

That second row is the one that matters. An allowlist that reopened the
exact hole this repository just had would be worse than having no
scanner.

## ⚠ The exposed token must still be revoked

**Removing it from the file does not un-publish it.** It has been
readable by anyone for as long as this repo has been public, and public
repos are continuously scraped.

Dashboard → My Profile → API Tokens → delete it. **No replacement is
needed** once `wrangler login` has been run once.

Companion to #31 (which adds the scanner that found this). Merging both
leaves the repo scanned and clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@hyperpolymath
hyperpolymath merged commit e9fba79 into main Aug 6, 2026
14 of 20 checks passed
@hyperpolymath
hyperpolymath deleted the feat/secret-scanning branch August 6, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gitar-approved Added by Gitar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant