Skip to content

Feature: Gateway rate limiting and security headers #20373

@devctx00

Description

@devctx00

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 limiter
  • src/gateway/middleware/security-headers.ts - header injection
  • src/gateway/server.ts - middleware registration
  • src/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

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity documentationstaleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions