parlov docs

PATCH

Status code differentials observed via PATCH requests.

Implemented

Status code differentials observed via PATCH requests. All strategies in this section are MethodDestructive risk tier — non-idempotent methods that may have side effects but avoid permanent data loss.


Elicitation Strategies


200 / 204 vs 404

Vector

Server returns 200 OK or 204 No Content for a successful PATCH request against an existing resource, but 404 for a nonexistent resource (assuming the patch document cannot logically create one). The success vs. 404 differential creates a binary existence signal.

Example

PATCH /api/users/123 HTTP/1.1
Host: target.com
Content-Type: application/merge-patch+json
{"role":"viewer"}

HTTP/1.1 200 OK
Content-Length: 72
{"id":123,"role":"viewer"}

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
Content-Type: application/merge-patch+json
{"role":"viewer"}

HTTP/1.1 404 Not Found
Content-Length: 27
{"error":"user not found"}

Leaking Response / Methodology

  • What leaks: 200/204 vs 404 confirms user 123 exists. A 200 response may also leak the newly modified representation of the resource.

409 vs 200 / 201 / 204

Vector

Server evaluates the current state of an existing resource against a valid PATCH document and returns 409 Conflict due to an optimistic locking failure (e.g., conflicting If-Match or schema mismatch). A nonexistent resource handles the PATCH in one of two ways:

  • 404 Not Found: If the server does not allow resource creation via PATCH.
  • 201 Created: If the server does allow creation via PATCH.

If the server creates resources via PATCH, the 409 vs 201 differential confirms that the resource already exists. If it doesn't create resources, the 409 vs 404 differential confirms existence. Even if the PATCH is successful, the 200/204 vs 404 differential creates an oracle.

Example

PATCH /api/users/123 HTTP/1.1
Host: target.com
Content-Type: application/json-patch+json
[{"op":"replace","path":"/department","value":"sales"}]

HTTP/1.1 409 Conflict
Content-Length: 68
{"error":"conflict","detail":"department field does not exist on user"}

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
Content-Type: application/json-patch+json
[{"op":"replace","path":"/department","value":"sales"}]

HTTP/1.1 201 Created
Content-Length: 52
{"id":999,"department":"sales"}

Leaking Response / Methodology

  • What leaks: 409 vs 201 confirms user 123 exists. The 409 body leaks details about the resource's current schema or state constraints.

Shared PATCH / PUT Oracles

The following oracles apply equally to both PATCH and PUT requests. They are documented here and cross-referenced from the PUT page.

422 vs 404

Vector

Server validates the request body against the existing resource's schema and returns 422 Unprocessable Entity for validation errors, but 404 for nonexistent resources. The validation error implies the resource was found — the server only validates input against a resource that exists. This is a two-for-one oracle: existence confirmation plus schema enumeration.

Example

PATCH /api/users/123 HTTP/1.1
Host: target.com
Content-Type: application/json
{"role":"invalid_role"}

HTTP/1.1 422 Unprocessable Entity
Content-Length: 72
{"error":"validation_error","detail":"role must be one of: admin, user, viewer"}

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
Content-Type: application/json
{"role":"invalid_role"}

HTTP/1.1 404 Not Found
Content-Length: 27
{"error":"user not found"}

Leaking Response / Methodology

  • What leaks: 422 vs 404 confirms user 123 exists. The 422 body leaks the resource's schema — valid enum values, field constraints, type requirements. The server reveals what it would accept, disclosing the resource's data model. Each different invalid payload reveals a different constraint.

415 vs 404

Vector

Payload negotiation failure. Sending a request with an obscure Content-Type causes an existing endpoint/resource to fail parsing and return 415 Unsupported Media Type. Nonexistent resources return 404 before payload parsing occurs.

Example

PATCH /api/users/123 HTTP/1.1
Host: target.com
Content-Type: application/x-made-up
{"name":"test"}

HTTP/1.1 415 Unsupported Media Type
Content-Length: 45
{"error":"unsupported request content type"}

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
Content-Type: application/x-made-up
{"name":"test"}

HTTP/1.1 404 Not Found
Content-Length: 27
{"error":"user not found"}

Leaking Response / Methodology

  • What leaks: 415 vs 404 confirms user 123 exists. The 415 indicates the server resolved the resource and attempted to process the request body.

412 vs 404

Vector

State-conditional requests using If-Match: "invalid-etag" or If-Unmodified-Since. The server checks the precondition against the actual state of an existing resource, failing with 412 Precondition Failed. If the resource is missing, it returns 404.

Example

PATCH /api/users/123 HTTP/1.1
Host: target.com
If-Match: "invalid-etag"
Content-Type: application/json
{"name":"test"}

HTTP/1.1 412 Precondition Failed
Content-Length: 40
{"error":"etag mismatch, update rejected"}

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
If-Match: "invalid-etag"
Content-Type: application/json
{"name":"test"}

HTTP/1.1 404 Not Found
Content-Length: 27
{"error":"user not found"}

Leaking Response / Methodology

  • What leaks: 412 vs 404 confirms user 123 exists. The 412 indicates the server evaluated the resource's current state against the precondition.

413 vs 404

Vector

Per RFC 9110 §15.5.14, a server returns 413 Content Too Large when the request body exceeds a size limit. If the limit is enforced after resolving the target resource, existing resources trigger 413 while nonexistent ones return 404.

Example

PATCH /api/users/123 HTTP/1.1
Host: target.com
Content-Type: application/json
Content-Length: 1048576
{"bio":"AAAA..."}

HTTP/1.1 413 Content Too Large

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
Content-Type: application/json
Content-Length: 1048576
{"bio":"AAAA..."}

HTTP/1.1 404 Not Found
{"error":"user not found"}
```http

#### Leaking Response / Methodology

- **What leaks:** 413 vs 404 confirms user 123 exists. The server resolved the resource before checking body size.

### 411 vs 404

#### Vector

Per RFC 9110 §15.5.12, a server returns 411 Length Required when the request lacks a `Content-Length` header and the server refuses to accept it without one. If this check occurs *after* resolving the resource, existing resources trigger 411 while nonexistent ones return 404.

#### Example

```jsx
PATCH /api/users/123 HTTP/1.1
Host: target.com
Content-Type: application/json
Transfer-Encoding: chunked

7
{"a":1}
0

HTTP/1.1 411 Length Required

---

PATCH /api/users/999 HTTP/1.1
Host: target.com
Content-Type: application/json
Transfer-Encoding: chunked

7
{"a":1}
0

HTTP/1.1 404 Not Found
{"error":"user not found"}

Leaking Response / Methodology

  • What leaks: 411 vs 404 confirms user 123 exists. Low-noise probe — omitting a single header is unlikely to trigger WAF rules.

On this page