Proposal: Resource-exhaustion and asymmetric-DoS hardening
Edge-statelessness defeats verification-flooding (ADR-0027), so abuse concentrates on issuance — but the sharper class is cheap-request to expensive-server: hammering Argon2id (CPU), XML entity-expansion in SAML, and deeply-nested or oversized JSON and tokens. Per-tenant rate limits are named (ADR-0012), but the amplification and parser-resource class is not. This proposal specs the hardening within existing components (Modgud admission, the parsers, the edge); it changes no architecture.
Motivation
An unauthenticated caller that can trigger an Argon2id hash, a SAML XML parse, or a large JSON decode per request turns a trivial request into disproportionate server work — a classic asymmetric DoS that infra-layer rate limiting alone does not stop, because it is application-cost-aware.
Design
- Input limits. Maximum request-body, token/credential, and assertion sizes; maximum JSON nesting depth and claim count; reject oversized input before parsing.
- XML hardening (SAML, ADR-0017): external entities disabled (XXE — already in the §12.5 catalog) and entity expansion disabled (the "billion laughs" attack), bounded document size, schema validation before signature processing.
- Cost-before-auth ordering. Cheap checks (rate limit, size, format) run before expensive ones (Argon2id, signature verification, XML parse), so an unauthenticated caller cannot trigger the expensive path at will. Under load, an optional proof-of-work or CAPTCHA gate on the unauthenticated login/registration path, by per-realm policy (ADR-0012).
- Layered rate limits. Per-IP, per-tenant, and per-principal token-bucket limits at Modgud (ADR-0009); connection/stream limits on the admin and SCIM surfaces.
Alternatives considered
- Infra-layer rate limiting only — rejected; cost-amplification needs application-aware limits.
- Reducing Argon2id cost — rejected; that weakens password hashing. Rate-limit the path instead, do not weaken the primitive.
Graduation criteria
Oversized/over-nested inputs are rejected before parsing; XML entity expansion is disabled (abuse-case test: a billion-laughs document is rejected); an unauthenticated load test cannot saturate Argon2id; limits apply per-IP, per-tenant, and per-principal.
Backward compatibility
Hardening configuration within existing components; no architecture change. Limit values are tunable budgets (shape now, numbers set during implementation).
Open questions
- Anti-automation choice for CIAM (proof-of-work vs CAPTCHA vs device signals).
- Default limit values — deferred to measurement.