Security

AI Didn't Invent New API Attacks. It Made the Old Ones Cheap.

What an AI-driven probe looks like in your logs, and the five checks that stop most of it.

Enumeration, credential stuffing, scraping and injection are not new. Most of them are older than the frameworks you’re running them against.

What changed is who runs them. An AI agent will try every ID, every parameter and every forgotten route at 2 a.m., without getting bored, for the cost of a few API credits. The basics you meant to get to later are now the whole attack surface.

The numbers back that up:

  • 53% of all web traffic in 2025 was automated. Humans are now the minority.
  • 27% of bot attacks in 2025 went straight at API endpoints, not web pages.
  • AI-driven bot attacks grew 12.5× from 2024 to 2025.
  • In a large study of 100 models, 45% of coding tasks introduced a security flaw. Your copilot writes fast; it doesn’t write safe by default.

The danger isn’t magic. It’s volume and speed aimed at the gaps every small team has: missing ownership checks, no rate limits, no logs.

Ten minutes, one agent

Here’s what an AI-driven probe looks like in your request logs. It’s an illustrative composite of common patterns, not real customer traffic.

Time Request Status What happened
02:14:07 GET /.env /.git/config /actuator 404 Recon from one IP
02:14:08 GET /api/v1/openapi.json 200 Full route map, handed over
02:14:09 POST /api/v1/signup 201 A fresh account
02:14:11 GET /api/v1/invoices/10418 … 11203 200 785 invoices that weren’t theirs
02:16:30 POST /api/v1/login 401 1,240 attempts across 312 IPs
02:19:44 PATCH /api/v1/users/me {"role":"admin"} 200 Mass assignment
02:21:02 POST /api/v1/chat "ignore previous…" 200 Prompt injection
02:23:15 POST /api/v1/coupons/redeem 200 64 redemptions, one account
02:24:50 GET /api/v1/export?limit=100000 500 Stack trace leaked

Every line is a decade-old technique. An agent just runs them all in a row.

And that’s the version where you have request logs. Without them, this is what you’re at risk for, and you’d have no record it happened.

Five checks that stop most of it

The full checklist has 40 items. These five close the worst gaps in the log above.

1. Scope every object lookup to the caller

Broken object-level authorization is #1 on the OWASP API Security Top 10 because it’s one missing WHERE clause, and agents are built to find it. The agent signs up, fetches its own invoice, sees /invoices/10418, and asks for 10419. Then the next 784. A human gets bored at ten. The agent doesn’t.

js
app.get('/api/invoices/:id', requireAuth, async (req, res) => {
  const invoice = await db.invoice.findFirst({
    where: { id: req.params.id, accountId: req.user.accountId }, // ownership, every time
  });
  if (!invoice) return res.status(404).end();
  res.json(toPublicInvoice(invoice)); // allowlisted fields only
});

If the row isn’t theirs, it doesn’t exist. Return 404, not 403, so you don’t confirm it’s there.

2. Rate limit login on the account, not just the IP

Per-IP limits fail against rotating proxies. In the log above, 1,240 login attempts came from 312 IPs, so no single IP looked busy. Key the limit on the targeted account too.

js
import { rateLimit, ipKeyGenerator } from 'express-rate-limit';

app.post('/api/login', express.json(), rateLimit({
  windowMs: 15 * 60_000,
  limit: 10,
  standardHeaders: 'draft-8',
  legacyHeaders: false,
  keyGenerator: (req) => `${ipKeyGenerator(req.ip)}:${req.body?.email ?? ''}`,
}), login);

3. Reject fields you didn’t ask for

Mass assignment turns any profile update into a promotion. AI-generated handlers love data: req.body. A strict schema rejects unknown keys before they ever reach the database.

js
import { z } from 'zod';

const UpdateProfile = z.strictObject({ // unknown keys → 400
  name: z.string().trim().min(1).max(80),
  timezone: z.string().max(64).optional(),
});

app.patch('/api/users/me', express.json({ limit: '100kb' }), async (req, res) => {
  const parsed = UpdateProfile.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'invalid_body', requestId: req.id });
  await db.user.update({ where: { id: req.user.id }, data: parsed.data });
  res.status(204).end(); // {"role":"admin"} never got this far
});

4. Fail quietly

A verbose 500 is a free architecture diagram: your ORM, your table names, your file paths. In production, return an error code and a request ID. Log the detail; send the ID. And cap the things that make 500s easy to trigger: body size, page size and export size.

5. Treat your AI feature like the API it is

A chat box or an agent with tools is a new endpoint that takes free text and acts on it. You can’t fully prevent prompt injection. You can make sure an injected model can only do what that user already could:

  • Run every tool call with the end user’s permissions, never a service account’s.
  • Set per-user token, request and spend budgets. An open chat endpoint is a free model for anyone who finds it, billed to you.
  • Require a human click for anything irreversible: refunds, deletes, sends, payments.

The one that unlocks the rest

Alerts, enumeration detection, prompt forensics and incident scope all depend on one thing: knowing what’s hitting your API. If you only do one thing today, start logging every request, with secrets redacted before they’re stored.

Get the full 40-point checklist

The AI-Era API Security Checklist covers all 40 checks across 9 areas, each prioritized and mapped to the OWASP API Security Top 10 and the OWASP Top 10 for LLM Apps. It also includes:

  • 5 Node snippets you can paste today
  • A 30-day plan for a team of one to twenty
  • An AI audit prompt. Paste it into Claude Code, Cursor or Copilot from your repo root, and it audits your app against all 40 items and writes a full report with file-and-line evidence.

Attackers point agents at your API. Point one at your code first.

Get the free checklist →


Sources: Thales/Imperva, 2026 Bad Bot Report; Asia Pacific Defence Reporter on the same Thales report; Veracode, 2025 GenAI Code Security Report; OWASP API Security Top 10 (2023); OWASP Top 10 for LLM Applications (2025). Code samples target express-rate-limit 8 and zod 4 and are starting points, not drop-in security.