Your AI Assistant Wrote a Fast API. It Also Wrote a DoS Bug.
作者:Seaworthy · 2026年10月18日
Photo by Nathan Dumlao on Unsplash
The endpoint looked fine. It was not.
A developer I know asked an AI assistant to scaffold a file-upload endpoint. The assistant produced clean, readable code in seconds. It also produced a service that would happily accept a 4 GB request body, hold it in memory, and fall over under three concurrent uploads. Nobody noticed until a staging environment with a smaller container started returning 502s during a demo.
This is not an AI failure story. It is a review failure story. Assistants are excellent at producing the happy path. They are less reliable at adding the boring guardrails that keep a service alive when someone (or something) sends garbage. Input validation and request size limits are the two guardrails most often missing from generated code. They are also the two that matter most when you care about resilience.
Why this keeps happening
Generated code tends to mirror the shape of a tutorial. Tutorials assume well-behaved clients. They show you how to parse a JSON body, not how to reject a body that is 200 MB of null bytes. They show you how to validate a required field, not how to cap the number of items in an array or the length of a string.
There is also a psychological trap. When an assistant hands you a working endpoint, the endpoint works. You run a request, you get a 200, and your brain marks the task done. The missing limits are invisible until traffic is not friendly. That is the worst time to discover them.
I have started treating generated endpoints the same way I treat generated SQL: assume the guardrails are missing until I see them.
The missing limits, in concrete terms
A request size limit caps how many bytes your service will read from a client before it gives up. Without one, a single client can consume memory, disk, or connection time far beyond what you budgeted. Input validation is the related discipline of checking that a payload matches expectations before you act on it: types, ranges, lengths, and counts.
The two belong together. A size limit alone lets a 1 MB body with a million-element array through. Validation alone lets a 500 MB body reach your parser. You want both.
Here is the kind of pattern I look for now, using a small Express example. The fix is unglamorous, which is exactly why it is easy to skip.
const express = require('express');
const app = express();
// Cap the raw body before any parser touches it.
app.use(express.json({ limit: '100kb' }));
// Validate shape, length, and count after parsing.
function validateCreateUser(req, res, next) {
const { name, tags } = req.body || {};
if (typeof name !== 'string' || name.length === 0 || name.length > 80) {
return res.status(400).json({ error: 'invalid name' });
}
if (tags !== undefined) {
if (!Array.isArray(tags) || tags.length > 20) {
return res.status(400).json({ error: 'invalid tags' });
}
if (tags.some((t) => typeof t !== 'string' || t.length > 40)) {
return res.status(400).json({ error: 'invalid tag' });
}
}
next();
}
app.post('/users', validateCreateUser, (req, res) => {
res.status(201).json({ ok: true });
});
Two things stand out. The limit option is set before parsing, so oversized bodies are rejected early. The validator checks counts and string lengths, not just presence. A generated endpoint often has neither line.
The same idea applies outside Node. Most frameworks expose a maximum body size setting. Use it. Set a global default and raise it only for endpoints that genuinely need more, and only after you have thought about the cost.
Make the assistant do the boring part
A practical habit: when you prompt for an endpoint, ask for the limits in the same request. Say, "include request body size limits and validate field types, lengths, and array counts." You will get better output, and you will have a checklist to compare against.
Then review for the things assistants still miss. Does the limit apply to every route or only some? Are errors returned without echoing the input back? Is there any timeout on slow clients? Size limits and validation are the first line, not the whole wall.
A resilience habit, not a one-time fix
Resilience is mostly the accumulation of small refusals. A service that says no to oversized bodies, malformed fields, and absurd array counts is a service that stays up when a client misbehaves or a retry loop goes wrong. Generated code gives you speed. The guardrails are your job, and they take minutes to add.
If you want a second set of eyes on these patterns, Seaworthy reviews developer-facing APIs for exactly this class of omission.
本文由 AI 生成,总结了公开可用的来源。
Seaworthy 会扫描你的代码仓库,发现类似本文提到的各种问题。
安全漏洞、泄露的密钥和配置错误——在部署前捕获。免费运行,无需账户。