fix: remove early length exit from timingSafeEqStr

🟢 open · #81 · willchen96/mike ← bmersereau/mike · opened 14d ago by bmersereau · +1,312-10 across 6 files · ↗ on GitHub

From the PR description

Summary

  • timingSafeEqStr returned false immediately when string lengths differed, before calling crypto.timingSafeEqual - violating the constant-time contract and creating a theoretical timing oracle
  • Fixed by always running the constant-time comparison first (on zero-padded buffers), then checking length equality afterward
  • In practice, all SHA-256 base64url signatures are 43 characters so this gap has no real exploit path for standard tokens; this is a defense-in-depth fix for the pattern

Closes #72

Changes

  • backend/src/lib/downloadTokens.ts - early length check removed; timingSafeEqStr now pads the shorter buffer and runs timingSafeEqual unconditionally before length verification; exported for testability
  • backend/src/lib/__tests__/timingSafeEq.test.ts - 5 unit tests

Test plan

  • Unit tests: equal strings, same-length mismatch, different-length mismatch, empty strings
  • Build and typecheck pass

Our analysis

Make timingSafeEqStr actually constant-time — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-81.md from inside the repo you want the changes in.

⬇ Download capture-pull-81.md