fix: rate limit /token and /revoke, bucket IPv6 by /64 and warn about untrusted forwarded headers (SEC-08)

This commit is contained in:
Latte committed 2026-10-14 17:29:12 +02:00
1 parent 782d416e46
commit f57c237bed
7 files changed
+273 -16

No files matched your search

+5 -4
View File
@@ -97,7 +97,7 @@ Denial of service
|---|---|---|
| Large request bodies | SDK body limit on the MCP endpoint and SDK OAuth routes; upload cap checked before decoding | `server.py` (`max_request_body_size`), `gitea/encoding.py` (consent route: SEC-01) |
| Large or hostile responses | 16 MiB text cap, `MAX_BINARY_BYTES`, 64 KiB error bodies, JSON depth 100, item and character limits | `gitea/executor.py` |
| Request floods | Sliding window per IP and per token hash, bounded key sets, rate-limit events audited once per window | `rate_limit.py`, `transports.py` (gaps: SEC-08) |
| Request floods | Sliding window per IP and per token hash, bounded key sets, rate-limit events audited once per window | `rate_limit.py`, `transports.py` (`ForwardedHeadersMiddleware`) |
| Unbounded OAuth state | Caps on clients (500), pending sign-ins (1024), codes (1024), sessions per login (50); store pruning | `oauth/provider.py`, `oauth/store.py` (flush by floods: SEC-09) |
Elevation of privilege
@@ -173,9 +173,10 @@ confirmation, `READ_ONLY`, `TOOLSETS`, `DISABLED_TOOLS` and narrow token scopes
- DNS-rebinding protection on the MCP endpoint: `Host` must be a loopback name, the bind
address, the `PUBLIC_BASE_URL` host or an `ALLOWED_HOSTS` entry (421 otherwise); a foreign
`Origin` gets 403; POST must be `application/json`.
- Rate limits: sliding window per client IP and per Authorization hash on the MCP path and the
unauthenticated OAuth paths, before authentication. Client IPs come from `X-Forwarded-For`
only for `FORWARDED_ALLOW_IPS`.
- Rate limits: sliding window per client IP (IPv6 per /64) and per Authorization hash on the
MCP path and the unauthenticated OAuth paths (`/register`, `/authorize`, `/token`, `/revoke`,
consent, callback), before authentication. Client IPs come from `X-Forwarded-For` only for
`FORWARDED_ALLOW_IPS`; a forwarded header from any other peer is ignored and logged once.
- `PUBLIC_BASE_URL` must be https unless loopback. Gitea redirects are never followed.
- stdio: stdout carries JSON-RPC only; all logging goes to stderr.