A Stranger Tried The Door — So We Built A New One
🔍 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.
^/downloads/s/(\d+)/([A-Za-z0-9_-]+)/([A-Za-z0-9._-]+)$→ 403
exp to Date.now(). Expired? Reject.→ LINK_EXPIRED
→ BAD_SIGNATURE
application/zip with cache-control: private, no-store.→ 200 OK
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.)
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.
| Probe | Verdict |
|---|---|
| Old leak paths (×6) on origin and apex | 404 |
Bare /downloads/<paid> at the gate | 403 SIGNED_URL_REQUIRED |
| Tampered signature (1 byte flipped) | 403 BAD_SIGNATURE |
Expired exp | 403 LINK_EXPIRED |
| Unknown filename in valid path | 403 UNKNOWN_FILE |
| Path traversal / encoded NULs / case games | 403 / 404 |
| Constant-time compare timing analysis | variance is network jitter, no leak |
| Mint-endpoint guards (Bearer + slug allow-list + Origin block) | all firing in correct order |
| Secret in git history | only 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.
| Severity | Count |
|---|---|
| Critical | 0 |
| High | 0 |
| Medium | 2 hardening items logged for the next sprint |
| Low | 4 minor cleanup items (consistency, error handling) |
| Info | 3 (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