Your API Doesn't Need a Bouncer. It Needs a Limit.
Par Seaworthy · 5 octobre 2026
Photo by Markus Spiske on Unsplash
I have reviewed a lot of code produced with AI assistants. The pattern is consistent. Ask for a login endpoint, and you get a working login endpoint. Ask for a file upload route, and you get a working file upload route. What you often do not get is a check on how large that file can be, or whether the JSON body contains the fields you expect.
The assistant did its job. It wrote code that solves the happy path. The problem is that attackers and bored teenagers do not use the happy path. They send you a 2 GB JSON blob. They send an array with a million entries. They send a string where your code expects an integer. If your app tries to parse it, allocate memory for it, or loop over it, you now have an outage. Not a breach necessarily, but an outage. That is a resilience problem, and it lands on the same pile as every other security gap.
Here is a small Node.js and Express example. This is the kind of code I see in tutorials and in AI suggestions. It looks fine. It is not.
app.post('/api/comment', async (req, res) => {
const { postId, text } = req.body;
const comment = await db.comments.create({
postId: postId,
text: text
});
res.json(comment);
});
There is no limit on the request body size. If your body parser has no limit, or a very high default, a single client can send a massive payload and make your server chew on it. There is also no check that postId is a number, or that text is a string under some length. Maybe the database accepts it. Maybe it throws a weird error that leaks a stack trace. Either way, you are one request away from a bad time.
I react badly to this because the fix is cheap. It is not exciting work. Nobody writes blog posts about setting a limit. But the absence of that limit is a direct path to downtime. And downtime is how you find out that your resilience plan was a hope, not a design.
The fix is not one thing. It is three. First, cap the request body size at the web server or framework level. Second, validate the shape and type of incoming data. Third, reject anything that fails validation with a clear, boring error before it touches your business logic.
Here is the same endpoint with those three steps added.
const express = require('express');
const app = express();
// 1. Cap body size (50kb is plenty for a comment)
app.use(express.json({ limit: '50kb' }));
// 2. Validate shape and type
function validateComment(req, res, next) {
const { postId, text } = req.body || {};
if (typeof postId !== 'number' || !Number.isInteger(postId)) {
return res.status(400).json({ error: 'postId must be an integer' });
}
if (typeof text !== 'string' || text.length === 0 || text.length > 2000) {
return res.status(400).json({ error: 'text must be 1-2000 characters' });
}
next();
}
app.post('/api/comment', validateComment, async (req, res) => {
const { postId, text } = req.body;
const comment = await db.comments.create({ postId, text });
res.json(comment);
});
That is it. A limit, a check, and a rejection. The code is not clever. It is not shorter. It is safer. The assistant would have written this if you asked for it. Most people do not ask.
I think the root cause is that AI assistants optimize for the prompt, not for production. If your prompt says "write an endpoint that saves a comment," you get an endpoint that saves a comment. If your prompt says "write an endpoint that saves a comment and survives abuse," you get something closer to the second example. The tool is not the problem. The request is.
There is also a cultural issue. Input validation and request size limits feel like ops work. They feel like something the infrastructure team handles. But unless you are behind a WAF with strict rules, and most small teams are not, this is application work. It belongs in your code. It belongs in the first version, not the version after the incident.
The cost of skipping it is not abstract. A single unbounded endpoint can exhaust memory, fill a queue, or cause a database to lock up. The recovery work is expensive. The fix is a few lines. I would rather write the few lines.
So here is my ask. Next time you accept an AI-generated route, read it once for the happy path and once for the unhappy path. Ask what happens if the body is huge. Ask what happens if a field is missing or the wrong type. If the answer is "I don't know," add the limit and the check. Your future self, paged at 2 AM, will be grateful.
Seaworthy builds tools for developers who want to find and fix these gaps in code generated with AI assistance.
Cet article a été généré par IA et résume des sources publiquement disponibles.
Seaworthy analyse votre dépôt pour détecter les problèmes abordés dans des articles comme celui-ci.
Failles de sécurité, secrets exposés et mauvaises configurations détectés avant le déploiement. Gratuit, aucun compte requis.