-
-
Notifications
You must be signed in to change notification settings - Fork 69.1k
Feature: Gateway rate limiting and security headers #20373
Copy link
Copy link
Open
Labels
securitySecurity documentationSecurity documentationstaleMarked as stale due to inactivityMarked as stale due to inactivity
Description
Problem
Gateway has no rate limiting and no security headers. When exposed via Tailscale Funnel or public reverse proxy, any client can send unlimited requests.
Current Behavior
- No per-IP or per-session request limits
- No security headers (CSP, HSTS, X-Frame-Options)
- No abuse detection or throttling
- Admin dashboard served without security headers
Proposed Implementation
1. Rate Limiting Middleware
import { RateLimiter } from "./rate-limiter";
const limiter = new RateLimiter({
windowMs: 60_000, // 1 minute window
maxRequests: 60, // per IP
maxPerSession: 30, // per authenticated session
keyGenerator: (req) => req.ip || req.headers["x-forwarded-for"],
onLimit: (req, res) => {
res.status(429).json({
error: "rate_limited",
retryAfterMs: limiter.getRetryAfter(req),
});
},
});
// Apply to gateway routes
app.use("/api/", limiter.middleware());2. Security Headers
const SECURITY_HEADERS = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "0", // modern browsers use CSP instead
"Referrer-Policy": "strict-origin-when-cross-origin",
"Content-Security-Policy": "default-src 'self'; script-src 'self'",
"Permissions-Policy": "camera=(), microphone=(), geolocation=()",
// Only when HTTPS:
// "Strict-Transport-Security": "max-age=31536000; includeSubDomains",
};
app.use((req, res, next) => {
for (const [key, value] of Object.entries(SECURITY_HEADERS)) {
res.setHeader(key, value);
}
next();
});3. Request Validation
- Maximum request body size enforcement (already via body-parser, verify limit)
- Input sanitization on user-provided fields
- Session token validation with constant-time comparison
4. Configuration
{
"security": {
"rateLimit": {
"enabled": true,
"windowMs": 60000,
"maxRequests": 60,
"maxPerSession": 30
},
"headers": {
"enabled": true,
"hsts": false,
"csp": "default-src 'self'"
}
}
}5. Endpoint-Specific Limits
| Endpoint | Limit | Window |
|---|---|---|
/api/chat |
20/min | per session |
/api/sessions |
60/min | per IP |
/health |
120/min | per IP |
| Admin routes | 30/min | per IP |
Files to Modify
src/gateway/middleware/rate-limiter.ts- new rate limitersrc/gateway/middleware/security-headers.ts- header injectionsrc/gateway/server.ts- middleware registrationsrc/config/schema.ts- security config section
Dependencies
None - can use in-memory token bucket (no Redis needed for single-instance).
Environment
- Gateway on loopback (default config)
- Can be exposed via Tailscale Serve/Funnel
- Admin dashboard served from same process
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
securitySecurity documentationSecurity documentationstaleMarked as stale due to inactivityMarked as stale due to inactivity
Type
Fields
Give feedbackNo fields configured for issues without a type.