amal66 hardens how Mike guards stored keys and download links

A trio of security fixes pulled from upstream that make secret handling sturdier without breaking anything already in place.

securityinfrastructure

amal66 reworked the way the fork protects sensitive credentials. Stored user API keys now get individually scrambled per record, so a single leaked row can't be used to unlock everyone else's - a meaningful upgrade over the old shared-recipe approach. Older records still open cleanly, so nothing existing breaks.

The same pass tightens download links: they now expire after 30 days, and the check that validates them was rebuilt to close a subtle timing weakness that a patient attacker could otherwise exploit to guess valid tokens. The fork also now refuses to start if a required setting is missing - a deliberate fail-loud choice that surfaces misconfiguration immediately rather than letting a half-configured deployment limp along.

So what Anyone running this fork in production and holding client credentials should care - this is textbook hygiene that lowers the blast radius of a breach.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

3 commits from amal66/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
9f15ed1c fix(chapter-04): fail fast on config and compare secrets safely Amal 2026-05-24 ↗ GitHub
commit body
Chapter: 04 - Runtime safety basics.

Plain-English map:
Validate required environment variables at startup, reuse Supabase and storage
clients instead of recreating them per request, and remove a timing leak from
download-token comparison.

Why it matters:
Bad configuration should be caught before users hit the app. Shared clients
avoid needless connection churn. Secret checks should not reveal clues through
response timing.

Principle:
Fail fast, reuse expensive resources, and compare secrets in constant time.

Precedent borrowed:
Upstream PRs #81, #106, and #109, which independently targeted timing-safe
comparison, env validation, and singleton client reuse.

Upstream base: willchen96/mike@d39f580.
Original local commit: c2d2a9a.
112a9a53 fix(chapter-14): give download tokens an expiration time Amal 2026-05-24 ↗ GitHub
commit body
Chapter: 14 - Secret lifetime.

Plain-English map:
Add a 30-day expiration to signed download tokens while keeping old tokens
backward compatible.

Why it matters:
A signed link should not be useful forever. Shorter lifetimes reduce the
damage if a link is copied, leaked, or found later.

Principle:
Secrets and bearer tokens should expire.

Precedent borrowed:
Upstream PR #77.

Upstream base: willchen96/mike@d39f580.
Original local commit: e6bfeb1.
5762ee71 fix(chapter-22): derive API-key encryption keys with HKDF salts Amal 2026-05-24 ↗ GitHub
commit body
Chapter: 22 - User API key protection.

Plain-English map:
Replace static SHA-256 key derivation with HKDF and a unique salt per stored
user API key row.

Why it matters:
Users may store real provider keys in Mike. Those keys deserve standard,
reviewable cryptography instead of one shared derived key for every row.

Principle:
Use established key-derivation functions and per-record salts for encrypted
secrets.

Precedent borrowed:
Upstream PR #76.

Upstream base: willchen96/mike@d39f580.
Original local commit: e0a64bd.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-584.md from inside the repo you want the changes in.

⬇ Download capture-thread-584.md