mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-16 13:38:33 +00:00
fix(api): add tiered rate limiting to prevent polling lockouts (#460)
* fix(api): add tiered rate limiting to prevent polling lockouts Replace the single global rate limiter (100 req/min/IP) with a tiered system that separates high-frequency polling endpoints from standard API traffic: - Polling tier (300/min): /stats, /system/stats, /stacks/statuses, /metrics/historical, /health, /meta, /auth/status, /auth/sso/providers, /license. Exempt from the global limiter but governed by their own safety net to prevent resource exhaustion. - Standard tier (200/min): All other endpoints, raised from 100. - Webhook tier (500/min): POST /webhooks/:id/trigger, dedicated limiter for CI/CD platforms sharing datacenter IPs. - Auth tier: Unchanged (5-10 attempts / 15 min). Enterprise adaptations: - Authenticated requests keyed by user session (JWT sub/username) instead of IP, preventing shared NAT/VPN environments from pooling budgets. - Internal node-to-node traffic (node_proxy tokens) bypasses all rate limiters entirely. Includes comprehensive stress tests (21 cases) validating tier separation, node proxy bypass, and per-user keying. * chore(deps): bump axios to 1.15.0 to fix SSRF vulnerability Addresses GHSA-3p68-rc4w-qgx5 (NO_PROXY hostname normalization bypass).
This commit is contained in:
@@ -88,7 +88,20 @@ This applies to all stack endpoints: read, write, deploy, down, restart, stop, s
|
||||
|
||||
## Rate limiting
|
||||
|
||||
All API endpoints are rate-limited per IP address. Authentication endpoints have stricter limits to prevent brute-force attacks. When exceeded, the server responds with `429 Too Many Requests`:
|
||||
Sencho uses a tiered rate limiting system that balances security with usability:
|
||||
|
||||
| Tier | Limit | Applies to | Keyed by |
|
||||
|------|-------|------------|----------|
|
||||
| **Polling** | 300/min | Dashboard status endpoints (`/stats`, `/system/stats`, `/stacks/statuses`, etc.) | User session |
|
||||
| **Standard** | 200/min | All other API endpoints | User session |
|
||||
| **Webhooks** | 500/min | `POST /webhooks/:id/trigger` | IP address |
|
||||
| **Auth** | 5-10/15min | Login, setup, SSO endpoints | IP address |
|
||||
|
||||
Authenticated requests (browser sessions and API tokens) are rate-limited per user, not per IP. This prevents teams behind shared NAT or VPN from pooling rate limit budgets. Unauthenticated requests fall back to IP-based limiting.
|
||||
|
||||
Internal node-to-node traffic (requests authenticated with node proxy tokens) bypasses rate limiting entirely.
|
||||
|
||||
When exceeded, the server responds with `429 Too Many Requests`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -98,6 +111,8 @@ All API endpoints are rate-limited per IP address. Authentication endpoints have
|
||||
|
||||
Standard rate limit headers (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`) are included in all API responses, so clients can self-throttle accordingly.
|
||||
|
||||
The default limits can be tuned via environment variables (`API_RATE_LIMIT`, `API_POLLING_RATE_LIMIT`). See [Self-Hosting](/operations/self-hosting) for details.
|
||||
|
||||
## License tier requirements
|
||||
|
||||
Some endpoints are gated by license tier:
|
||||
|
||||
@@ -89,7 +89,8 @@ Quick reference for all environment variables. See [Configuration](/getting-star
|
||||
| `COMPOSE_DIR` | `/app/compose` | Path to compose project files (1:1 rule applies) |
|
||||
| `DATA_DIR` | `/app/data` | Persistent data directory |
|
||||
| `FRONTEND_URL` | *(empty)* | Frontend origin for CORS; leave empty for same-origin |
|
||||
| `API_RATE_LIMIT` | `100` | Maximum API requests per minute per IP (production only) |
|
||||
| `API_RATE_LIMIT` | `200` | Maximum API requests per minute per user session (production only) |
|
||||
| `API_POLLING_RATE_LIMIT` | `300` | Rate limit for dashboard polling endpoints (production only) |
|
||||
| `NODE_ENV` | `production` | Set automatically in the Docker image |
|
||||
|
||||
SSO variables are documented separately in the [SSO Quickstart](/getting-started/sso-quickstart).
|
||||
|
||||
@@ -13,7 +13,7 @@ A comprehensive security audit was performed before the Sencho paid tiers launch
|
||||
|
||||
- **Path traversal prevention** in `env_file` resolution, preventing reads outside the compose directory
|
||||
- **Stack name validation** enforced on all routes, rejecting names with special characters or path components
|
||||
- **Global API rate limiting** to protect against brute-force and abuse
|
||||
- **Tiered API rate limiting** with per-user session keying to protect against brute-force and abuse
|
||||
|
||||
### Authentication and secrets
|
||||
|
||||
|
||||
Reference in New Issue
Block a user