← Toutes les actualités
data-exposure4 min de lecture

Your Stack Trace Is a Gift to Attackers

Par Seaworthy · 29 octobre 2026

Close-up of running water from a faucet with splashing droplets

Photo by Ian Talmacs on Unsplash

I keep seeing the same thing in code reviews: a beautifully generated Express route, complete with a try/catch block that returns err.stack straight to the client. The developer didn't write it. An AI assistant did. And the assistant didn't mention that shipping a stack trace to every browser is a data-exposure bug.

This is not a rare edge case. Verbose error handling is one of the most common patterns I find in AI-generated backends. It looks helpful. It speeds up debugging. It also hands an attacker a map of your application's internals.

What actually leaks

A stack trace from a failed database query can reveal:

  • The exact framework and version (/node_modules/express/lib/router/index.js:174:19)
  • Internal file paths and directory structure
  • Database table and column names
  • Sometimes connection strings or query fragments
  • Authentication logic flow

None of that belongs in a client response. But when you ask an AI assistant to "handle errors properly" or "add error handling," you often get something like this:

app.get('/api/users/:id', async (req, res) => {
  try {
    const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
    res.json(user);
  } catch (err) {
    // AI-generated: "return detailed error for debugging"
    res.status(500).json({
      error: err.message,
      stack: err.stack,
      query: err.sql
    });
  }
});

That response is a small gift to anyone probing your API. The err.sql field alone can confirm your table schema. The stack confirms your framework and your file layout. An attacker can repeat this across endpoints to map your entire backend.

Why AI assistants keep doing this

Language models are trained on a lot of tutorial code, and tutorial code is optimized for learning, not for production. "Return the full error so you can see what went wrong" is a reasonable teaching pattern. It is a terrible production pattern.

Assistants also tend to optimize for developer convenience. A verbose error makes the next debugging session easier, so the model sees it as a good answer. Security review is not part of the default loop unless you ask for it.

This is the core problem: developers who lean on AI assistants are skipping the ops and security basics that used to be learned the hard way. Error handling is exactly the kind of unglamorous basic that gets skipped when the code "works."

The fix is boring, which is why it works

Separate the internal error from the client response. Log everything internally. Return almost nothing externally. A generic message plus a request ID is enough for support, and it gives you a way to correlate a user complaint with a server log line.

app.get('/api/users/:id', async (req, res) => {
  const requestId = crypto.randomUUID();
  try {
    const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
    res.json(user);
  } catch (err) {
    // Full detail stays server-side, tied to the request ID
    logger.error({ requestId, message: err.message, stack: err.stack, sql: err.sql });
    // Client gets a generic message and a reference number
    res.status(500).json({
      error: 'Internal server error',
      requestId
    });
  }
});

Two rules I enforce now. First, no stack traces, SQL, or file paths in any HTTP response, including 4xx responses. Validation errors should name the bad field, not the ORM internals. Second, every error response carries a request ID that maps to a structured log line.

Check your assistant's output

If you use an AI coding assistant, add error handling to the list of things you manually review. Grep your codebase for err.stack, error.stack, err.message inside res.json or res.send, and any place you return a raw exception object. You will find more than you expect.

You can also prompt the assistant to follow your rule. Something like "return a generic client message with a request ID, log the full error server-side" works far better than "add error handling." Be specific about what must not leave the server.

My take

Verbose error responses are a self-inflicted data exposure bug, and AI assistants are making them more common by default. That is not a reason to stop using assistants. It is a reason to treat their output as a first draft from a fast junior developer who has never run a production incident. Review the error paths. They are where the leaks live.

Seaworthy builds tooling for developers who want to catch these patterns before they ship, with security checks designed for AI-assisted codebases.

Cet article a été généré par IA et résume des sources publiquement disponibles.

Par les créateurs de Seaworthy

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.

$ npx seaworthycode