Please report suspected vulnerabilities privately:
- Email: security@formbit.dev
- Or use GitHub's private vulnerability reporting on this repository.
Include what you can: affected version, reproduction steps, impact assessment. You will receive an acknowledgment within 72 hours.
Please do not open public issues for security reports, and do not test against instances you do not own or have permission to test.
- We follow coordinated disclosure with a 90-day window: we aim to ship a fix and publish an advisory well within 90 days of a report; reporters are free to publish after 90 days regardless.
- Fixes are released as patch versions for the current minor line, with a
GitHub Security Advisory and a
[SECURITY]tag in release notes. - Credit is given to reporters in the advisory unless anonymity is requested.
- There is no bug bounty program - this is a community-funded open-source project. We still deeply appreciate reports.
| Version | Supported |
|---|---|
| Latest minor (1.x) | ✓ security fixes |
| Older lines | ✗ upgrade - patch/minor upgrades are pull-and-up (see docs/upgrading.md) |
The full threat model and control inventory live in
docs/spec/SECURITY-SOC2.md; operator-facing
compliance docs in docs/compliance/. Highlights:
- Passwords: scrypt (N=2^17, r=8, p=1), length-only policy (NIST 800-63B), bundled offline breached-password list; optional HIBP check.
- Sessions: 32-byte random tokens, stored only as SHA-256 hashes;
__Host-prefixed,HttpOnly,Secure,SameSite=Laxcookies; 30-day absolute / 7-day idle lifetime; token rotation on every privilege change; revoke-all on password change. - 2FA: TOTP with AES-256-GCM-encrypted seeds, replay protection, and single-use hashed recovery codes.
- Secrets: one
APP_SECRET, HKDF-SHA256 subkeys per purpose (TOTP encryption, webhook secrets, IP hashing, token pepper); fail-closed boot when missing or weak. - Respondent privacy: raw IPs are never stored on responses - only an HMAC pseudonym; analytics are cookieless and never joined to responses.
- Tenant isolation: every query resolves through the caller's
workspace_id; cross-tenant IDs return 404, never 403. - Uploads: extension + MIME + magic-byte agreement required; scripts and
SVG/HTML are denied outright; served
attachment+nosniff+ CSPsandbox; storage paths are never user-derived. - Webhooks: HTTPS-only, private/reserved IP ranges blocked with DNS pinning, no redirects, HMAC-SHA256 signed payloads with a 5-minute replay window.
- Headers: strict CSP with per-request nonces,
frame-ancestors 'none'on the app (public forms are intentionally embeddable), HSTS via Caddy. - Accountability: append-only audit log covering every privileged action.
- Supply chain: committed lockfile,
npm ci --ignore-scriptsin the image build, no postinstall scripts, no native modules, no runtime CDNs or telemetry.
Operators: complete the hardening checklist before going to production.