Skip to content

Git history has never been scanned for secrets, and it is now public #278

Description

@jpr5

The full git history of this repo has never been scanned for committed secrets. The repo went public on 2026-09-14, so that history is now public too — every commit, every branch, every blob reachable from them.

Carried forward from #219, which listed "no secrets in git history" as a prerequisite for going source-available. The repo went source-available without the scan having been run.

Why this is not already handled

We redacted and deleted GitHub issues containing credentials. That work does not touch this. Issues live in GitHub's issue store; a secret pasted into a source file, a .env, a test fixture, a workflow file, a lockfile or a commit message lives in the git object tree, and nothing we did to the issues removed anything from the tree. The two are entirely separate stores and need entirely separate remediation.

The repo has a long private development history with live integrations — Discord, Slack, Teams, Linear, GitHub App, Postmark, HubSpot, Anthropic, Railway, Postgres. Any of those could have had a real key committed at some point and later replaced with a placeholder; the replacement commit does not remove the original blob.

Remediation is rotation, not removal

Rewriting history does not undo exposure:

  • Forks keep their own copy of the objects; a rewrite on this repo does not touch them.
  • Clones already on disk elsewhere keep the full history.
  • Scrapes and mirrors — public repos are continuously cloned by archival services, security scanners, and model-training crawlers, typically within minutes of going public. Assume anything that was in the tree on 2026-09-14 has already been copied.
  • GitHub keeps unreachable objects accessible by SHA for a period even after a force-push.

So the only remediation that actually closes the exposure for a leaked credential is rotating it. History rewriting is optional hygiene afterward, not the fix, and it should not be treated as one.

What needs doing

  1. Scan the full history, not the working tree — gitleaks detect --log-opts="--all" and trufflehog git file://. --since-commit=<root>, or equivalent. Run both; they have different detector sets and neither is a superset of the other. Include all refs and all branches, not just main.
  2. Triage every hit into: real credential, placeholder/example, or false positive. Record the verdict — an unclassified hit is not a cleared hit.
  3. Rotate every real credential found, in the provider, regardless of whether it looks expired, unused, or already replaced in a later commit. An untested assumption that a key is dead is not a determination that it is dead.
  4. Record the outcome — what was scanned, at what commit, what was found, what was rotated. A future "has this been checked?" should have an answer.
  5. Add a push/PR-time secret scan to CI so the next one is caught before it lands, and enable GitHub secret scanning + push protection on the repo now that it is public.

Done when

Both scanners have run over full history, every hit is triaged, every real credential is rotated, the result is written down, and CI blocks the next one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: infrastructureWorker, queue, CI, deploy, containers, observabilityarea: securitySecurity & tenant/environment isolationroadmap: nowRoadmap horizon: V1 launch critical path / safety

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions