skip to content

Some APIs accept an X-HTTP-Method-Override header (or a _method form field) so a POST can be treated as PUT, PATCH or DELETE. When is that justified, and what risks does it introduce?

level: seniorimportance: nice to knowfreq 26%

answer

  1. POST + X-HTTP-Method-Override / _method=DELETE
  2. Exists for HTML forms and method-stripping proxies
  3. Edge WAF/gateway sees POST → policy bypass
  4. Normalize before authz, never honour on GET
  5. Allowlist methods; log wire + effective

basics

~20 s

It exists for clients or intermediaries that cannot send PUT, PATCH or DELETE — old HTML forms, restrictive proxies, some corporate firewalls. The risk is that security controls keyed on the real method (WAF rules, CSRF exemptions, method-based authorization, gateway policy) see a POST while the application performs a delete.

solid answer

~60 s

The mechanism: the client sends `POST` with `X-HTTP-Method-Override: DELETE` (or `_method=DELETE` in a form body), and a filter rewrites the method before routing. **Justified** only when a real client cannot do better: HTML forms, which support GET and POST only; a legacy SDK or an intermediary that strips PATCH; some restrictive corporate networks. It is a compatibility shim, not a design choice. **Risks**, all from the gap between the wire method and the effective one: - Anything upstream that decides on the method — WAF rules, API-gateway policy, an `@PreAuthorize` keyed on HTTP method, read-only route restrictions — is evaluated against POST and can be bypassed. - CSRF defences that treat POST as "protected" are fine, but caches and logs now misreport what happened; auditing a delete requires reading a header. - If the override is honoured on GET, it is a straight vulnerability: a link becomes a delete. If you must support it: accept it only on POST, only for an explicit allowlist of methods, only from clients that need it, and normalize before any authorization runs.

go deeper

for a junior

Know that the header makes a POST behave as PUT, PATCH or DELETE, and that it exists for clients that cannot send those methods.

for a middle

Explain the HTML-form and restrictive-proxy motivations and note that logs and edge rules then see POST.

for a senior

Analyse the bypass: edge policy and method-based authorization evaluated against the wrong method, filter ordering, and the narrow allowlisted configuration you would accept.

for a principal

Decide whether the platform supports it at all, which clients justify it, how the gateway stays consistent, and set a deprecation path.

## What the mechanism is Method override lets a client that can only issue certain HTTP methods reach handlers bound to others. Two common encodings: ``` POST /orders/42 HTTP/1.1 X-HTTP-Method-Override: DELETE ``` or, from an HTML form: ``` POST /orders/42 Content-Type: application/x-www-form-urlencoded _method=DELETE ``` A filter early in the server pipeline reads the override and rewrites the request method, so routing and the application see `DELETE`. ## Why it exists **HTML forms.** The form element supports only GET and POST. Server-rendered applications that want RESTful routes for update and delete have used `_method` for decades; several frameworks ship it built in. **Hostile intermediaries.** Some corporate proxies, older load balancers and a few WAF configurations block or strip PUT, PATCH and DELETE — historically because those methods were associated with WebDAV. A client behind one cannot reach your endpoints at all. **Constrained clients.** Old SDKs, embedded HTTP stacks, or a partner's integration platform that only exposes GET and POST. Outside those, it is not justified. A modern browser `fetch`, a mobile app, or any server-side HTTP client can send any method, and using override there just obscures what the code does. ## The security problem Everything between the client and your handler makes decisions using the method on the request line. Once the effective method differs, those decisions are made about the wrong operation. **Gateway and WAF policy.** A rule like "DELETE is only allowed for the admin path" or "this route is read-only" inspects the request line, sees POST, and lets it through. The application then deletes. This is the classic method-override bypass, and it is real: teams put method restrictions at the edge precisely because they trust the edge, and override silently invalidates that. **Method-based authorization in the app.** Frameworks let you express rules per method. If the authorization filter runs *before* the override filter, the rule is evaluated against POST while the handler performs a DELETE. Ordering is the whole ballgame: normalization must happen before any security decision, and that ordering must be tested, not assumed. **Override on GET.** Some implementations honour the header on any method. If `GET /orders/42` with an override header performs a delete, you have re-created the state-changing-GET vulnerability with an extra step — and CSRF protection typically exempts GET entirely. Never honour the override on a safe method. **Observability and audit.** Access logs, metrics and traces record POST. Working out that a resource was deleted requires correlating a header nobody logs by default. In an incident, that costs time. **Caching.** POST responses are not cached, so this is mostly benign, but intermediaries reasoning about safety and idempotency now have wrong information — a proxy will not retry what it thinks is a POST even though the operation is an idempotent PUT, and conversely will not treat it as unsafe when it should. ## If you must support it 1. **Only on POST.** Reject or ignore the header on GET, HEAD and OPTIONS. 2. **Allowlist the target methods** — PUT, PATCH, DELETE. Do not allow arbitrary strings, and certainly not GET (which would let an attacker turn a protected write route into a read of something else). 3. **Normalize first.** Run the override filter before authentication, authorization, CSRF and rate limiting, so every downstream decision sees the effective method. 4. **Scope it.** Enable only on the routes or client groups that genuinely need it, ideally gated by an API key or a specific path prefix, rather than globally. 5. **Log both** the wire method and the effective method, and make sure metrics and audit records use the effective one. 6. **Keep the edge in sync.** If your gateway enforces method policy, it must apply the same normalization, or its rules are decorative. 7. **Retire it.** Track which clients still need it and remove support when they are gone — it is a compatibility shim with an expiry date. ## Alternatives Before adding it, check whether the blockage is real: often the "proxy strips PATCH" story is folklore. If only creation and updates are affected, exposing a POST-based action endpoint (`POST /orders/42/cancel`) is more honest than tunnelling DELETE, because the wire method then matches what actually happens. And CORS preflight failures — a common reason PATCH "does not work" from a browser — are fixed by configuring `Access-Control-Allow-Methods`, not by tunnelling.

  • Where in the request pipeline must the override be applied?
    Before any security decision — authentication, authorization, CSRF checks, rate limiting and routing must all see the effective method. If an authorization rule keyed on HTTP method runs first, it evaluates POST while the handler performs a DELETE, which is exactly the bypass the header enables. This ordering should be covered by a test, since filter order is easy to change accidentally.
  • A browser client says PATCH does not work. Is method override the right fix?
    Usually not. The most common cause is CORS: the preflight response does not list PATCH in Access-Control-Allow-Methods, or the custom headers are not allowed. Fixing the CORS configuration keeps the wire method honest. Reach for override only when a real intermediary outside your control strips the method, and then scope it narrowly.

saying these in an interview costs you the question

  • Enabling method override globally by default when no client needs it
  • Honouring the override header on GET requests
  • Applying the override after authorization or CSRF checks have already run
  • Assuming an edge WAF or gateway still enforces method policy once override is enabled
  • Allowing any method value in the header rather than a small allowlist

context