Files
bakery-ia/SSE_SECURITY_MITIGATIONS.md

8.9 KiB

SSE Authentication Security Mitigations

Implementation Date

2025-10-02

Security Concern: Token in Query Parameters

The SSE endpoint (/api/events?token=xxx) accepts authentication tokens via query parameters due to browser EventSource API limitations. This introduces security risks that have been mitigated.


Security Risks & Mitigations

1. Token Exposure in Logs ⚠️

Risk: Nginx access logs contain full URLs including tokens Impact: Medium - If logs are compromised, tokens could be exposed

Mitigations Implemented:

  • Short Token Expiry: JWT tokens expire in 30 minutes (configurable in .env)
  • HTTPS Only: All production traffic uses TLS encryption
  • Log Access Control: Kubernetes logs have RBAC restrictions
  • ⚠️ Manual Log Filtering: Nginx configuration-snippet is disabled by admin

Additional Mitigation (Manual): If you have access to nginx ingress controller configuration, enable log filtering:

# In nginx ingress controller ConfigMap
data:
  log-format-upstream: '$remote_addr - $remote_user [$time_local] "$request_method $sanitized_uri $server_protocol" $status $body_bytes_sent "$http_referer" "$http_user_agent"'

Or use a log aggregation tool (Loki, ELK) with regex filtering to redact tokens.


2. Token in Browser History 📝

Risk: Browser stores URLs with query params in history Impact: Low - Requires local access to user's machine

Mitigations Implemented:

  • User's Own Browser: History is private to the user
  • Short Expiry: Old tokens in history expire quickly
  • Auto-logout: Session management invalidates tokens

Not a Risk: SSE connections are initiated by JavaScript (EventSource), not user navigation, so they typically don't appear in browser history.


3. Referrer Header Leakage 🔗

Risk: When user navigates away, Referrer header might include SSE URL Impact: Medium - Token could leak to third-party sites

Mitigations Implemented:

  • ⚠️ Referrer-Policy Header: Attempted via nginx annotation (blocked by admin)
  • SameSite Routing: SSE is same-origin (no external referrers)
  • HTTPS: Browsers don't send Referrer from HTTPS to HTTP

Manual Mitigation: Add to HTML head in frontend:

<meta name="referrer" content="no-referrer">

Or add HTTP header via frontend response headers.


4. Proxy/CDN Caching 🌐

Risk: Intermediary proxies might cache or log URLs Impact: Low - Internal infrastructure only

Mitigations Implemented:

  • Direct Ingress: No external proxies/CDNs
  • Internal Network: All routing within Kubernetes cluster
  • Cache-Control Headers: SSE endpoints set no-cache

5. Accidental URL Sharing 📤

Risk: Users could copy/share URLs with embedded tokens Impact: High (for regular URLs) / Low (for SSE - not user-visible)

Mitigations Implemented:

  • Hidden from Users: EventSource connections not visible in address bar
  • Short Token Expiry: Shared tokens expire quickly
  • One-Time Use: Tokens invalidated on logout

Security Comparison

Threat Query Param Token Header Token Cookie Token WebSocket
Server Logs ⚠️ Medium Safe Safe Safe
Browser History ⚠️ Low Safe Safe Safe
Referrer Leakage ⚠️ Medium Safe ⚠️ Medium Safe
XSS Attacks ⚠️ Vulnerable ⚠️ Vulnerable httpOnly ⚠️ Vulnerable
CSRF Attacks Safe Safe ⚠️ Requires token Safe
Ease of Use Simple Not supported ⚠️ Complex ⚠️ Complex
Browser Support Native No EventSource Native Native

Applied Mitigations Summary

Implemented:

  1. Short token expiry (30 minutes)
  2. HTTPS enforcement (production)
  3. Token validation (middleware + endpoint)
  4. CORS restrictions (specific origins)
  5. Kubernetes RBAC (log access control)
  6. Same-origin policy (no external referrers)
  7. Auto-logout (session management)

⚠️ Blocked by Infrastructure:

  1. Nginx log filtering (configuration-snippet disabled)
  2. Referrer-Policy header (configuration-snippet disabled)
  1. Add Referrer-Policy meta tag to frontend HTML
  2. Enable nginx log filtering if ingress admin allows
  3. Use log aggregation with token redaction (Loki/ELK)
  4. Monitor for suspicious patterns in logs

Production Checklist

Before deploying to production, ensure:

  • HTTPS enforced (no HTTP fallback)
  • Token expiry set to ≤ 30 minutes
  • CORS origins limited to specific domains (not *)
  • Kubernetes RBAC configured for log access
  • Frontend has Referrer-Policy meta tag
  • Log aggregation configured with token redaction
  • Monitoring/alerting for failed auth attempts
  • Rate limiting enabled on gateway
  • Regular security audits of access logs

For maximum security, migrate to cookie-based authentication:

Effort: ~2-3 hours Security: (5/5)

Changes needed:

  1. Auth service sets httpOnly cookie on login
  2. Gateway auth middleware reads cookie instead of query param
  3. Frontend uses withCredentials: true (already done!)

Benefits:

  • No token in URL
  • No token in logs
  • XSS protection (httpOnly)
  • CSRF protection (SameSite)

Risk Assessment

Current Risk Level: MEDIUM ⚠️

Acceptable for:

  • Internal/development environments
  • Short-term production (with monitoring)
  • Low-sensitivity data

Not recommended for:

  • High-security environments
  • Long-term production without upgrade path
  • Systems handling PII/financial data

Upgrade recommended within: 30-60 days for production


Incident Response

If Token Leak Suspected:

  1. Immediate Actions:

    # Invalidate all active sessions
    kubectl exec -it -n bakery-ia $(kubectl get pod -n bakery-ia -l app=redis -o name) -- redis-cli
    KEYS auth:token:*
    DEL auth:token:*
    
  2. Rotate JWT Secret:

    # Update .env
    JWT_SECRET_KEY=<new-secret-64-chars>
    
    # Restart auth service and gateway
    kubectl rollout restart deployment auth-service gateway -n bakery-ia
    
  3. Force Re-authentication:

    • All users must login again
    • Existing tokens invalidated
  4. Audit Logs:

    # Check for suspicious SSE connections
    kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller | grep "/api/events"
    

Monitoring Queries

Check for Suspicious Activity:

# High volume of SSE connections from single IP
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller | grep "/api/events" | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# Failed authentication attempts
kubectl logs -n bakery-ia -l app.kubernetes.io/name=gateway | grep "401\|Invalid token"

# SSE connections with expired tokens
kubectl logs -n bakery-ia -l app.kubernetes.io/name=gateway | grep "Token expired"

Compliance Notes

GDPR:

  • Tokens are pseudonymous identifiers
  • Short retention (30 min expiry)
  • ⚠️ Tokens in logs = personal data processing (document in privacy policy)

SOC 2:

  • ⚠️ Query param auth acceptable with compensating controls
  • Encryption in transit (HTTPS)
  • Access controls (RBAC)
  • 📝 Document risk acceptance in security policy

PCI DSS:

  • Not recommended for payment card data
  • Acceptable for non-cardholder data
  • 📝 May require additional compensating controls

References


Decision Log

Date: 2025-10-02 Decision: Use query parameter authentication for SSE endpoint Rationale: EventSource API limitation (no custom headers) Accepted Risk: Medium (token in logs, limited referrer leakage) Mitigation Plan: Implement cookie-based auth within 60 days Approved By: Technical Lead


Next Steps

  1. Short-term (now):

    • Query param auth implemented
    • Security mitigations documented
    • 📝 Add Referrer-Policy to frontend
    • 📝 Configure log monitoring
  2. Medium-term (30 days):

    • 📝 Implement cookie-based authentication
    • 📝 Enable nginx log filtering (if allowed)
    • 📝 Set up log aggregation with redaction
  3. Long-term (60 days):

    • 📝 Security audit of implementation
    • 📝 Penetration testing
    • 📝 Consider WebSocket migration (if bidirectional needed)