Security
Security best practices for running MXHook in production.
Authentication
API Key
Protect the REST API with an API key:
bash
MXHOOK_API_KEY=your-secret-key ./mxhook startAll API endpoints (except /health and /openapi.yaml) require the X-API-Key header when a key is configured. Always set an API key in production.
Webhook Signing
Configure a webhook_secret on each route to enable HMAC-SHA256 payload signing. Your application should verify the signature on every request and reject unsigned or incorrectly signed payloads.
Network Security
TLS
- API: Place the REST API behind a reverse proxy (nginx, Caddy, Traefik) with TLS termination. Do not expose the API over plain HTTP in production.
- SMTP: MXHook supports STARTTLS for encrypted SMTP connections. TLS 1.2+ is enforced.
Firewall
| Port | Protocol | Source | Purpose |
|---|---|---|---|
| 25 | TCP | Internet | Inbound SMTP |
| 8080 | TCP | Internal | REST API (behind reverse proxy) |
| 5432 | TCP | Internal | PostgreSQL (MXHook only) |
- Expose port 25 to the internet for receiving email.
- Restrict API access to internal networks or authenticated clients.
- Never expose PostgreSQL to the public internet.
Rate Limiting
MXHook enforces inbound SMTP rate limiting at 100 messages per hour per source IP. This protects against abuse and spam floods.
Input Validation
- Email parsing is handled by the battle-tested
enmimelibrary with hardened defaults - Webhook URLs are validated before route creation
- SQL injection is prevented through parameterized queries (pgx)
- Maximum message size is enforced at the SMTP level (default: 10 MB)
Data Isolation
In multi-tenant deployments, data is isolated per domain. Messages, routes, and DLQ entries are scoped to the domains registered in MXHook.