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

Your Error Messages Are Oversharing: A Wake-Up Call for AI-Assisted Developers

Par Seaworthy · 12 septembre 2026

Lines of code and error output displayed on a computer screen

Photo by Artturi Jalli on Unsplash

I get it. You're using an AI coding assistant to ship features fast. It suggests a try/catch block, you accept, and move on. But have you looked at what that catch block actually returns to the client? If it's the raw exception message, you're leaking sensitive details. And I'm not just nitpicking. This is a real data exposure problem that keeps showing up in production.

The problem in plain sight

When your code throws an error, the default behavior in many frameworks is to send a detailed message back to the caller. That message often includes file paths, database query snippets, library versions, and even portions of environment variables. For a developer debugging locally, that's helpful. For an attacker probing your API, it's a gift.

Here's a typical pattern I see in AI-generated code:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/user/<int:user_id>')
def get_user(user_id):
    try:
        user = db.query(f"SELECT * FROM users WHERE id = {user_id}")
        return jsonify(user)
    except Exception as e:
        return jsonify({"error": str(e)}), 500

That str(e) might return something like psycopg2.errors.UndefinedColumn: column "users.password_hash" does not exist plus the full SQL statement. Now the attacker knows your table structure, your database driver, and that you're not using parameterized queries. That last part is a separate disaster, but the error message made it worse.

Why AI assistants make this worse

AI coding helpers are trained on vast amounts of public code. Much of that code is written for tutorials, quick demos, or internal tools where security is an afterthought. When you ask for a CRUD endpoint, the assistant gives you something that works. It rarely warns you that the error handling is unsafe. It doesn't know your deployment context. It just knows the pattern.

And because the code runs, you might not notice. The happy path works. The error path only triggers when something breaks, and by then you're in firefighting mode, not security review mode.

I've seen this in code reviews for startups and large enterprises alike. The fix is simple, but only if you know to look for it.

The fix: sanitize everything

Never send raw exception details to the client. Log them on the server. Return a generic message with a correlation ID. That way you can still debug, but attackers get nothing.

Here's the same endpoint, fixed:

import logging
import uuid
from flask import Flask, jsonify

app = Flask(__name__)
logger = logging.getLogger(__name__)

@app.route('/user/<int:user_id>')
def get_user(user_id):
    try:
        user = db.query("SELECT * FROM users WHERE id = %s", (user_id,))
        return jsonify(user)
    except Exception as e:
        error_id = str(uuid.uuid4())
        logger.exception(f"Error {error_id} for user {user_id}: {e}")
        return jsonify({"error": "Internal server error", "error_id": error_id}), 500

Now the client gets a clean message. You get the full stack trace in your logs, tied to a unique ID. If a user reports a problem, you can search for that ID. No sensitive data leaves your server.

Don't rely on framework defaults

Some frameworks have debug modes that are off by default in production, but others don't. Express.js, for example, will send a stack trace if you pass an error to next() without a custom error handler. Django's DEBUG setting is explicit, but many developers forget to set it to False in production. ASP.NET Core has a developer exception page that must be disabled.

The point is: you must be deliberate. Check your error handling in every environment. Write a test that triggers a failure and asserts that the response body does not contain words like "Traceback", "at line", "SELECT", or "password". This is not paranoia. It's basic hygiene.

A quick checklist

  • Disable debug modes in production. Every framework has a setting. Find it.
  • Use a global error handler. Catch exceptions at the top level and return a generic response.
  • Log details server-side. Include a unique ID in the response so you can correlate.
  • Review AI-generated error handling. If you didn't write it, read it. The assistant won't warn you.
  • Test your error paths. A simple test can catch this before it ships.

My take

This is not a sophisticated attack vector. It's a leak. And leaks are dangerous because they accumulate. One verbose error message might reveal a table name. Another might reveal a file path. Combined, they give an attacker a map of your system. You don't need to be a security expert to fix this. You just need to care enough to look at what your code sends back when things go wrong.

Seaworthy offers a security scanner that checks for verbose error messages and other common data exposure patterns in your codebase.

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