Security Resources

⌘K
  1. Home
  2. Security Resources
  3. Secure Code Explain
  4. Verbose Error Messages and Stack Trace Disclosure

Verbose Error Messages and Stack Trace Disclosure

Here is an example of Python code that is vulnerable to stack trace and error message disclosure:

🥺 Vulnerable Code

app = Flask(__name__)
app.config["DEBUG"] = True          # interactive debugger left on in production


@app.route("/api/orders/<order_id>")
def get_order(order_id):
    try:
        return jsonify(fetch_order(order_id))
    except Exception as exc:
        # Vulnerable: internal detail is handed to the client
        return jsonify({"error": str(exc), "trace": traceback.format_exc()}), 500

The trace hands over absolute file paths, framework and library versions, function names, SQL fragments, and often the connection string with credentials in it. That is a free map of the application for anyone probing it. Leaving DEBUG = True is worse than a leak: the Werkzeug console is an interactive Python shell in the browser, and its PIN protection has been bypassed more than once.

😎 Secure Code

Here is a version of the same code that is secured against stack trace and error message disclosure:

app = Flask(__name__)
app.config["DEBUG"] = False
app.config["PROPAGATE_EXCEPTIONS"] = False


@app.errorhandler(Exception)
def handle_error(exc):
    incident = uuid.uuid4().hex

    # Everything useful goes to the log, nothing useful goes to the client
    app.logger.exception("unhandled_error incident=%s path=%s", incident, request.path)

    if isinstance(exc, HTTPException):
        return jsonify({"error": exc.name, "incident": incident}), exc.code

    return jsonify({"error": "Internal server error", "incident": incident}), 500

The client gets a generic message plus an incident id, support can find the full trace in the logs with that id, and the attacker learns nothing about the stack. Do the same for 404 and 403 pages so error text does not confirm whether a record exists, turn off directory listings and server version banners, and prove it by triggering a deliberate 500 in staging and reading the response body.