Your AI Assistant Forgot the Boring Part: Input Validation and Request Size Limits
By Seaworthy · October 25, 2026
Photo by Domaintechnik Ledl.net on Unsplash
I keep seeing the same pull request from developers who lean on AI coding assistants. The handler is clean, the types line up, the tests pass, and then someone asks what happens when a client sends a 40 MB JSON body with a missing field. The answer is usually a shrug. That shrug is the problem.
AI assistants are good at producing the shape of a working endpoint. They are less reliable at producing the guardrails around it. Ask for a signup route and you get parsing, a database call, and a response. You rarely get a body size cap, a schema check, or a decision about what to do when a field is null. Those omissions do not show up in a demo, but they show up in production the first time a scanner, a buggy client, or an unhappy user finds the edge.
Missing input validation and missing request size limits are not exotic vulnerabilities. They are ordinary hygiene, and they keep getting skipped because the code looks finished without them. A parser that accepts anything will happily build objects from attacker-controlled keys. A server that reads an entire request into memory before checking anything will do that for every request, including the ones you did not expect.
Here is the pattern I see most often in generated code:
@app.post("/profile")
async def update_profile(request: Request):
data = await request.json() # no size check, no schema
user = get_user(data["user_id"])
user.name = data.get("name")
user.save()
return {"ok": True}
Nothing here is wrong in the narrow sense. It does what the prompt asked. But data["user_id"] raises if the key is absent, data.get("name") will accept a list or a nested object, and await request.json() will read whatever arrives. A client can send a huge payload and make your process spend real time and memory before you ever look at a field. If the framework has no body limit configured, that is your problem now.
The fix is not clever. Validate at the boundary and cap the request before parsing. Most frameworks let you set a maximum body size globally. Then use a schema so unknown fields are rejected and types are enforced. Here is one version:
from pydantic import BaseModel, constr, conint
class ProfileUpdate(BaseModel):
user_id: conint(gt=0)
name: constr(min_length=1, max_length=80)
MAX_BODY = 64 * 1024 # 64 KB is plenty for this endpoint
@app.post("/profile")
async def update_profile(request: Request):
declared = request.headers.get("content-length")
if declared is None or int(declared) > MAX_BODY:
return JSONResponse({"error": "payload too large"}, status_code=413)
raw = await request.body()
if len(raw) > MAX_BODY:
return JSONResponse({"error": "payload too large"}, status_code=413)
try:
payload = ProfileUpdate.model_validate_json(raw)
except ValidationError as exc:
return JSONResponse({"error": "invalid input"}, status_code=422)
update_user(payload.user_id, payload.name)
return {"ok": True}
Two details matter here. First, check the declared length, but never trust it alone. Read the body with a hard cap, because a client can lie about content-length or send chunked data. Second, reject unknown fields and bad types with a 422 rather than letting them cascade into the database layer. A validation error is a normal response, not an exception to swallow.
My reaction to the usual excuse ("the frontend already validates") is that the frontend is not your security boundary. Clients are not yours. The API is reachable by anything that can send bytes. Client-side checks are a courtesy to users, not a control.
A few habits make this stick. Set a default body limit at the proxy or app server level and treat per-route overrides as exceptions that need a reason. Set read timeouts so slow uploads cannot hold connections open. Log validation failures, but do not log full payloads, since those can contain secrets. Keep schemas next to handlers so a new field cannot appear without a review. If you use an AI assistant, add "validate input, cap request size, reject unknown fields" to the prompt and check the diff for it. The assistant will usually comply once asked.
These controls cost a few lines. Skipping them costs you an incident report, a memory spike, or a data integrity bug that takes a day to trace. They are the least glamorous part of the endpoint, and that is exactly why they deserve a spot in your review checklist.
Seaworthy reviews application code and infrastructure for missing input validation, request size limits, and related resilience gaps.
This article was generated by AI and summarises publicly available sources.
Seaworthy scans your repo for the issues covered in articles like this one.
Security gaps, exposed secrets, and misconfigurations — caught before you deploy. Free to run, no account needed.