Threat Model
Overview
This document identifies security threats to the proxy server and our mitigation strategies.
Last Updated: January 26, 2026
Next Review: April 26, 2026
Trust Model
UNTRUSTED → [Proxy (Trust Boundary)] → TRUSTED- Everything before the proxy is untrusted
- Everything after is trusted (assumes validation passed)
Attack Vectors & Mitigations
1. Server-Side Request Forgery (SSRF)
Risk Level: 🔴 CRITICAL
Attack
Attacker manipulates proxy to make requests to internal services:
POST /proxy
{
"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
}Impact
- Access to cloud metadata endpoints (AWS, GCP, Azure)
- Internal service enumeration
- Exfiltration of secrets
Mitigations
✅ Implemented:
- Allow-list of target hosts (no arbitrary URLs)
- IP blacklist: Block private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8)
- Block cloud metadata IPs: 169.254.169.254, fd00:ec2::254
- DNS rebinding protection: Resolve and validate target IP before connecting
- Protocol restriction: Only HTTP/HTTPS (no file://, gopher://, etc.)
✅ Configuration:
proxy:
allowedHosts:
- "api.example.com"
- "*.internal.corp"
blockedIPs:
- "169.254.169.254"
- "10.0.0.0/8"
- "127.0.0.0/8"What We Don't Block (And Why)
- ❌ DNS-based SSRF via TTL manipulation → Mitigation: DNS caching (60s TTL)
- ❌ IPv6 SSRF variants → Future work: Add IPv6 range validation
2. Header Injection
Risk Level: 🟠 HIGH
Attack
Inject malicious headers via unvalidated input:
GET /proxy?target=evil.com HTTP/1.1
X-Custom-Header: foo\r\nX-Admin: trueImpact
- HTTP response splitting
- Cache poisoning
- Authentication bypass
Mitigations
✅ Implemented:
- Header sanitization: Strip CRLF (\r\n) from all header values
- Forbidden headers: Block
Host,Connection,Transfer-Encodingfrom client - Header size limits: Max 8KB per header, 32KB total
const FORBIDDEN_HEADERS = ['host', 'connection', 'transfer-encoding', 'upgrade'];
const SANITIZE_REGEX = /[\r\n]/g;3. Denial of Service (DoS)
Risk Level: 🟠 HIGH
Attack Variants
3a. Request Flood
High volume of requests exhaust resources.
Mitigations: ✅ Rate limiting (token bucket algorithm) ✅ Connection limits per IP ✅ Request size limits
3b. Slowloris
Client sends headers slowly to exhaust connections.
Mitigations: ✅ Header timeout (10s) ✅ Request timeout (30s) ✅ Idle connection timeout (60s)
3c. Large Payload
Massive request/response bodies consume memory.
Mitigations: ✅ Max body size: 10MB request, 50MB response ✅ Streaming responses (no buffering) ✅ Memory-based backpressure
Configuration
limits:
rateLimit:
windowMs: 60000
max: 100
requestTimeout: 30000
maxBodySize: 10485760 # 10MB4. Authentication Bypass
Risk Level: 🔴 CRITICAL
Attack
- Reuse expired tokens
- Forge signatures
- Missing authentication on routes
Mitigations
✅ Implemented:
- API Key validation: HMAC-SHA256 signature verification
- Key rotation: Support multiple valid keys during rotation
- Time-based validation: Reject requests with timestamp drift > 5 minutes
- Deny by default: Routes require explicit
auth: truein config
routes:
- path: "/api/*"
auth: required # Explicit opt-in
upstream: "https://api.backend.com"What We Don't Do (Intentionally)
- ❌ OAuth/OIDC flows → Reason: Complexity, use Kong/Auth0 for this
- ❌ Session management → Reason: Stateless design
5. Path Traversal
Risk Level: 🟡 MEDIUM
Attack
GET /proxy/../../../etc/passwdMitigations
✅ Implemented:
- Path normalization: Resolve
..before routing - Absolute path validation: No paths outside configured base
- Reject encoded slashes: Block
%2F,%5C
6. Injection Attacks
Risk Level: 🟡 MEDIUM
6a. Command Injection
Not applicable (no shell commands executed).
6b. NoSQL Injection
If config uses MongoDB, attacker could inject queries.
Mitigations: ✅ Config is YAML/JSON (loaded at startup, not runtime) ✅ No dynamic query construction
6c. Log Injection
Inject newlines to forge log entries:
username: "admin\n[ERROR] Authentication failed for admin"Mitigations: ✅ Structured logging (JSON) ✅ Field sanitization (escape special chars)
7. Information Disclosure
Risk Level: 🟡 MEDIUM
Attack
- Stack traces in error responses
- Debug endpoints in production
- Verbose error messages
Mitigations
✅ Implemented:
- Environment-based responses:
- Production: Generic errors (
"Internal Server Error") - Development: Full stack traces
- Production: Generic errors (
- Health endpoint: No sensitive info
- Header filtering: Remove
X-Powered-By, upstream headers
app.use((err, req, res, next) => {
res.status(err.status || 500).json({
error: process.env.NODE_ENV === 'production'
? 'Internal Server Error'
: err.message
});
});8. Man-in-the-Middle (MitM)
Risk Level: 🟠 HIGH
Attack
Intercept traffic between proxy and upstream.
Mitigations
✅ Implemented:
- Enforce HTTPS to upstream (configurable)
- Certificate validation (reject self-signed in prod)
- TLS 1.2+ only
- HSTS headers (downstream)
What We Don't Do
- ❌ Certificate pinning → Reason: Operational complexity
- ❌ mTLS to upstream → Future work
Threat Scenarios We Accept
Compromised Upstream
Scenario: Backend service is compromised.
Impact: Proxy forwards malicious responses.
Why We Accept:
- Backend is in trusted zone
- Proxy can't validate business logic
- Mitigation: Response size limits, timeout enforcement
Config File Tampering
Scenario: Attacker modifies config files.
Impact: Complete compromise.
Why We Accept:
- Config is in trusted deployment pipeline
- File system access implies full compromise anyway
- Mitigation: Config validation on load, signature verification (future)
Memory Exhaustion via Legitimate Traffic
Scenario: Spike in traffic causes OOM.
Impact: Crash and restart.
Why We Accept:
- Node.js memory model makes this hard to prevent
- Mitigation: Connection limits, k8s resource limits, circuit breaker
Security Checklist (Pre-Deployment)
- [ ] All routes have explicit auth requirements
- [ ] Allowed hosts list is minimal
- [ ] Rate limits configured per route
- [ ] Secrets in env vars (not config files)
- [ ] HTTPS enforced to upstream
- [ ] Health endpoint doesn't leak info
- [ ] Logs don't contain PII/secrets
- [ ] Timeouts configured
- [ ] Error responses sanitized for production
Incident Response
If SSRF Detected
- Identify target host from logs (correlation ID)
- Add to
blockedIPsimmediately - Deploy updated config (< 5 min)
- Review all requests from that client IP
- Rotate API keys
If DoS Detected
- Enable rate limit override (stricter limits)
- Add IP to block list
- Scale horizontally if legitimate traffic
- Check circuit breaker status
If Auth Bypass Detected
- Rotate all API keys immediately
- Review auth logs for time window
- Check for config errors
- Deploy fix + re-auth all clients
Future Work
- WAF Integration: Integrate with ModSecurity/Coraza
- mTLS: Mutual TLS to backend services
- Request Signing: HMAC-signed request bodies
- Anomaly Detection: ML-based traffic analysis
- Config Signing: Cryptographically sign config files