How Formwire is built
Formwire holds other people's form submissions, which are frequently the most sensitive thing on a small site: names, emails, and whatever someone typed into a message box. These are the controls that protect them.
Tenant isolation
Every table carrying customer data has an account id and a row-level security policy. The dashboard connects to the database as the signed-in user, never with a privileged key, so a missing filter in application code cannot leak another account's rows — the database refuses. Privileged operations live in a handful of named server functions that check authorisation first.
Policies alone are not enough, so we also revoke the privileges that bypass them — TRUNCATE in particular ignores row-level security entirely. Our tests assert that access is denied, which is a different claim from “a policy exists”.
Credentials
The webhook URLs and bot tokens you connect are encrypted before they touch the database, with a key held outside it, and bound to the integration they belong to so an envelope cannot be replayed into another. They are redacted in logs and never returned by an API response — including your own data export.
The submission endpoint
- Body size, field count, and field size are capped and checked before the body is read.
- JSON keys named
__proto__,constructororprototypeare rejected outright rather than stripped. - Redirect targets are validated as absolute URLs on allowed origins — an unchecked redirect on our domain would be a phishing tool aimed at your visitors.
- Outbound webhook targets are checked against private address ranges and cloud metadata endpoints, including DNS-rebinding hostnames.
- Rate limits and quotas are enforced at the edge, per form and per IP.
The dashboard
Submission content is always rendered as text, never as HTML. A strict Content-Security-Policy with a per-request nonce and no unsafe-inline or unsafe-eval means an injected script has nothing to execute with. Exports escape spreadsheet formula characters, so a submission cannot become a formula in your CSV. Sign-in is passwordless; deleting an account requires a recent sign-in.
Reporting a vulnerability
Please write to security@formwire.dev, or read security.txt. If you have found a way to read, change, or delete data belonging to an account that is not yours, that is the report we most want. We confirm receipt within three working days and ask for 90 days before disclosure.