Add fixes to procurement logic and fix rel-time connections
This commit is contained in:
291
SSE_SECURITY_MITIGATIONS.md
Normal file
291
SSE_SECURITY_MITIGATIONS.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# 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:
|
||||
```yaml
|
||||
# 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:
|
||||
```html
|
||||
<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)
|
||||
|
||||
### 📝 Recommended (Manual):
|
||||
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
|
||||
|
||||
---
|
||||
|
||||
## Upgrade Path to Cookie-Based Auth
|
||||
|
||||
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:**
|
||||
```bash
|
||||
# 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:**
|
||||
```bash
|
||||
# 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:**
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
- [OWASP: Transport Layer Protection](https://owasp.org/www-community/controls/Transport_Layer_Protection)
|
||||
- [EventSource API Spec](https://html.spec.whatwg.org/multipage/server-sent-events.html)
|
||||
- [RFC 6750: OAuth 2.0 Bearer Token Usage](https://www.rfc-editor.org/rfc/rfc6750.html#section-2.3)
|
||||
|
||||
---
|
||||
|
||||
## 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)
|
||||
Reference in New Issue
Block a user