Formwork
Menu
Get started free Log in

Security

Security

This page describes what the application actually does today. It is not a certification claim. Where something depends on how your copy is hosted, it says so.

Accounts and sessions

  • Passwords are hashed with PHP's password_hash, never stored or logged in plain text.
  • Sessions use HttpOnly, SameSite=Lax cookies, and are marked Secure when served over HTTPS. The session id is regenerated at sign-in.
  • A session is tied to the current password. Changing or resetting it signs out every other device.
  • Two-factor authentication uses time-based one-time codes with recovery codes.
  • Sign-in, registration, password reset and magic-link requests are rate limited.

Requests and pages

  • Every state-changing request from a signed-in browser needs a CSRF token.
  • The Content Security Policy allows scripts only from the site itself and from inline blocks that carry a per-request nonce. There are no inline event handlers.
  • Responses send X-Content-Type-Options: nosniff, a strict referrer policy and a restrictive permissions policy. Over HTTPS they add HTTP Strict Transport Security.
  • Only public form pages can be framed by other sites, so they can be embedded. Everything else refuses to be framed.
  • Database access uses prepared statements. Output is escaped in templates.

Access control

  • Every read and write of a form checks the person's role in the workspace and on the form. Someone with no access gets a 404, so a form's existence is not revealed.
  • Workspace roles and per-form roles decide who can view, edit and manage.
  • Settings, access and key changes are written to an audit log, kept for a year. Viewing the log is part of the team plan.

Respondents and abuse

  • Public form endpoints are rate limited and protected by a signed page token. A hidden honeypot field silently discards bot submissions.
  • Cloudflare Turnstile can be switched on by the operator.
  • Uploads are checked against an allow-list of file types, given random names and stored outside the public web root. They are only served through the application, after a permission check.
  • Respondents' resume tokens are stored as SHA-256 hashes.
  • IP addresses are never stored as they are. A salted hash that changes daily is used for abuse control.

API keys and webhooks

  • API keys start with fwk_, are shown once and are stored only as a SHA-256 hash. Read keys cannot write, and a key never exceeds its owner's permissions.
  • Webhook deliveries are signed with HMAC-SHA256 over a timestamp and the body. Signing secrets are encrypted at rest with AES-256-GCM.
  • Webhook targets are resolved and checked before a request is made. Private, loopback and link-local addresses are refused, and the resolved address is pinned so a second DNS answer cannot redirect the request.

Your data

  • You can export everything tied to your account and delete the account.
  • A form in the trash is deleted after 30 days. Unresumed partial responses are deleted after 30 days.
  • Data is stored in the database and file storage of the server your copy of Formwork runs on. This site adds no third-party analytics scripts.

Reporting a problem

If you think you found a vulnerability, please use the contact page and describe what you saw. Do not include other people's data. We read every report.