HTTP methods used correctly
Why it matters
Using GET to delete resources or POST for all mutations violates HTTP semantics in ways that cause real damage: browsers and CDNs will cache or prefetch GET endpoints that actually mutate state, link prefetchers can trigger deletes without user intent, and CWE-749 (exposed dangerous methods) applies when destructive operations are reachable via safe-method verbs. Semantically incorrect methods also break API consumers who rely on HTTP conventions — retry logic in HTTP clients retries GET and PUT as safe/idempotent but not POST.
Severity rationale
High because GET-based mutations can be triggered by prefetchers, cached by CDNs, or exploited via CSRF — any of which produces unintended data destruction or exposure.
Remediation
Align each route handler export in app/api/ with its actual semantic in one pass: GET reads only, POST creates, PATCH partially updates, PUT replaces, DELETE removes. In Next.js App Router this means changing the exported function name:
// Before (wrong)
export async function GET(req: Request) {
await db.user.delete({ where: { id: req.nextUrl.searchParams.get('id') } })
}
// After (correct)
export async function DELETE(req: Request) {
const { id } = await req.json()
await db.user.delete({ where: { id } })
}
Update all client-side fetch calls to use the matching method. Work through your route list systematically — most AI-generated APIs default POST for everything and need a full sweep.
Detection
- ID:
http-methods-correct - Severity:
high - What to look for: Enumerate all route handler files. For each, classify which HTTP method is exported and verify it uses the semantically correct HTTP method. Check for these anti-patterns: (1) GET requests that create, update, or delete data; (2) POST requests used for all mutations when PUT/PATCH/DELETE would be more appropriate; (3) DELETE operations implemented via POST or GET with a query parameter; (4) GET requests with a request body (not supported in all HTTP clients). Look for handler function names like
export async function GET,export async function POST, etc. in Next.js App Router, orreq.method === 'POST'branching in Pages Router handlers. - Pass criteria: GET handlers read data only, POST creates resources, PUT/PATCH updates resources, DELETE deletes resources. Some overlap is acceptable (e.g., POST used for complex search queries, RPC-style actions via POST).
- Fail criteria: Any of these are present: GET handlers that mutate data; POST handlers doing all mutations with no PUT/PATCH/DELETE; DELETE operations triggered via GET (e.g.,
/api/delete-user?id=123). - Skip (N/A) when: Fewer than 2 API routes exist. Signal: only 0 or 1 route handler files detected.
- Detail on fail: Identify the specific violation (e.g., "GET /api/delete-account mutates data; all updates use POST rather than PUT/PATCH"). Max 500 chars.
- Remediation: Align HTTP methods with their standard semantics in
app/api/route files. Use GET for safe, idempotent reads. Use POST for resource creation or non-idempotent actions. Use PUT to replace a resource entirely (full update), PATCH for partial updates, and DELETE for removal. Update both the route handler export names and any client-side fetch calls. Most AI-generated APIs default to POST for everything — work through your route list and reassign appropriately.
External references
- iso-25010:2011 · maintainability.modifiability — Modifiability
- cwe · CWE-749 — Exposed Dangerous Method or Function
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-api-design·automated