Update REST Assessment Cheat Sheet: OpenAPI, JWT/OAuth2, BOLA, Mass Assignment, Rate Limiting#2100
Conversation
…ss Assignment, Rate Limiting sections Closes OWASP#2023 Adds five new sections to bring the cheat sheet in line with modern API security practices: - Assessing OpenAPI/Swagger-based REST APIs: schema discovery paths, endpoint enumeration, undocumented field testing, schema-driven fuzzing - JWT and OAuth2 Assessment: alg:none, algorithm confusion, claim tampering, expiry validation, kid injection, scope enforcement, PKCE - Broken Object Level Authorization (BOLA): horizontal/vertical privilege escalation patterns, indirect reference testing - Mass Assignment: field injection via POST/PUT/PATCH, privilege escalation via numeric fields - Rate Limiting: baseline measurement, limit bypass techniques, sensitive operation coverage Updated Related Resources to include OWASP API Security Top 10, JWT Cheat Sheet, OAuth2 Cheat Sheet, and Schemathesis.
There was a problem hiding this comment.
Pull request overview
Updates the REST Assessment Cheat Sheet to reflect modern API assessment practices by adding coverage for OpenAPI-based discovery/testing, common API authn/authz mechanisms, and prevalent API-specific vulnerability classes.
Changes:
- Adds new guidance sections for OpenAPI/Swagger discovery + schema-driven testing, JWT/OAuth2 assessment, BOLA, mass assignment, and rate limiting/throttling.
- Expands “Related Resources” with OWASP API Security Top 10, JWT/OAuth2 cheat sheets, and Schemathesis.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ## Assessing OpenAPI/Swagger-based REST APIs | ||
|
|
||
| Modern REST APIs are commonly described using the [OpenAPI Specification (OAS)](https://www.openapis.org/), which replaces older formats such as WSDL and WADL. When an OpenAPI definition is available it significantly accelerates attack surface discovery. |
There was a problem hiding this comment.
The sentence implies OpenAPI "replaces" WSDL and WADL, but WSDL is primarily a SOAP service description format (and the earlier section of this cheat sheet already frames WSDL in the SOAP context). To avoid factual inconsistency/misleading guidance, consider rephrasing to position OpenAPI as the de facto standard for REST API descriptions, contrasting mainly with older REST description proposals like WADL (and optionally noting that WSDL is typically for SOAP).
| Modern REST APIs are commonly described using the [OpenAPI Specification (OAS)](https://www.openapis.org/), which replaces older formats such as WSDL and WADL. When an OpenAPI definition is available it significantly accelerates attack surface discovery. | |
| Modern REST APIs are commonly described using the [OpenAPI Specification (OAS)](https://www.openapis.org/), the de facto standard for REST API descriptions. It supersedes older REST description proposals such as WADL; WSDL is typically used for SOAP services. When an OpenAPI definition is available it significantly accelerates attack surface discovery. |
| **Establish a baseline.** Send a sequence of identical requests and note response time, headers, and status codes. Look for standard rate-limiting headers: | ||
|
|
||
| - `X-RateLimit-Limit` — the request ceiling | ||
| - `X-RateLimit-Remaining` — requests remaining in the current window | ||
| - `X-RateLimit-Reset` — Unix timestamp when the window resets |
There was a problem hiding this comment.
These are common/de facto rate-limit headers, but calling them "standard" is inaccurate: X-RateLimit-* is non-standard, and there is also the standardized RateLimit-* header set (RFC 9239) used by some APIs. Suggest changing wording to "common"/"often used" and optionally adding RateLimit-Limit/Remaining/Reset alongside the X- variants.
| **Establish a baseline.** Send a sequence of identical requests and note response time, headers, and status codes. Look for standard rate-limiting headers: | |
| - `X-RateLimit-Limit` — the request ceiling | |
| - `X-RateLimit-Remaining` — requests remaining in the current window | |
| - `X-RateLimit-Reset` — Unix timestamp when the window resets | |
| **Establish a baseline.** Send a sequence of identical requests and note response time, headers, and status codes. Look for common rate-limiting headers such as: | |
| - `X-RateLimit-Limit` — common non-standard header for the request ceiling | |
| - `X-RateLimit-Remaining` — common non-standard header for requests remaining in the current window | |
| - `X-RateLimit-Reset` — common non-standard header for when the window resets | |
| - `RateLimit-Limit` — standardized header for the request ceiling | |
| - `RateLimit-Remaining` — standardized header for requests remaining in the current window | |
| - `RateLimit-Reset` — standardized header for when the window resets |
|
|
||
| **Tamper with claims.** Decode the payload (it is Base64Url-encoded, not encrypted), modify claims such as `sub`, `role`, or `email`, re-sign or strip the signature, and replay the token. | ||
|
|
||
| **Check expiry enforcement.** Send a token whose `exp` claim is in the past. The server should return `401`; if it returns `200`, expiry is not being validated. |
There was a problem hiding this comment.
Not all APIs respond with 401 specifically for an expired/invalid JWT (some use 403 or 400 depending on authn/authz handling). To keep the guidance accurate across implementations, consider changing this to "the server should reject the request" and optionally mention common status codes (401/403).
| **Check expiry enforcement.** Send a token whose `exp` claim is in the past. The server should return `401`; if it returns `200`, expiry is not being validated. | |
| **Check expiry enforcement.** Send a token whose `exp` claim is in the past. The server should reject the request (commonly with `401` or `403`); if it returns `200`, expiry is not being validated. |
|
|
||
| ### OAuth2 Assessment | ||
|
|
||
| **Validate scope enforcement.** Obtain a token with a limited scope (e.g. `read:profile`) and attempt operations that require broader scope (e.g. `write:admin`). The server should reject out-of-scope requests with `403`. |
There was a problem hiding this comment.
Similar to JWT expiry handling, out-of-scope OAuth2 requests are often rejected with 403, but some APIs use 401 or insufficient_scope error responses. Consider wording this as "should be rejected" and optionally mention 403 as a common outcome rather than a strict requirement.
| **Validate scope enforcement.** Obtain a token with a limited scope (e.g. `read:profile`) and attempt operations that require broader scope (e.g. `write:admin`). The server should reject out-of-scope requests with `403`. | |
| **Validate scope enforcement.** Obtain a token with a limited scope (e.g. `read:profile`) and attempt operations that require broader scope (e.g. `write:admin`). The server should reject out-of-scope requests, commonly with `403` or an `insufficient_scope` error response. |
mackowski
left a comment
There was a problem hiding this comment.
Please fix two comment and linter errors
|
|
||
| ### JWT Assessment | ||
|
|
||
| **Verify signature validation.** Swap the algorithm header to `alg: none` and remove the signature. A vulnerable server will accept the token without validating it. |
There was a problem hiding this comment.
The actual attack retains the trailing . — the token structure must remain header.payload. (with an empty signature segment), not
header.payload. Some JWT libraries reject a token that is missing the final period entirely. The description should read:
▎ Strip the signature body but keep the trailing period: header.payload.
| - In headers. | ||
| - Structured parameters and responses using JSON or XML in a parameter values, request body or response body. Those are required to communicate machine useful information. | ||
| - Custom authentication and session management, often utilizing custom security tokens: this is needed as machine to machine communication does not allow for login sequences. | ||
| - Lack of formal documentation. A [proposed standard for describing RESTful web services called WADL](http://www.w3.org/Submission/wadl/) was submitted by Sun Microsystems but was never officially adapted. |
There was a problem hiding this comment.
The new OpenAPI section says OpenAPI "replaces older formats such as WSDL and WADL," but the original text is left untouched. Readers
will encounter the old claim and the new framing in the same document without reconciliation. The existing paragraph should be updated
to acknowledge OpenAPI as the current standard.
What this PR addresses
Closes #2023
The REST Assessment Cheat Sheet is a solid foundation but references WSDL/WADL as service description formats without addressing OpenAPI — the standard that now describes virtually every modern REST API. It also has no coverage of the authentication mechanisms, authorization flaws, or abuse vectors most commonly found in APIs today.
Changes
Five new sections added between the existing fuzzing guidance and the Related Resources footer:
1. Assessing OpenAPI/Swagger-based REST APIs
/openapi.json,/swagger.json,/docs, etc.)2. JWT and OAuth2 Assessment
alg: noneand algorithm confusion attackskidheader injection (SQL injection, path traversal, SSRF)3. Broken Object Level Authorization (BOLA)
4. Mass Assignment in JSON APIs
5. Rate Limiting and Throttling Assessment
429enforcementUpdated Related Resources section to include the OWASP API Security Top 10, JWT Cheat Sheet, OAuth2 Cheat Sheet, and Schemathesis.
Checklist
[TEXT](URL)AI Tool Usage Disclosure