Simple Inbox

Security

Single-Worker boundaries, setup authorization, mailbox privacy, secrets, and recovery.

Simple Inbox treats email content as hostile input and every mailbox lookup as an authorization boundary. Public docs and health metadata are anonymous; mailbox data is not.

Secrets

Create two independent secret values of at least 32 random bytes:

  • AUTH_TOKEN_PEPPER keys magic-link, session, and API-token digests. Rotation invalidates values protected by the old pepper.
  • SETUP_TOKEN authorizes first-run setup. It is compared by digest and is never stored in D1, returned, or logged.

Never commit either value, reuse one as the other, expose it in shell arguments, or copy it into logs, tickets, screenshots, or smoke evidence.

Single-Worker boundaries

The public fetch, Email Routing email, and retention scheduled handlers share one Worker and its D1/R2/Email bindings. The application retains explicit logical boundaries:

  • the root router exposes pages and /api/v1/*, never mail /internal/* routes;
  • the API owns authentication, CSRF, scopes, contracts, and mailbox authorization;
  • an in-process adapter accepts only the fixed private mail origin/path;
  • repositories own D1 invariants and authorize raw/attachment reads before R2 access;
  • static boundary checks and integration tests prove public internal-mail probes return 404.

An in-process call is not an authorization substitute. Browser routes must never call privileged mail services with unvalidated actor, mailbox, scope, request-ID, or idempotency context.

Setup security

Before installation completes, protected APIs fail unavailable, inbound email is rejected, retention is idle, and UI routes redirect to /setup.

Setup mutation requires HTTPS (except local loopback), exact same-origin headers, source rate limiting, and the setup token. One D1 transaction creates the owner, mailbox, sole owner membership, canonical origin, domain, and retention settings. Exact replay is idempotent; conflicting or partial state fails closed.

Setup records the request origin. Attach an intended custom domain before setup or keep using the workers.dev origin; changing origins later without an explicit migration can break magic links, Secure cookies, and CSRF checks.

Magic-link requests intentionally return the same accepted representation for known, unknown, throttled, and temporarily unavailable addresses to resist account enumeration.

  • Links are one-time tokens that expire after 15 minutes.
  • Requests have a per-address cooldown plus a Cloudflare rate limit.
  • D1 stores only keyed digests, never plaintext tokens.
  • Sessions expire after 30 days and use Secure, HttpOnly, SameSite=Lax __Host- cookies when deployed.
  • Cookie mutations require trusted same-origin metadata; bearer-token requests are scope checked.

Mailbox and content isolation

Every mailbox, thread, message, raw object, and attachment lookup is scoped to the authenticated owner. Missing and unauthorized objects share not-found responses where appropriate.

  • Keep R2 private with no r2.dev URL or custom domain.
  • Store raw RFC 822 data under opaque keys and never include it in D1 DTOs or structured logs.
  • Sanitize filenames/media types and serve downloads with nosniff and private no-store caching.
  • Treat HTML as hostile; use safe projections and do not load remote content in the app origin.
  • Keep provider invocation logs and automatic traces disabled because their metadata can contain token-bearing URLs, searches, and Email recipients.
  • Keep message bodies, raw addresses, tokens, attachments, and storage keys out of application logs.

The application performs no AI inference and sends no mailbox content or metadata to an AI service.

Retention and recovery

Raw retention must not exceed application-record retention. The scheduled handler deletes private R2 bytes first, then transactionally removes expired D1 projections and repairs threads. A durable content-free tombstone holds retry state and safe failure codes.

Deletion is irreversible at the application layer. Before shortening a policy or applying a destructive migration, export required owner-authorized raw/attachment data to encrypted storage and test D1 restoration. Worker rollback cannot undo migrations or restore deleted D1/R2 data.

Operational safeguards

  • Treat vp run deploy as a remote build + migration + deployment after verifying the account.
  • Email Sending, R2 lifecycle, custom domains, and Email Routing are explicit Dashboard actions.
  • Use only synthetic example.test content and owner-controlled destinations for live testing.
  • Never discover, import, mutate, cut over, or delete a legacy Inbox resource through repository automation.
  • On incident, preserve request IDs, Worker versions, and timestamps without copying sensitive payloads; rotate exposed secrets and manually restore any changed routing target.

On this page