This document describes the security features, threat model, and best practices for deploying and operating Empath MTA.
- Vulnerability Reporting
- Threat Model
- Security Features
- Configuration Best Practices
- Automated Security Scanning
- Security Update Process
- Known Limitations
- Security Roadmap
We take security vulnerabilities seriously. If you discover a security issue in Empath MTA, please report it responsibly.
- DO NOT open a public issue for security vulnerabilities
- Email security reports to: security@pyxxilated.studio (or create a private security advisory on your forge)
- Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if available)
- Allow up to 48 hours for initial response
- We will coordinate disclosure timeline with you
| Version | Supported |
|---|---|
| 0.0.x | ✅ |
Note: Empath is currently in early development (version 0.0.x). Security patches will be released as point releases.
Empath MTA exposes the following attack surfaces:
-
SMTP Server (Port 25/587/465)
- Threat: Malicious clients sending crafted SMTP commands
- Mitigation: Input validation, state machine enforcement, timeouts
- Risk Level: HIGH (exposed to internet)
-
Control Socket (Unix Domain Socket)
- Threat: Unauthorized administrative access
- Mitigation: Filesystem permissions (mode 0600) + optional token-based authentication
- Risk Level: LOW (with authentication enabled) / MEDIUM (filesystem permissions only)
-
SMTP Client (Outbound Delivery)
- Threat: Man-in-the-Middle attacks, certificate spoofing
- Mitigation: TLS certificate validation (enabled by default)
- Risk Level: MEDIUM (network-dependent)
-
Dynamic Module Loading
- Threat: Malicious shared libraries loaded at runtime
- Mitigation: File permissions, run as non-root user, code review
- Risk Level: HIGH (if enabled)
-
Spool Directory (Filesystem)
- Threat: Unauthorized access to message content
- Mitigation: Filesystem permissions, encryption at rest (external)
- Risk Level: HIGH (contains sensitive email data)
Scenario: Attacker floods SMTP server with connections or sends malformed commands to exhaust resources.
Mitigations:
- Connection timeouts: Maximum 30-minute session lifetime (configurable)
- Command timeouts: RFC 5321 compliant timeouts (5 minutes per command)
- Message size limits: SIZE extension with configurable maximum (default: 25MB)
- Queue size limits: Health check fails when queue exceeds threshold (default: 10,000 messages)
- State-aware timeouts: Prevents slowloris attacks (3-minute timeout between data chunks)
Residual Risk: Application-layer DoS still possible. Recommend external rate limiting (iptables, fail2ban).
Scenario: Attacker intercepts SMTP traffic to read or modify messages in transit.
Mitigations:
- STARTTLS support: Upgrade plaintext connections to TLS (RFC 3207)
- Certificate validation: All outbound connections validate certificates by default
- TLS metadata logging: Protocol version and cipher suite logged to context
- Security warnings: WARN-level logs when certificate validation is disabled
Residual Risk: Downgrade attacks if STARTTLS is optional. Recommend require_tls per-domain flag (roadmap).
Scenario: Attacker uses Empath as an open relay to send spam or spoofed messages.
Mitigations:
- No authentication yet: Empath does not currently implement SMTP AUTH (roadmap item)
- Module system: Implement SPF/DKIM validation via custom modules
- IP-based restrictions: Use firewall rules to limit SMTP access
Residual Risk: HIGH. Empath is NOT recommended for public-facing SMTP without authentication.
Scenario: Attacker injects malicious headers or body content via crafted SMTP commands.
Mitigations:
- SMTP command parsing: Zero-allocation parsing with strict RFC 5321 compliance
- ESMTP parameter validation: Duplicate detection, type checking, SIZE=0 rejection
- State machine enforcement: Type-safe state transitions prevent invalid command sequences
- Email address validation: RFC 5321 compliant parsing
Residual Risk: LOW for SMTP protocol. Header injection still possible if modules don't validate content.
Scenario: Unprivileged user gains administrative access to MTA via control socket.
Mitigations:
- Unix domain socket: Local access only (no network exposure)
- Restrictive permissions: Mode 0600 (owner read/write only)
- Token-based authentication: Optional SHA-256 hashed bearer tokens (enabled by default in production)
- Multiple token support: Different access levels possible (admin vs read-only tokens)
- Stale socket detection: Prevents socket hijacking from crashed processes
- Comprehensive audit logging: All control commands logged with user/UID and authentication status
Residual Risk: LOW (with authentication enabled). Filesystem permissions alone provide MEDIUM protection.
Implementation: empath-smtp/src/connection.rs:116-171
Features:
- STARTTLS support: Upgrades plaintext connections to TLS on-demand (RFC 3207)
- TLS library: tokio-rustls with no client authentication
- Metadata preservation: Connection context preserved across TLS upgrade
- Protocol logging: TLS version and cipher suite stored in context metadata
Configuration Example:
extensions: [
{
"starttls": {
"id": "smtp-primary",
"active_profile": "default",
"profiles": {
"default": {
"key": "/etc/empath/tls/private.key",
"certificate": "/etc/empath/tls/certificate.crt",
},
"rotation": {
"key": "/etc/empath/tls/private.next.key",
"certificate": "/etc/empath/tls/certificate.next.crt",
},
},
}
}
]Certificate Formats Supported:
- PKCS#1
- PKCS#8
- SEC1
Post-Upgrade Metadata:
{
"tls": "true",
"protocol": "TLSv1.3",
"cipher": "TLS_AES_256_GCM_SHA384"
}Implementation: empath-delivery/src/smtp_transaction.rs
Certificate Validation Policy:
Empath uses a two-tier configuration system for certificate validation:
-
Global Default (Secure):
delivery: ( accept_invalid_certs: false, // Validate all certificates )
-
Per-Domain Override:
delivery: ( accept_invalid_certs: false, domains: { "test.example.com": ( accept_invalid_certs: true, // Override for testing ONLY ), "secure.example.com": ( accept_invalid_certs: false, // Explicitly require valid certs ), }, )
Priority: Per-domain setting > Global setting
Security Warnings:
When certificate validation is disabled, Empath logs:
WARN SECURITY WARNING: TLS certificate validation is disabled for this connection
domain=test.example.com server=192.168.1.100:25
NEVER set accept_invalid_certs: true in production environments. This setting is ONLY for:
- Local development with self-signed certificates
- Integration testing with mock SMTP servers
- Staging environments with internal CAs
TLS Negotiation (RFC 3207 Compliant):
- Opportunistic TLS: Attempts STARTTLS if advertised, gracefully falls back if fails
- Required TLS: Delivery fails if TLS cannot be negotiated (per-domain
require_tlsflag - roadmap) - Retry logic: Reconnects without TLS if opportunistic STARTTLS fails (RFC 3207 Section 4.1)
Implementation: empath-smtp/src/session/mod.rs
Empath implements state-aware timeouts that follow RFC 5321 Section 4.5.3.2 recommendations:
Configuration:
timeouts: (
command_secs: 300, // 5 minutes - regular commands (EHLO, MAIL FROM, RCPT TO, etc.)
data_init_secs: 120, // 2 minutes - DATA command response
data_block_secs: 180, // 3 minutes - between data chunks during message reception
data_termination_secs: 600, // 10 minutes - processing after final dot (.)
connection_secs: 1800, // 30 minutes - maximum total session lifetime
)How It Works:
-
State-aware selection: Timeout automatically selected based on current SMTP state
Readingstate: Usesdata_block_secs(prevents slowloris attacks)Datastate: Usesdata_init_secsPostDotstate: Usesdata_termination_secs- All other states: Uses
command_secs
-
Connection lifetime enforcement: Checked on every iteration of session loop
-
Graceful shutdown: Connection closed with timeout error when exceeded
Security Benefits:
- ✅ Prevents slowloris attacks (clients sending data very slowly)
- ✅ Prevents resource exhaustion from hung connections
- ✅ Mitigates DoS vulnerabilities from clients holding resources indefinitely
- ✅ Protects against misbehaving SMTP clients
Implementation: empath-delivery/src/types.rs
Configuration:
smtp_timeouts: (
connect_secs: 30, // Initial connection establishment
ehlo_secs: 30, // EHLO/HELO commands
starttls_secs: 30, // STARTTLS command and TLS upgrade
mail_from_secs: 30, // MAIL FROM command
rcpt_to_secs: 30, // RCPT TO command (per recipient)
data_secs: 120, // DATA command and message transmission (longer for large messages)
quit_secs: 10, // QUIT command (best-effort after successful delivery)
)QUIT Timeout Behavior:
Since QUIT occurs after successful delivery, timeout errors are logged but do not fail the delivery:
if let Err(e) = tokio::time::timeout(quit_timeout, client.quit()).await {
tracing::warn!("QUIT command timed out after successful delivery: {e}");
}Empath enforces message size limits at three validation points:
1. SIZE Extension Advertisement (RFC 1870):
extensions: [
{ "size": 25000000 } // 25MB limit advertised to clients
]2. SIZE Parameter Validation (MAIL FROM):
When client declares size via MAIL FROM: <addr> SIZE=12345:
- Validated against advertised maximum before accepting message
- Response:
552 5.2.3 Declared message size exceeds maximum - Location:
empath-ffi/src/modules/core.rs:51-67
3. Actual Message Size Validation (DATA):
During message body reception:
- Checked BEFORE extending buffer (prevents overflow vulnerability)
- Uses
saturating_addto prevent integer overflow on 32-bit systems - Response:
552 Exceeded Storage Allocation - Location:
empath-smtp/src/session/io.rs:54-74
Security Note: Validation BEFORE buffer extension prevents memory exhaustion attacks.
Implementation: empath-health/src/checker.rs
Empath integrates with Kubernetes health checks to prevent queue overflow:
Configuration:
health: (
max_queue_size: 10000, // Readiness probe fails if queue exceeds this
)Behavior:
- Kubernetes readiness probe fails when queue size > threshold
- Pod removed from service endpoints (stops accepting new traffic)
- Auto-recovery when queue drains below threshold
- Prevents accepting new traffic when system is overwhelmed
Implementation: empath-smtp/src/command.rs
Security Features:
- ✅ Case-insensitive command matching
- ✅ Zero-allocation prefix matching (performance)
- ✅ RFC 5321 compliant email address parsing
- ✅ ESMTP parameter parsing with validation
- ✅ State machine enforcement (type-safe transitions)
Implementation: empath-smtp/src/command.rs:64-122
Validation Rules:
-
Duplicate Detection:
- Same parameter cannot appear twice
- Example:
MAIL FROM:<addr> SIZE=1000 SIZE=2000→ REJECTED
-
SIZE Parameter Validation:
- Must be numeric
- Cannot be zero (
SIZE=0→ REJECTED) - Case-insensitive (
size=,SIZE=,SiZe=all valid)
-
Performance:
- Perfect hash map for O(1) known parameter lookup
- Known parameters: SIZE, BODY, AUTH, RET, ENVID, SMTPUTF8
Example Validation:
// Special validation for SIZE parameter
if key_normalized == "SIZE" {
if let Ok(size_val) = value.parse::<usize>() {
if size_val == 0 {
return Err(String::from("SIZE=0 is not allowed"));
}
} else {
return Err(format!("Invalid SIZE value: {value}"));
}
}Test Coverage:
- ✅ SIZE=0 rejection
- ✅ Malformed SIZE values
- ✅ Duplicate SIZE parameters
- ✅ Case-insensitive parsing
Location: empath-smtp/src/command.rs:489-565
Implementation: empath-control/src/server.rs
Empath's control socket provides runtime management via Unix domain socket IPC.
Security Features:
-
Unix Domain Socket (Local IPC Only):
- No network exposure by default
- Path:
/tmp/empath.sock(configurable)
-
Restrictive Permissions:
#[cfg(unix)] { let mut perms = metadata.permissions(); perms.set_mode(0o600); // Owner read/write only tokio::fs::set_permissions(&socket_path, perms).await?; }
-
Stale Socket Detection:
- Tests if socket is active before binding
- Removes stale sockets from crashed processes
- Returns error if active instance already running
-
Connection Timeout:
- 30 seconds per control request
- Prevents resource exhaustion
Multi-User Access (Production):
For environments requiring group access:
# After Empath starts, set permissions:
chown empath:admin /var/run/empath.sock
chmod 660 /var/run/empath.sock # Group read/write- Token-Based Authentication (Optional):
control_auth: ( enabled: true, tokens: [ ( // SHA-256 hash of "read-token" hash: "0328587016f9e316b9c31c94f944a2c453e1494a564062b5eab68039c75b58bf", role: "read_only", ), ( // SHA-256 hash of "admin-token" hash: "10a4c7c9fc5206d6f36dc6944a81bb6f4a3cb0e25014ae3b12e6c3e52712292a", role: "admin", ), ], // token_hashes: ["..."] // legacy admin-only tokens )
Implementation Details:
- Tokens stored as SHA-256 hashes (not plaintext)
- Multiple tokens supported for read-only vs admin access
- Client sends plaintext token, server validates against hash
- Authentication failures logged with warnings
- Read-only tokens can only run list/status commands
Generating Tokens:
# Generate secure token
TOKEN=$(openssl rand -hex 32)
# Generate hash for config
echo -n "$TOKEN" | sha256sumClient Usage:
use empath_control::ControlClient;
let client = ControlClient::new("/tmp/empath.sock")
.with_token("your-secret-token");
let response = client.send_request(request).await?;Deployment Recommendations:
- ✅ Enable authentication in production multi-user environments
- ✅ Use strong cryptographically random tokens (32+ bytes)
- ✅ Rotate tokens periodically
- ✅ Use different tokens for different administrators
- ❌ Don't commit token hashes to version control
- ❌ Don't share tokens across environments
Architecture: Empath pushes metrics to OpenTelemetry Collector (no exposed HTTP endpoint).
Configuration:
metrics: (
enabled: true,
endpoint: "http://otel-collector:4318/v1/metrics",
api_key: "your-metrics-api-key", // Optional API key authentication
)Security Model:
- Empath makes outbound connections only (no listening HTTP server)
- OTLP Collector can then expose to Prometheus
- Securing Prometheus/Grafana is deployment-specific
API Key Authentication (Optional):
When an API key is configured, Empath sends it in the Authorization: Bearer <key> header with all OTLP requests. The collector must be configured to validate the key.
OTLP Collector Configuration Example:
# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
auth:
authenticator: bearertokenauth
extensions:
bearertokenauth:
scheme: "Bearer"
tokens:
- token: "your-metrics-api-key"
service:
extensions: [bearertokenauth]
pipelines:
metrics:
receivers: [otlp]
exporters: [prometheus]Security Considerations:
⚠️ API key stored in plaintext in config (required for OTLP protocol)- ✅ Use environment variable substitution for production:
export METRICS_API_KEY="your-secret-key" # Reference in config: api_key: "$ENV:METRICS_API_KEY" (future)
- ✅ Or use Kubernetes secrets mounting
- ✅ Rotate API keys periodically
- ✅ Use unique keys per environment (dev/staging/prod)
Deployment Recommendations:
- Enable API key authentication for production deployments
- Use network segmentation as defense-in-depth
- Monitor collector logs for authentication failures
- Implement rate limiting at the collector level
Implementation: empath/src/control_handler.rs
All control commands are automatically logged with structured data for accountability and compliance.
Information Logged:
| Field | Description | Example |
|---|---|---|
| command | Command type and details | DNS:ClearCache |
| user | User executing command ($USER) |
alice |
| uid | User ID (Unix only) | 1000 |
| timestamp | Automatic via tracing | 2025-11-15T10:30:45Z |
| result | Success or error details | completed successfully |
Log Format Example:
2025-11-15T10:30:45Z INFO Control command: DNS user=alice uid=1000 command=ClearCache
2025-11-15T10:30:45Z INFO DNS command completed successfully user=alice uid=1000
Audit Events Covered:
- DNS cache operations (clear, refresh, list, overrides)
- System status queries (ping, status)
- Queue management (list, view, delete, retry, stats, process-now)
Security Benefits:
- ✅ Accountability: Track who performed administrative actions
- ✅ Forensics: Investigate security incidents or configuration changes
- ✅ Compliance: Meet audit requirements for mail systems
- ✅ Monitoring: Detect unauthorized access attempts
Log Configuration:
# Enable audit logging
export RUST_LOG=empath=info
# For detailed audit trails, log to file
export RUST_LOG=empath_control=info,empath=infoImplementation: Throughout codebase via tracing framework
Events Logged:
- Connection opened/closed (peer address, duration)
- TLS upgrade events (protocol, cipher)
- Command reception (command, parameters)
- Validation failures (error, rejection reason)
- Spool operations (message ID, size)
- Error responses (4xx/5xx codes)
Example:
2025-11-15T10:32:15Z INFO Connection opened peer=192.168.1.100:54321
2025-11-15T10:32:16Z INFO TLS upgraded protocol=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384
2025-11-15T10:32:18Z INFO Message spooled id=01JCXYZ... size=4523 bytes
Implementation: empath-delivery/src/dns.rs
Security Features:
-
TTL-Based Expiration:
- Respects DNS record TTLs from authoritative servers
- Min TTL: 60 seconds (prevents excessive queries)
- Max TTL: 3600 seconds (ensures eventual refresh)
- Prevents stale cache poisoning
-
Lock-Free Concurrent Caching:
- Uses DashMap for thread-safe access
- No lock contention during lookups
- Atomic TTL expiration checks
-
MX Record Validation:
- Proper MX priority ordering (lower = higher priority)
- Fallback to A/AAAA records if no MX
- Port specification support
-
DNSSEC Validation (Optional):
- Enable DNSSEC verification in the resolver
- Logs validation status (secure/insecure/bogus/indeterminate)
- Strict mode can fail delivery on bogus or indeterminate results
Configuration:
dns: (
min_ttl_secs: 60, // Minimum cache TTL (prevents query flood)
max_ttl_secs: 3600, // Maximum cache TTL (ensures freshness)
dnssec_enabled: true, // Enable DNSSEC validation
dnssec_strict: false, // Fail delivery on bogus/indeterminate DNSSEC
)Cache Management:
Via control socket:
# View current cache with TTLs
empathctl dns list-cache
# Manually refresh domain
empathctl dns refresh example.com
# Clear entire cache (nuclear option)
empathctl dns clear-cacheKnown Limitations:
- DNSSEC validation is optional; if disabled, trust relies on upstream resolver
- Cache poisoning still possible via upstream resolver
❌ INSECURE:
delivery: (
accept_invalid_certs: true, // NEVER in production!
)✅ SECURE:
delivery: (
accept_invalid_certs: false, // Validate all certificates
domains: {
// Only override for explicitly trusted internal domains
"internal.company.com": (
mx_override: "relay.company.com:25",
accept_invalid_certs: false, // Still require valid certs
),
},
)TLS Certificate Setup:
# Install certificates
sudo mkdir -p /etc/empath/tls
sudo cp server.key /etc/empath/tls/private.key
sudo cp server.crt /etc/empath/tls/certificate.crt
sudo chown -R empath:empath /etc/empath/tls
sudo chmod 600 /etc/empath/tls/private.key
sudo chmod 644 /etc/empath/tls/certificate.crtSpool Directory:
# Create spool with restrictive permissions
sudo mkdir -p /var/spool/empath
sudo chown -R empath:empath /var/spool/empath
sudo chmod 700 /var/spool/empath # Owner onlyControl Socket:
# Create socket directory
sudo mkdir -p /var/run/empath
sudo chown empath:empath /var/run/empath
sudo chmod 755 /var/run/empath
# Socket permissions set automatically by Empath (0600)
# For multi-user access, adjust after startup:
sudo chown empath:admin /var/run/empath.sock
sudo chmod 660 /var/run/empath.sockConfiguration File:
# Protect config file (may contain sensitive paths)
sudo chown empath:empath /etc/empath/empath.config.ron
sudo chmod 600 /etc/empath/empath.config.ronCreate dedicated user:
sudo useradd -r -s /bin/false -d /var/spool/empath empathSystemd Service (Example):
[Unit]
Description=Empath MTA
After=network.target
[Service]
Type=simple
User=empath
Group=empath
ExecStart=/usr/local/bin/empath /etc/empath/empath.config.ron
Restart=on-failure
RestartSec=5s
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/spool/empath /var/run/empath
[Install]
WantedBy=multi-user.targetFirewall Rules (iptables example):
# Allow SMTP only from trusted networks
sudo iptables -A INPUT -p tcp --dport 25 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 25 -j DROP
# Rate limiting (optional)
sudo iptables -A INPUT -p tcp --dport 25 -m connlimit --connlimit-above 50 -j REJECT
sudo iptables -A INPUT -p tcp --dport 25 -m recent --set
sudo iptables -A INPUT -p tcp --dport 25 -m recent --update --seconds 60 --hitcount 20 -j DROPRecommendation: Use fail2ban for automated IP blocking based on SMTP errors.
Log to File:
# Systemd journal (automatic)
journalctl -u empath -f
# Or configure file logging via tracing-subscriber
export RUST_LOG=info
export RUST_LOG_FILE=/var/log/empath/empath.logMonitor for Security Events:
# Watch for security warnings
journalctl -u empath | grep -i "security warning"
# Monitor failed deliveries (potential DoS or misconfiguration)
journalctl -u empath | grep -i "delivery failed"
# Track control socket access
journalctl -u empath | grep "Control command"Spool Backup:
# Daily backup of spool directory
sudo tar -czf /backup/empath-spool-$(date +%Y%m%d).tar.gz /var/spool/empath
# Restore
sudo tar -xzf /backup/empath-spool-20250115.tar.gz -C /Queue State Backup:
# Queue state is auto-saved to spool/queue_state.bin
# Backup includes delivery retry schedules
sudo cp /var/spool/empath/queue_state.bin /backup/queue_state-$(date +%Y%m%d).bin-
No SMTP Authentication (AUTH)
- Impact: Cannot restrict who can send mail
- Workaround: Use IP-based firewall rules
- Roadmap: Task 0.28 (high priority)
- Risk: HIGH if exposed to untrusted networks
-
Control Socket Authentication Disabled by Default
- Impact: Control socket security relies on filesystem permissions unless tokens are enabled
- Workaround: Enable
control_authwith role-based tokens for multi-user systems - Roadmap: Task 0.13 (medium priority) resolved via optional control auth
- Risk: MEDIUM if multi-user access is required and auth remains disabled
-
No Rate Limiting Enforcement
- Impact: Configuration exists but not enforced per-domain
- Workaround: Use external rate limiting (iptables, fail2ban)
- Roadmap: Task 3.3 (medium priority)
- Risk: MEDIUM (DoS via excessive connections)
-
DNSSEC Validation Optional
- Impact: DNS queries rely on upstream resolver unless DNSSEC is enabled
- Workaround: Enable
dnssec_enabledand use resolvers with DNSSEC support - Roadmap: Task 1.2.1 completed with optional DNSSEC validation
- Risk: LOW when DNSSEC is enabled; MEDIUM if upstream resolver is untrusted
-
Module Loading Security
- Impact: Malicious shared libraries can execute arbitrary code
- Workaround: Only load trusted modules, run as non-root
- Roadmap: Module signature verification (long-term)
- Risk: HIGH if untrusted modules loaded
-
No SPF/DKIM/DMARC Validation
- Impact: Cannot validate sender authenticity
- Workaround: Implement via custom modules
- Roadmap: Phase 6 (DKIM signing task 6.2)
- Risk: MEDIUM (phishing/spoofing potential)
| Task | Description | Effort | Status |
|---|---|---|---|
| 0.27 | Control socket token auth | 2-3 days | ✅ Complete |
| 0.28 | Metrics endpoint API key | 1-2 days | ✅ Complete |
| - | SMTP AUTH support | 1 week | Planned |
| Task | Description | Effort | Status |
|---|---|---|---|
| 1.2.1 | DNSSEC validation | 2-3 days | ✅ Complete |
| 0.14 | DNS logging and alerting | 1-2 days | Planned |
| Task | Description | Effort | Status |
|---|---|---|---|
| 3.3 | Per-domain rate limiting | 2-3 days | Planned |
| 5.1 | Circuit breakers | 2-3 days | Planned |
| Task | Description | Effort | Status |
|---|---|---|---|
| 6.2 | DKIM signing | 1 week | Planned |
| - | SPF validation | 3-5 days | Research |
| - | DMARC reporting | 1 week | Research |
| Task | Description | Effort | Status |
|---|---|---|---|
| - | Module signature verification | 1-2 weeks | Research |
| - | Sandboxed module execution | 2-3 weeks | Research |
Empath includes security-focused tests:
1. SIZE Validation:
empath-smtp/src/command.rs:489-565- Tests SIZE=0 rejection, malformed values, duplicate parameters
2. Timeout Enforcement:
empath-smtp/src/session/mod.rs:360-398- Tests connection lifetime, state-aware timeout selection
3. TLS Integration:
empath-smtp/tests/client_integration.rs- Tests STARTTLS upgrade, certificate validation
4. Spool Security:
- Cross-platform path validation (prevents Windows system directory creation)
- 16 comprehensive spool tests
Recommended Tools:
-
SMTP Fuzzing:
# Test malformed commands echo "EHLO test\r\nMAIL FROM:<test@example.com> SIZE=abc\r\n" | nc localhost 25 # Test oversized message dd if=/dev/zero bs=1M count=30 | nc localhost 25
-
TLS Testing:
# Verify certificate validation openssl s_client -starttls smtp -connect localhost:25 # Test with invalid cert (should fail in production) openssl s_client -starttls smtp -connect test.example.com:25
-
Control Socket Security:
# Verify permissions ls -la /var/run/empath.sock # Should show: srw------- (0600) # Test unauthorized access (filesystem permissions) sudo -u nobody empathctl system status # Should fail with permission denied # Test authentication (if enabled) empathctl system status # Without token - should fail empathctl --token "wrong-token" system status # Invalid token - should fail empathctl --token "$VALID_TOKEN" system status # Valid token - should succeed # Check authentication logs grep "authentication" /var/log/empath.log # Should show authentication events with user/UID
-
Metrics Authentication:
# Monitor OTLP collector logs for auth failures docker logs otel-collector | grep "401\|403" # Test with invalid API key # (Modify config temporarily with wrong key, check collector logs)
Empath MTA uses multiple automated tools to detect security vulnerabilities in dependencies and maintain supply chain transparency.
cargo-audit scans Rust dependencies against the RustSec Advisory Database for known security vulnerabilities.
Automated Scanning (CI):
- Runs daily at 00:00 UTC via scheduled workflow
- Runs on every push/PR that modifies
Cargo.lock - Fails CI on HIGH and CRITICAL vulnerabilities
- Generates JSON audit reports (available as artifacts for 30 days)
Local Usage:
# Run security audit
just deps-audit
# Or directly with cargo
cargo audit
# Check specific advisory
cargo audit --ignore RUSTSEC-YYYY-NNNNConfiguration: .gitea/workflows/security.yml
cargo-deny enforces policies for licenses, sources, and security advisories.
Automated Checks (CI):
- Runs as part of security workflow
- Validates license compliance
- Ensures dependencies come from trusted sources
- Blocks banned or yanked crates
Local Usage:
cargo deny checkConfiguration: deny.toml (if exists)
Empath generates CycloneDX-format SBOMs for compliance and supply chain security.
What is an SBOM? A Software Bill of Materials (SBOM) is a comprehensive inventory of all components, libraries, and dependencies used in the software. It enables:
- Supply chain transparency
- Vulnerability tracking
- Compliance auditing (NIST, EU Cyber Resilience Act)
- License compliance verification
SBOM Generation (CI):
- Security Workflow: Generated on every run, available as artifacts for 90 days
- Release Workflow: Generated for every tagged release (
v*), available for 365 days - Formats: Both JSON and XML (CycloneDX 1.4+)
- Checksums: SHA256 checksums included for integrity verification
Local Generation:
# Install cargo-cyclonedx
cargo install cargo-cyclonedx
# Generate SBOM (JSON format, recommended)
cargo cyclonedx --format json --all
# Generate SBOM (XML format)
cargo cyclonedx --format xml --allSBOM Artifacts: empath-<version>-sbom.{json,xml}
Using SBOMs:
# Download from release artifacts
wget https://gitea.example.com/pyxxil/empath/releases/download/v1.0.0/empath-1.0.0-sbom.json
# Verify checksum
sha256sum empath-1.0.0-sbom.json
cat empath-sbom-checksums.txt
# Analyze with dependency-track or similar tools
docker run -d -p 8080:8080 dependencytrack/bundled
# Upload empath-1.0.0-sbom.json via web UIRenovate Bot monitors dependencies and creates automated update PRs.
Features:
- Automatic detection of new versions
- Security patch prioritization
- Grouped updates by category
- Automated vulnerability scanning
Workflow:
- Renovate detects new version
- Creates PR with changelog
- CI runs cargo-audit on updated dependencies
- Review and merge if tests pass
When a security vulnerability is discovered in a dependency:
-
Identify Vulnerability:
# Check cargo-audit output cargo audit # Check RustSec advisory details # Example: https://rustsec.org/advisories/RUSTSEC-2024-1234
-
Assess Severity (based on RustSec severity):
- CRITICAL: Address immediately (within 24 hours)
- Remote code execution, privilege escalation
- Update deployed systems immediately
- HIGH: Address urgently (within 48 hours)
- Memory safety issues, authentication bypass
- Coordinate emergency patch release
- MEDIUM: Address within 1 week
- Denial of service, information disclosure
- Include in next scheduled release
- LOW: Address in next release cycle
- Minor security improvements
- Bundle with other updates
- CRITICAL: Address immediately (within 24 hours)
-
Update Dependencies:
# Update specific vulnerable dependency cargo update -p <crate-name> # Verify vulnerability is resolved cargo audit # Run full test suite just ci
-
Test Changes:
# Run tests cargo nextest run # Run E2E tests cargo nextest run --test e2e_basic --test-threads=1 # Run security-specific tests (if applicable) cargo test security
-
Document in CHANGELOG:
# Generate updated changelog just changelog # Manually add security advisory details: # - RUSTSEC-YYYY-NNNN advisory reference # - Affected versions # - CVE ID (if assigned) # - Credit to reporter (if applicable)
-
Release Patch:
# Tag release with version bump git tag v0.0.X git push origin v0.0.X # CI will automatically: # - Build release binaries # - Generate SBOM # - Publish Docker images # - Create forge release
-
Notify Users:
- Forge security advisory (if applicable)
- Release notes with security section
- Email notification to maintainers mailing list
- Update docs/SECURITY.md with resolution
Monitoring for Vulnerabilities:
- Watch Repository: Enable notifications for security advisories
- Subscribe to Renovate PRs: If you've forked the repository
- Regular Audits: Run
cargo auditweekly in your deployment - Check CI Artifacts: Security audit reports available in workflow artifacts
Updating Empath:
Source Build:
# Pull latest changes
cd /path/to/empath
git pull origin main
# Verify no vulnerabilities
cargo audit
# Rebuild with updated dependencies
cargo build --release
# Run tests (recommended)
cargo nextest run
# Deploy updated binary
sudo systemctl stop empath
sudo cp target/release/empath /usr/local/bin/
sudo systemctl start empath
# Verify
empathctl system statusDocker Deployment:
# Pull latest image
docker pull git.pyxxilated.media/pyxxil/empath:latest
# Restart services
docker-compose down
docker-compose up -d
# Verify
docker logs empath --tail 50Binary Release (if available):
# Download latest release
wget https://gitea.example.com/pyxxil/empath/releases/download/v1.0.0/empath-linux-x86_64
# Verify checksum
sha256sum empath-linux-x86_64
cat empath-linux-x86_64.sha256
# Deploy
sudo systemctl stop empath
sudo mv empath-linux-x86_64 /usr/local/bin/empath
sudo chmod +x /usr/local/bin/empath
sudo systemctl start empathEmergency Patching (critical vulnerabilities):
- Subscribe to security advisories
- Apply patches within 24 hours
- Test in staging environment first (if time permits)
- Update production immediately
- Monitor logs for exploitation attempts
Rollback Procedure (if update causes issues):
# Docker
docker-compose down
docker run ... pyxxil/empath:v0.0.X-old # Previous version
# Source/Binary
sudo systemctl stop empath
sudo cp /usr/local/bin/empath.backup /usr/local/bin/empath
sudo systemctl start empath| Severity | Initial Response | Patch Release | User Notification |
|---|---|---|---|
| CRITICAL | 4 hours | 24 hours | Immediate |
| HIGH | 24 hours | 48 hours | Within 24h |
| MEDIUM | 48 hours | 7 days | Next release notes |
| LOW | Best effort | Next release | Changelog |
- CLAUDE.md: Development guide with security implementation details
- TODO.md: Security roadmap and planned improvements
- Production Config Example:
examples/config/production.ron - SMTP RFCs: RFC 5321 (SMTP), RFC 3207 (STARTTLS), RFC 1870 (SIZE)
- Security Standards: OWASP Email Security Cheat Sheet
Document Version: 1.1 Last Updated: 2025-12-04 Maintainer: Empath MTA Project