Skip to content

Harden MIME boundaries, topup atomicity, and nonce cleanup#8

Merged
sragss merged 5 commits intomainfrom
fix/security-hardening
Feb 12, 2026
Merged

Harden MIME boundaries, topup atomicity, and nonce cleanup#8
sragss merged 5 commits intomainfrom
fix/security-hardening

Conversation

@sragss
Copy link
Copy Markdown
Contributor

@sragss sragss commented Feb 12, 2026

Summary

  • MIME boundary injection: Replace predictable Date.now() with crypto.randomUUID() for MIME boundary generation in ses.ts
  • Topup race condition: Replace read-compute-write with atomic UPDATE ... SET "expiresAt" = GREATEST("expiresAt", NOW()) + interval so concurrent topups both correctly extend
  • SiwxNonce unbounded growth: Add probabilistic cleanup (~1% of writes) that deletes nonces older than 24h

Test plan

  • pnpm build passes
  • Send email with attachments — verify MIME boundaries use UUIDs
  • Topup an inbox — verify expiry extends correctly
  • SIWX auth still works (nonce recording + cleanup don't break flow)

🤖 Generated with Claude Code

- Use crypto.randomUUID() for MIME boundaries instead of predictable
  Date.now() to prevent boundary injection attacks
- Fix topup race condition: use atomic SQL UPDATE with GREATEST() so
  concurrent topups both correctly extend from the latest expiresAt
- Add probabilistic SiwxNonce cleanup (~1% of writes) to prevent
  unbounded table growth — deletes entries older than 24h

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
x402email Ready Ready Preview, Comment Feb 12, 2026 4:32am

Subdomain owners can buy the matching inbox name with the same wallet.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Log nonce cleanup errors instead of silently swallowing them
- Guard against empty UPDATE result if inbox is deleted between
  findUnique and atomic update

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Agents probing the endpoint now learn that subdomain owners can buy
the matching inbox name with the same wallet.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
- forwardTo is now optional on buy and nullable on update
- When forwardTo is omitted, retainMessages is enabled automatically
  so the inbox works as a programmatic mailbox via the messages API
- Forward handler skips forwarding for inboxes without forwardTo
- Cron reminder skips inboxes without a forwarding address
- S3 cleanup no longer requires forwarding to have happened
- Updated discovery description, llms.txt, and CLAUDE.md

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@sragss sragss merged commit e2f5136 into main Feb 12, 2026
4 checks passed
@sragss sragss deleted the fix/security-hardening branch February 12, 2026 04:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant