Data Protection
Data Protection
Data Protection
Formic applies multiple layers of protection to ensure submitted data is stored and transmitted safely.
XSS Sanitization
All submitted data is sanitized before storage to prevent cross-site scripting (XSS) attacks. This is critical because form data may be rendered in HTML emails, admin dashboards, or other contexts.
HTML Entity Escaping
The following characters are escaped in all string values:
| Character | Escaped Form |
|---|---|
& | & |
< | < |
> | > |
" | " |
' | ' |
Example: The input <script>alert('xss')</script> becomes <script>alert('xss')</script>.
Non-string values (numbers, booleans, objects, arrays, null) are preserved as-is.
Unicode Normalization
String values are normalized to Unicode NFKC form to prevent homoglyph attacks where visually similar characters are used to bypass filters.
String Truncation
String values are truncated to prevent abuse via excessively long fields:
| Condition | Maximum Length |
|---|---|
Schema defines maxLength | Value from schema |
No schema or no maxLength | 10,000 characters |
Truncation is character-boundary safe to prevent corrupting multi-byte Unicode characters.
Sanitization Depth
The sanitizer limits recursion to 10 levels to prevent stack overflow attacks via deeply nested JSON objects.
Processing Order
Sanitization runs after JSON Schema validation. If validation fails, the submission is rejected with 400 Bad Request and sanitization is skipped entirely.
Submission Metadata
When a submission is accepted, Formic stores metadata alongside the submitted data in the submissions.meta JSONB column:
| Field | Source | Purpose |
|---|---|---|
ip | CF-Connecting-IP → X-Real-IP → X-Forwarded-For → "unknown" | Client IP for audit and abuse analysis |
user_agent | User-Agent header | Browser/client identification |
referer | Referer header | Submission origin page |
IP extraction follows a priority chain that respects Cloudflare and other proxy headers.
Transport Security
API Transport (HTTPS)
All API traffic is encrypted with TLS, terminated at the Caddy reverse proxy layer. The Caddyfile configures security headers including:
Strict-Transport-Security(HSTS)X-Content-Type-Options(nosniff)X-Frame-Options(deny)X-XSS-ProtectionReferrer-Policy
Database Transport (TLS)
PostgreSQL connections use TLS via SQLx tls-rustls feature.
Email Transport (TLS)
SMTP connections use TLS via Lettre with tokio1-rustls-tls.
Secret Masking
Formic never logs secrets. The mask_secret() function ensures that:
- Connection strings: Only scheme + host are logged; credentials are masked
- API keys: Only the first 4 and last 4 characters are logged
- Tokens and passwords: Fully masked in log output
This prevents accidental credential exposure through log aggregation systems, error reports, or monitoring dashboards.
Related
- Security Overview — Full security architecture
- Authentication — API key management
- Anti-Abuse Protections — Rate limiting and validation