Three CI findings, three different kinds of problem.
gitleaks flagged a Fernet key hardcoded in e2e-server.sh. That one is real: it
encrypts only a throwaway local e2e.db and prod reads TREG_SECRET_KEY from the
environment, so the blast radius is a local database — but a committed key is a
committed key. treg-dev-server hardcodes one because its database persists and a
new key would orphan stored secrets; this harness deletes its database between
runs, so it now generates a fresh key per run and needs no constant at all.
The other two were the same fixture: a Stripe-shaped string in a test whose whole
job is to prove such strings get masked. Now reuses the placeholder .gitleaks.toml
already allowlists for that exact purpose, so a test about masking secrets stops
tripping the secret scanner and the allowlist stops growing a line per test.
CodeQL flagged the JWT alternative as polynomial on uncontrolled data, and it was
right — the alternative was written for argv and round 2 moved it onto PROVIDER
response bodies. Measured on 'eyJ' repeated: 1.1ms at 2KB, 4.2ms at 4KB, 17ms at
8KB — quadratic, attacker-triggerable, on the request path, once per failed call.
Anchoring with \b leaves one start position instead of one every three characters,
and a possessive quantifier removes backtracking within an attempt (it cannot
change what matches: the class excludes '.', so the run always ends at the first
one). Unmeasurable at every size after, and real JWTs still mask. Fixed in the argv
rule too — same shape, same exposure.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The unit tests use a fake relay, so nothing until now had shown that a REAL
provider's error body survives the round trip — decode, redaction, truncation,
column, and back out through /admin/errors. This runs it end to end on the real
platform keys for a few tenths of a cent.
12/12, and two of the checks only mean something because they ran for real:
- tikhub answers this machine with a Cloudflare HTML block page, not JSON. That
is exactly the CDN/WAF case the decode path was written for — the edge
generates it and ignores the identity request. It stored at 2001 chars (the
2000 cap plus the truncation marker) and decoded clean, no replacement
characters. A stub would never have produced it.
- the leak check asserts all twenty real platform keys are absent from every
captured row, and asserts separately that there WAS evidence to search, so it
cannot pass vacuously. Keys are compared, never printed.
Also confirmed against a live upstream: a 200 stores nothing, /calls still does
not carry the columns, and the two spyfu/serpapi attempts were refused by treg
before relay (refused_by=request) — the required-param gate doing its job, and
correctly NOT captured.
The harness runs on its own port and its own database, deliberately not through
treg-dev-server: that script pkills every `python -m treg`, and another session
has one running against the main checkout. Its own stop had the same class of
bug and is fixed here — it matched an env var that never appears in argv, so it
silently killed nothing and left an orphan holding the deleted database open,
which surfaced as "attempt to write a readonly database". It kills by port now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>