Security ⏱️ 6 min read

A Stranger Tried The Door — So We Built A New One

TL;DR

🔍 The find: A researcher, David, disclosed that four paid product downloads were sitting unauthenticated under getgodmode.dev/downloads/* — anyone with the filenames could grab them.
🔧 The fix: Pulled the files out of the static folder, dropped them into a Cloudflare KV bucket, and put a 60-line Worker in front that only serves them via short-lived HMAC path-signed URLs.
🔍 The follow-through: Audited the rest of the site for similar patterns. 0 critical, 0 high. Two medium-priority hardenings logged.
🎁 The thanks: David got a packaged copy of /one-shot-scripts and a written thank-you.

🔍 What David Found

The disclosure was simple and embarrassing: four paid downloads were public.

If you knew (or guessed) the filenames — godmode.zip, godmode-plus.zip, godmode-evolution-QUICKSTART.md, one-shot-scripts.zip — you could just curl them off the static site. No auth, no signing, no purchase check. The folder was a corkboard.

Two extra paths were also leaking under obfuscated names: /dl-a8f3c9e2b714.skill and /dl-e7d4b1f06a39.md. Obfuscation was never the security model — it just slowed things down for anyone who didn't read the page source carefully.

Think of it like a key under the doormat: the lock works fine, but anyone who looks under enough doormats eventually finds one. Obscurity isn't a control — it's a delay.

🚪 The Old Door

The original setup was the cheapest possible: paid product files lived in the same /downloads/ folder as the free files. The website's checkout page sent the link to your inbox, and that was the whole gate.

The problem with sending a permanent link to a permanent file is that the file doesn't know who has the link. Once a single URL leaks — pasted in a Slack, screenshotted in a tweet, indexed by a crawler — the file is everyone's.

🔐 The New Gate

The fix was to build a gate that asks two questions on every request: did the right person ask for this? and did they ask for it recently?

The shape of the answer is a path-style HMAC signed URL. Each part of the path is a piece of evidence the gate checks before opening:

When the Worker sees a request, it runs four checks in order. The request fails on the first one that doesn't pass.

That's the entire gate. Sixty lines of JavaScript and a single shared secret on three places: the Worker, plus the two server-side endpoints that mint URLs (one for the npm MCP client, one for the browser dashboard).

🎮 Try The Gate

The interactive panel below is wired to the same logic the live Worker runs. Flip the switches to feed the gate different inputs — the URL on the right changes to match, and the verdict box shows what the Worker would return. (No real requests; this runs in your browser.)

🧪 Live decision — try the gate
flip switches · watch the verdict update
Path
Filename
Expires
Signature
✅ 200 OK KV bytes streamed · cache-control: private, no-store

What the demo shows that the static gate couldn't: every check is independent, and a leaked URL stops working five minutes after it was minted — even if every other field is perfect.

🔎 Verifying The Fix

Before declaring this done we ran a full pen test against the new gate. Sixteen probes covering replay, path traversal, method tampering, timing analysis, and signature forgery. Every adversarial input got a 403; every valid input got a 200.

ProbeVerdict
Old leak paths (×6) on origin and apex404
Bare /downloads/<paid> at the gate403 SIGNED_URL_REQUIRED
Tampered signature (1 byte flipped)403 BAD_SIGNATURE
Expired exp403 LINK_EXPIRED
Unknown filename in valid path403 UNKNOWN_FILE
Path traversal / encoded NULs / case games403 / 404
Constant-time compare timing analysisvariance is network jitter, no leak
Mint-endpoint guards (Bearer + slug allow-list + Origin block)all firing in correct order
Secret in git historyonly env-var name, no value

🛡️ While We Were Here

You can't audit one corner of a site without looking at the rest. The same shape of bug — trusting the URL alone — might be hiding somewhere else. So we did a sweep across the supabase edge functions, Cloudflare workers, client JS, and the auth flows.

Result: the rest of the codebase is in better shape than the leaky folder was.

SeverityCount
Critical0
High0
Medium2 hardening items logged for the next sprint
Low4 minor cleanup items (consistency, error handling)
Info3 (anon keys public-by-design, etc.)

Stripe webhook signature is properly verified. Every privileged edge function checks a JWT before doing anything. The image-upload function verifies magic bytes server-side, not just MIME claims. Idempotency keys are baked into the purchase recording. None of these were rushed in after the disclosure — they were already there.

The two medium-priority items are both infrastructure-level hardenings rather than code defects, and they're already on the next sprint.

🎁 Thank You, David

Responsible disclosure costs the researcher time and asks them to trust us not to react badly. David spent both, and got nothing for it except the satisfaction of doing it right.

So we packaged up the /one-shot-scripts skill — the same protocol that ran most of the testing in this post — with a thank-you note, and sent it across. Small thing, but it's the kind of trade we want more of: a researcher tells us something, we fix it fast and quietly, and they get something useful back.

If you're a researcher reading this: we will always thank you for a real disclosure. The address is support@getgodmode.dev.

📝 Lessons Worth Repeating

Do

Put a server in front of paid bytes. Make every download URL a contract: this file, this person, this five-minute window.

Don't

Rely on filename obscurity. The filename leaks the moment one customer screenshots a receipt or shares an inbox.

Do

Bake the filename into the signature. Then a stolen sig can't be replayed against a different file in the catalogue.

Don't

Let the client pick the expiry. Server clock decides when the URL dies — otherwise expiry is just a suggestion.

Want the protocol that did the audit?

One-Shot Scripts is the universal-execution skill that ran the pen test, the broader audit, and most of the post-mortem. Same skill we sent David.

See One-Shot Pricing