Weakness reference
CWE-650

Trusting HTTP Permission Methods on the Server Side

This weakness occurs when a web application relies solely on HTTP method restrictions GET, POST, PUT, DELETE, etc. to enforce security controls, without…

01Summary

This weakness occurs when a web application relies solely on HTTP method restrictions (GET, POST, PUT, DELETE, etc.) to enforce security controls, without implementing proper server-side authorization checks. An attacker can bypass these controls by using a different HTTP method to access the same resource, potentially gaining unauthorized access to sensitive functionality.

02How It Happens

Web developers sometimes assume that restricting a sensitive action to POST requests (or another specific method) provides security. However, HTTP method restrictions are a *routing convenience*, not a security boundary. An attacker can craft requests using alternative methods (GET, HEAD, OPTIONS, PATCH, etc.) to the same endpoint. If the server does not independently verify that the user has permission to perform the action—regardless of which HTTP method is used—the restriction is trivial to bypass. This is especially common in frameworks where method-based routing is the primary control mechanism, with no additional authorization logic inside the handler.

03Real-World Impact

An attacker exploiting this weakness can perform unauthorized actions such as deleting records, modifying user accounts, changing permissions, or triggering administrative functions. For example, a password reset endpoint protected only by a POST restriction could be accessed via GET, allowing an unauthenticated user to reset another user's password. The impact ranges from account takeover to data destruction, depending on what functionality is protected by the insufficient method check.

04Vulnerable & Fixed Patterns

Vulnerable pattern
from flask import Flask, request

app = Flask(__name__)

@app.route('/admin/delete_user/<user_id>', methods=['POST'])
def delete_user(user_id):
    # No authorization check — assumes POST method is sufficient protection
    db.execute("DELETE FROM users WHERE id = ?", (user_id,))
    return "User deleted"

Why it's vulnerable:
The endpoint only accepts POST requests, but an attacker can send a GET, PUT, or DELETE request to the same URL and bypass the method restriction entirely. There is no server-side check of the user's role or permissions.

Fixed pattern
from flask import Flask, request, abort
from functools import wraps

def require_admin(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not is_user_admin(request.user):
            abort(403)
        return f(*args, **kwargs)
    return decorated

@app.route('/admin/delete_user/<user_id>', methods=['POST'])
@require_admin
def delete_user(user_id):
    db.execute("DELETE FROM users WHERE id = ?", (user_id,))
    return "User deleted"
Vulnerable pattern
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $user_id = $_POST['user_id'];
    $mysqli->query("DELETE FROM users WHERE id = $user_id");
    echo "User deleted";
}
?>

Why it's vulnerable:
The code checks only the HTTP method. An attacker can send a GET request with ?user_id=123 or use a PUT/DELETE request, and if the server does not validate the method strictly or if the framework allows method override, the deletion proceeds without authorization.

Fixed pattern
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!current_user_is_admin()) {
        http_response_code(403);
        die("Forbidden");
    }
    $user_id = intval($_POST['user_id']);
    $stmt = $mysqli->prepare("DELETE FROM users WHERE id = ?");
    $stmt->bind_param("i", $user_id);
    $stmt->execute();
    echo "User deleted";
}
?>

05Prevention Checklist

Implement role-based access control (RBAC) or attribute-based access control (ABAC)
on every sensitive endpoint, independent of HTTP method.
Verify user permissions server-side
before executing any state-changing operation, using session data or tokens, never client-supplied claims.
Use framework-level authorization middleware
(decorators, filters, or guards) to enforce access rules consistently across all routes.
Disable HTTP method overrides
(e.g., X-HTTP-Method-Override headers) unless absolutely necessary, and validate them strictly if used.
Test endpoints with multiple HTTP methods
(GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) to confirm that authorization is enforced regardless of method.
Log and monitor unexpected HTTP methods
on sensitive endpoints as a potential indicator of attack attempts.

06Signs You May Already Be Affected

Check your application logs for requests using unusual HTTP methods (PUT, DELETE, PATCH, OPTIONS) on endpoints that should only accept POST. Look for successful deletions, modifications, or administrative actions triggered by GET requests or methods other than the intended one. Review your codebase for endpoints where HTTP method checks are the only authorization mechanism, with no role or permission validation inside the handler.

07Related Recent Vulnerabilities