Threat model
Frontmail lets you send email straight from the browser. That’s convenient, but it means part of your integration lives in code that anyone can read and copy. This page lists every attack we know of against this model, how Frontmail defends against it, what you should set up yourself, and – openly – the risk that remains. If you find something that’s missing, write to security@frontmail.dev.
The basic model
Section titled “The basic model”- The public key is public. It’s in your page’s source code. Treat it like a username, not a password. Anyone can copy it and call the API from a script.
- The
Originheader is not authentication. Browsers set it honestly, but a script can send any value. Allowed origins stop other websites from using your key in their visitors’ browsers – they don’t stop a determined attacker. - What really protects you is what the attacker can’t change:
- the template – the attacker can only send your templates and only fill in their params,
- CAPTCHA (Turnstile) – each send costs a human-like solve,
- limits – per IP, per key, per organization, per recipient, and your credits.
- The private key is a secret. It belongs on your server only. It skips the origin allowlist and CAPTCHA and can read your message history.
The rest of this page follows from these four points.
Attacks and defenses
Section titled “Attacks and defenses”1. Phishing from your domain (the most important one)
Section titled “1. Phishing from your domain (the most important one)”Attack. A template takes its recipient from params – a password reset, a notification, a
newsletter confirmation. The attacker copies your public key and sends that template to a victim,
filling reset_url with their own site. The email comes from your domain, passes SPF and DKIM,
looks exactly like yours and links to the attacker.
What Frontmail does. A public-key request to a template with a dynamic recipient gets a locked content:
- CAPTCHA is mandatory (
dynamic_recipient_requires_captcha), - every link must point to your allowed domains – links in attributes, CSS, plain text (also bare
evil.com/login, which mail clients turn into links) and the subject are checked, including tricks likehttps://you.com@evil.com, backslashes, look-alike Unicode domains and encoded characters (link_not_allowed), - From address, From name and Reply-To can’t come from params (
dynamic_field_not_allowed), - no HTML params, text params at most 500 characters,
- each recipient gets at most 5 such emails per day from your organization (configurable).
Everything is checked before a credit is used. Auto-replies are locked the same way.
What you should do. Fill in Security → Allowed link domains if your links go anywhere other than your website’s domain. Set up your own Turnstile keys. Templates that only your server sends (order confirmations, password resets generated on your backend) should be sent with the private key.
Remaining risk. The attacker can still send your legitimate email to a stranger – for example “Confirm your newsletter subscription” with a link to your site. It contains nothing they control, so it can’t phish, but it can annoy. The per-recipient limit and CAPTCHA keep this small. Plain text without links (for example “call this number”) in a text param is still possible within 500 characters – keep dynamic text params to what the email really needs.
2. Spam to your own inbox
Section titled “2. Spam to your own inbox”Attack. A script floods your contact form template with junk.
What Frontmail does. Per-IP limit (default 10 requests / 60 s, IPv6 counted per /64 network), per-key and per-organization limits, anomaly detection, server-side headless-browser and block-list checks, optional CAPTCHA per template.
What you should do. Turn on Require CAPTCHA for public forms. Use the block list for known spam values.
Remaining risk. Without CAPTCHA a patient attacker rotating IP addresses gets through the limits. With CAPTCHA they have to pay a solving service for every email.
3. Calling the API from a script or a fake “app”
Section titled “3. Calling the API from a script or a fake “app””Attack. The attacker sends requests without a browser, with a forged Origin or with none at all.
What Frontmail does. Requests without Origin and Referer (typical for scripts) are refused
unless you turned on Allow mobile apps – also when your allowlist is empty. Only organizations
with that option use Frontmail’s shared mobile CAPTCHA; everyone else must pass your own Turnstile
widget, and its token must have been issued on the requesting domain.
What you should do. Keep Allow mobile apps off unless you have a native app. Server-side code should use the private key.
Remaining risk. A forged Origin still passes the allowlist; CAPTCHA and the limits are what stop
it (see point 2).
4. Draining your credits or your card
Section titled “4. Draining your credits or your card”Attack. With your public key, the attacker sends as many emails as the limits allow to burn your monthly quota – and, if they could, your overdraft and automatic top-ups.
What Frontmail does.
- Public-key traffic does not use the overdraft and does not trigger auto top-up unless you explicitly allow it (Billing → Spending by public-key traffic).
- The hold queue has a cap; beyond it requests are refused instead of queued, so junk can’t eat the credits you buy later.
- Auto top-up has a monthly count and spending cap.
What you should do. Keep the defaults, use CAPTCHA, watch the anomaly e-mails.
Remaining risk. Your regular quota and credit packs can still be spent by junk that gets past CAPTCHA and limits. That costs you credits, not extra money.
5. Blocking your form for real visitors
Section titled “5. Blocking your form for real visitors”Attack. A cheap flood of invalid requests exhausts your organization’s limits so real visitors
get 429.
What Frontmail does. Organization-wide limits and anomaly detection only count requests that passed template and CAPTCHA checks; before that only the per-IP limit and a generous flood guard apply.
Remaining risk. A large distributed flood can still slow things down; the edge firewall (WAF) absorbs most of it.
6. Bypassing the firewall
Section titled “6. Bypassing the firewall”Attack. Calling Frontmail’s servers directly instead of through the CDN to skip the web application firewall and fake the client IP address.
What Frontmail does. The servers only accept requests that came through our CDN and only trust the client IP address the CDN reports. Nothing for you to configure.
7. A leaked private key
Section titled “7. A leaked private key”Attack. The private key ends up in browser code (often after migrating from EmailJS, whose
accessToken is a private key) and someone copies it.
What Frontmail does. The browser SDKs refuse to run with a private key
(private_key_in_browser), and the API refuses private-key requests coming from a web page unless
you turned on Allow private keys in browsers. Private keys are stored only as hashes.
What you should do. Never put sk_… into frontend code or into VITE_ / NEXT_PUBLIC_
variables. If it leaked, rotate it immediately.
Remaining risk. Someone holding your private key can send without CAPTCHA and read your message history (including form submissions). Protect it like a password.
8. Dangerous attachments
Section titled “8. Dangerous attachments”Attack. Sending malware to you or to a dynamic recipient as an attachment.
What Frontmail does. Attachments from the browser are off unless the template allows them.
Executables, scripts, HTML/SVG, disk images, macro-enabled Office files and similar types are
blocked, also when hidden behind tricks like invoice.pdf.exe., right-to-left characters or
invisible characters. Public-key uploads have a daily volume limit.
Remaining risk. Ordinary documents (PDF, DOCX) can still carry malicious content; your mail client’s antivirus is the last line.
9. Injecting HTML or script into the email
Section titled “9. Injecting HTML or script into the email”Attack. Putting <script>, tracking pixels or a fake form into a param.
What Frontmail does. Params are always HTML-escaped (even with {{{ }}}), html params are
sanitized by an allowlist and can’t break out of attributes, dangerous URLs are neutralized, line
breaks are removed from headers (no header injection), prototype-polluting keys are dropped.
10. Harassing one person (mail bombing)
Section titled “10. Harassing one person (mail bombing)”Attack. Using a dynamic-recipient template to send many emails to one address.
What Frontmail does. Per-recipient daily limit (default 5), shared with auto-replies; suppression list for addresses that bounced or complained.
11. Taking over your dashboard account
Section titled “11. Taking over your dashboard account”Attack. Password guessing, stolen session, stolen mailbox.
What Frontmail does. Sign-in rate limits, two-factor authentication that is enforced for every sign-in method, password-reset links that work once and sign out all devices, e-mail changes confirmed from the old address, new-device notifications, roles with least privilege and an audit log.
What you should do. Turn on 2FA, give teammates the smallest role that works.
12. Stealing your form submissions
Section titled “12. Stealing your form submissions”Attack. Reading other people’s message history or files.
What Frontmail does. History is readable only with the private key or by members of your organization; every lookup is scoped to your organization, including files attached to templates.
13. Forged delivery events
Section titled “13. Forged delivery events”Attack. Sending fake “bounced” or “complained” events to put your customers on the suppression list.
What Frontmail does. Provider webhooks are verified by signature where the provider supports it and always by a secret URL token; an event only affects a message’s actual recipient.
What you should do. Configure the signing key for your provider where offered.
14. A compromised SDK
Section titled “14. A compromised SDK”Attack. Malicious code in the script your website loads.
What Frontmail does. Releases are built without secrets, published with provenance, and CI actions are pinned to exact versions.
What you should do. Load the SDK from a versioned URL with an integrity attribute (see
Browser SDK), or bundle the npm package.
15. Frontmail used by criminals
Section titled “15. Frontmail used by criminals”Attack. A phishing site uses its own Frontmail account to send stolen passwords to itself – this happens to every service of this kind.
What Frontmail does. Verified owner e-mail, monitoring of unusual traffic, fast suspension of reported accounts. Report abuse to abuse@frontmail.dev.
What stays in your hands – checklist
Section titled “What stays in your hands – checklist”- Fill in Allowed origins with your domains.
- Add your own Turnstile keys and require CAPTCHA on public forms.
- Use a dynamic recipient only where you need it; fill in Allowed link domains.
- Keep Allow mobile apps and Allow private keys in browsers off unless you need them.
- Private key only on the server; rotate it if in doubt.
- Keep public-key overdraft and auto top-up off (the default).
- Turn on 2FA for everyone on your team.
- Load the SDK from a pinned version with
integrity.