Skip to content

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:

http
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:

  1. Allow-list of target hosts (no arbitrary URLs)
  2. 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)
  3. Block cloud metadata IPs: 169.254.169.254, fd00:ec2::254
  4. DNS rebinding protection: Resolve and validate target IP before connecting
  5. Protocol restriction: Only HTTP/HTTPS (no file://, gopher://, etc.)

✅ Configuration:

yaml
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:

http
GET /proxy?target=evil.com HTTP/1.1
X-Custom-Header: foo\r\nX-Admin: true

Impact ​

  • HTTP response splitting
  • Cache poisoning
  • Authentication bypass

Mitigations ​

✅ Implemented:

  1. Header sanitization: Strip CRLF (\r\n) from all header values
  2. Forbidden headers: Block Host, Connection, Transfer-Encoding from client
  3. Header size limits: Max 8KB per header, 32KB total
javascript
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 ​

yaml
limits:
  rateLimit:
    windowMs: 60000
    max: 100
  requestTimeout: 30000
  maxBodySize: 10485760  # 10MB

4. Authentication Bypass ​

Risk Level: 🔴 CRITICAL

Attack ​

  • Reuse expired tokens
  • Forge signatures
  • Missing authentication on routes

Mitigations ​

✅ Implemented:

  1. API Key validation: HMAC-SHA256 signature verification
  2. Key rotation: Support multiple valid keys during rotation
  3. Time-based validation: Reject requests with timestamp drift > 5 minutes
  4. Deny by default: Routes require explicit auth: true in config
yaml
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 ​

http
GET /proxy/../../../etc/passwd

Mitigations ​

✅ Implemented:

  1. Path normalization: Resolve .. before routing
  2. Absolute path validation: No paths outside configured base
  3. 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:

  1. Environment-based responses:
    • Production: Generic errors ("Internal Server Error")
    • Development: Full stack traces
  2. Health endpoint: No sensitive info
  3. Header filtering: Remove X-Powered-By, upstream headers
javascript
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:

  1. Enforce HTTPS to upstream (configurable)
  2. Certificate validation (reject self-signed in prod)
  3. TLS 1.2+ only
  4. 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 ​

  1. Identify target host from logs (correlation ID)
  2. Add to blockedIPs immediately
  3. Deploy updated config (< 5 min)
  4. Review all requests from that client IP
  5. Rotate API keys

If DoS Detected ​

  1. Enable rate limit override (stricter limits)
  2. Add IP to block list
  3. Scale horizontally if legitimate traffic
  4. Check circuit breaker status

If Auth Bypass Detected ​

  1. Rotate all API keys immediately
  2. Review auth logs for time window
  3. Check for config errors
  4. Deploy fix + re-auth all clients

Future Work ​

  1. WAF Integration: Integrate with ModSecurity/Coraza
  2. mTLS: Mutual TLS to backend services
  3. Request Signing: HMAC-signed request bodies
  4. Anomaly Detection: ML-based traffic analysis
  5. Config Signing: Cryptographically sign config files

References ​

Released under the MIT License.