Safeguard
Application Security•

ASVS 5.0 V4.1.4: Allow Only the HTTP Methods You Use

Every route should accept an explicit list of HTTP methods and reject the rest with 405. Here is how to set it up and prove it works.

Safeguard Security Team
3 min read

ASVS 5.0 V4.1.4 (level 3) requires that only HTTP methods the application or API explicitly supports can be used, including OPTIONS for CORS preflight, and that every other method is blocked.

If a route serves GET and POST, then PUT, DELETE, PATCH, TRACE and anything exotic should return 405 Method Not Allowed, ideally with an Allow header listing the valid ones.

Why it matters

Frameworks and servers often accept more than you wrote handlers for. A catch all route may treat DELETE as GET. A proxy may let TRACE through. Method override headers like X-HTTP-Method-Override can turn a harmless POST into a destructive call. Each unused method is surface you never reviewed, tested or put behind authorization.

Authorization bugs love this gap. A team protects DELETE /orders/42 with a role check, but a PUT on the same path hits a generic update handler that was never meant to be public.

How to implement it

Declare methods per route and reject everything else. In Express with a small guard:

const allow = (...methods) => (req, res, next) => {
  if (methods.includes(req.method)) return next();
  res.set('Allow', methods.join(', '));
  res.status(405).json({ error: 'method_not_allowed' });
};

app.all('/orders', allow('GET', 'POST', 'OPTIONS'), ordersHandler);

At the proxy, add a global deny for methods no route uses:

if ($request_method !~ ^(GET|POST|PUT|DELETE|OPTIONS)$) {
    return 405;
}

Turn off TRACE in the web server, and disable method override middleware unless you truly need it. For CORS, answer OPTIONS only on routes that need preflight and return the narrow Access-Control-Allow-Methods list.

How to test it

Loop through methods against a handful of routes and record the status codes.

for m in GET POST PUT PATCH DELETE TRACE HEAD OPTIONS FOO; do
  printf "%s " $m
  curl -s -o /dev/null -w "%{http_code}\n" -X $m https://api.example.com/orders
done

Compare the result with your route table. Any method you did not implement must give 405 (or 404 where the resource is hidden). Add the same loop to a test suite so a new route cannot ship with open methods.

Common mistakes

  • Using app.all or a wildcard route and forgetting to filter methods.
  • Authorizing only the methods you expected and leaving the others on a default handler.
  • Honoring X-HTTP-Method-Override from public clients.
  • Letting HEAD run full handlers with side effects.
  • Blocking OPTIONS everywhere and then breaking legitimate CORS preflight.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

What should a route return when it gets a method it does not support?

A 405 Method Not Allowed response, with an Allow header listing the methods that are supported.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.