6.5 KiB
Secrets scan over the whole git history
Run 2026-09-17 against the local checkout at main = c9858cc, before any public push.
Scope: every commit on every ref, not just the working tree.
No secret value appears anywhere in this document. Findings are described by shape and location only.
What was run
| tool | version | command | coverage |
|---|---|---|---|
| gitleaks | 8.30.0 | gitleaks git . --log-opts="--all" --redact |
460 non-merge commits, ~8.27 MB of diffs |
| gitleaks | 8.30.0 | gitleaks dir . |
the checked-out tree, 2.02 GB incl. target/ and node_modules/ |
| trufflehog | 3.90.10 | trufflehog git file:///<checkout> |
322,604 chunks, 4.23 GB, all branches |
| grep (own pattern set) | — | every blob in the object DB, see below | 5,791 objects incl. dangling blobs |
Both binaries were installed as prebuilt releases under ~/.local/bin (no root, no package
manager). Repository size for reference: 563 commits, 87 refs, one author.
The grep pass exists because gitleaks and trufflehog know generic provider shapes but not this
project's own ones. It enumerates git rev-list --objects --all plus the dangling blobs from
git fsck --lost-found, pipes each blob through git cat-file blob, and matches:
-----BEGIN [A-Z ]*PRIVATE KEY------ Twitch IRC tokens:
oauth:[A-Za-z0-9]{20,} - Twitch/RTMP stream keys:
live_[0-9]{6,}_[A-Za-z0-9]{20,} Authorization: (Bearer|Basic|OAuth) <12+ chars>client_secret/clientSecret/CLIENT_SECRETassigned a 20+ char valuestream_key/STREAM_KEY/streamKeyassigned a 12+ char valueaccess_token/refresh_token/accessToken/refreshTokenassigned a 16+ char valueapi_key/API_KEY/apiKeyassigned a 16+ char valuepassword/passwd/PASSWORDassigned an 8+ char literalpass show/pass ls(this repo's credential store ispass, so captured output would look like a shell pipeline in a script or a log)- AWS
AKIA…, GitHubghp_/gho_/ghu_/ghs_/ghr_, Slackxox[baprs]-, OpenAIsk- - a separate broad sweep for any 32+ char high-entropy token not already explained by a
checksum,
integrityfield or base64 blob
Findings
gitleaks: no leaks found, on history and on the tree.
trufflehog: 0 verified, 0 unverified secrets (one non-critical decode error on
data/fafb-v783/weights.binz, which is a gzip stream trufflehog tried to read as brotli — not a
finding).
The grep pass matched 14 blobs across 5 paths. Every one is a reference to a credential, never a credential. Full list:
| # | shape matched | path | commits (first → last touching) | verdict |
|---|---|---|---|---|
| 1 | pass show "$PASS_KEY" shell pipelines, 4 blobs |
infra/06-secrets.sh |
0d1a762 → 69816e6 |
False positive. The script's whole job is to pipe pass show into systemd-creds on the container; the value never lands in a file and never in git. PASS_KEY holds a pass entry name (twitch/fly-pokemon-key), not a secret. |
| 2 | pass show … | head -c8 in a verify helper, 6 blobs |
infra/verify.sh |
0d1a762 → 57276d4 |
False positive. Reads the first 8 bytes of the stored key to compare a prefix against what the container holds. The prefix is computed at run time and printed nowhere that is committed. |
| 3 | accessToken: / refreshToken: struct fields, 3 blobs |
services/bridge/src/auth.ts |
d9f00b6 → 48cd40a |
False positive. Twurple AccessToken field names in code (accessToken: token.accessToken). No literal values. |
| 4 | accessToken: / refreshToken: struct fields, 1 blob |
services/bridge/tools/authorize.mts |
77f5892 |
False positive. Same: the interactive authorize tool writes the token it just fetched to a path outside the repo. |
| 5 | the words pass show | systemd-creds in prose |
infra/docs/release-ct-provision.md |
6598ad0 |
False positive. A provisioning log describing the mechanism. |
Broad high-entropy sweep: 1,101 blobs carried a 32+ char token line, all accounted for by
package-lock.json integrity hashes, the FlyWire meta.json / tools/artifact-checksums.txt
sha256 digests, and vendored binjgb tables. Nothing credential-shaped.
Negative results worth recording
- No
.envwas ever committed. The only*.envpaths in history areinfra/env/fly-pokemon.env,infra/env/fly-platformer.envandinfra/env/spike.env, which are deployment profiles, not credential files. Dumping everyKEY=valueline those three files have ever carried, across every commit, yields only CT sizing (CORES,CPUSET,MEMORY_MB), network (IP,HOSTNAME), stream geometry (STREAM_WIDTH,STREAM_KBPS), feature flags,PASS_KEY(an entry name),TWITCH_CHANNEL/TWITCH_BOT_USER(public handles) andPUSH_TARGET..gitignorecovers.envand.env.*with a!.env.exampleexception. - No key material of any kind. Zero matches for
BEGIN … PRIVATE KEY,id_rsa,id_ed25519,*.pem,*.key,*.p12,*.pfxas paths or as content. - No stream key, ever. Zero matches for the
live_…RTMP shape or for aSTREAM_KEY=assignment. Stream keys reach the containers only throughpass→systemd-creds. - The remote carries no credential. the operator's git remote — SSH, no token in the URL.
- One advisory, not a secret:
ROM_SHA256=0e85…219fis committed ininfra/env/spike.envandinfra/env/fly-pokemon.env. It is a cartridge fingerprint, so it is not a credential and needs no rotation, but it does identify a specific commercial ROM dump. Flagging it for whoever is handling the licence/redaction pass, not for this scan.
Verdict
Clean. Nothing to rotate, nothing to rewrite history for. Three independent engines
(gitleaks, trufflehog, a project-specific grep set over every blob including dangling objects)
found zero real credentials across all 563 commits. All 14 grep hits are code and prose that
name credentials handled by pass at run time. The hard rule in CLAUDE.md — "Stream keys and
tokens live in pass, never in git" — holds in the history as well as in the tree.
Re-running this
gitleaks git . --log-opts="--all" --redact --no-banner
trufflehog git "file://$PWD" --no-update
Neither is wired into .forgejo/workflows/ci.yml or .github/workflows/ci.yml: CI runs no
secret-bearing step, and a full-history scan is a pre-publish gate rather than a per-push one.
Run it again before any new public push, and after any commit that touches
infra/06-secrets.sh, infra/env/*.env or services/bridge/src/auth.ts.