Weakness reference
CWE-497

Exposure of Sensitive System Information to an Unauthorized Control Sphere

This weakness occurs when an application or system leaks internal details—such as software versions, file paths, configuration settings, or environment…

01Summary

This weakness occurs when an application or system leaks internal details—such as software versions, file paths, configuration settings, or environment information—to users or attackers who should not have access to that data. These details can help attackers plan more targeted attacks or exploit known vulnerabilities. Preventing this exposure is a foundational part of security hardening.

02How It Happens

Applications often inadvertently reveal system information through error messages, HTTP headers, directory listings, debug output, or publicly accessible configuration files. Developers may enable verbose logging or detailed error reporting during development and forget to disable it in production. Web servers may be misconfigured to serve directory indexes or expose version banners. API responses might include internal field names or stack traces. In each case, the application fails to distinguish between information safe for end users and information that should remain internal.

03Real-World Impact

Exposed system information significantly reduces the attacker's reconnaissance effort. Knowing the exact version of a web server, CMS, or framework allows an attacker to search for known vulnerabilities in that specific version. Leaked file paths reveal the application's internal structure, making it easier to guess other endpoints or resources. Configuration details such as database names or API endpoints can be leveraged in follow-up attacks. While information disclosure alone may not directly compromise data, it almost always precedes and enables more serious attacks.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import traceback
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/user/<user_id>')
def get_user(user_id):
    try:
        # Simulate database lookup
        user = fetch_user_from_db(user_id)
        return jsonify(user)
    except Exception as e:
        # Exposes full stack trace and internal paths
        return jsonify({"error": str(e), "traceback": traceback.format_exc()}), 500

Why it's vulnerable:
The error response includes the full exception message and stack trace, which reveals internal function names, file paths, and the application's structure to any client that triggers an error.

Fixed pattern
import traceback
import logging
from flask import Flask, jsonify

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

@app.route('/api/user/<user_id>')
def get_user(user_id):
    try:
        user = fetch_user_from_db(user_id)
        return jsonify(user)
    except Exception as e:
        # Log full details internally; return generic message to client
        logger.error("Error fetching user", exc_info=True)
        return jsonify({"error": "An error occurred. Please try again later."}), 500
Vulnerable pattern
<?php
// Expose PHP version and configuration in headers
header("X-Powered-By: PHP/8.1.5");

// Display detailed error messages to all users
ini_set('display_errors', 1);
error_reporting(E_ALL);

$user_id = $_GET['id'];
$result = mysqli_query($conn, "SELECT * FROM users WHERE id = $user_id");

if (!$result) {
    // Exposes database error details to the client
    die("Database error: " . mysqli_error($conn));
}
?>

Why it's vulnerable:
The code exposes the PHP version in headers, enables error display to all users (including attackers), and returns raw database error messages that reveal table and column names.

Fixed pattern
<?php
// Suppress version information
header_remove("X-Powered-By");

// Log errors internally; never display to users
ini_set('display_errors', 0);
ini_set('log_errors', 1);
error_reporting(E_ALL);

$user_id = $_GET['id'];
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();

if (!$result) {
    // Log the real error; return generic message to client
    error_log("Database query failed: " . $conn->error);
    die("An error occurred. Please contact support.");
}
?>

05Prevention Checklist

Disable verbose error reporting in production.
Set display_errors to 0 and log errors to a file accessible only to administrators, not to the client.
Remove or mask server and framework version headers.
Disable X-Powered-By, Server, and similar headers that advertise software versions.
Disable directory listing.
Configure web servers to deny directory index requests; serve only explicitly defined files.
Sanitize error messages.
Return generic, user-friendly error messages to clients while logging full details server-side for debugging.
Audit configuration files.
Ensure .env, config.php, settings.json, and similar files are not web-accessible and are excluded from version control.
Review API responses.
Avoid exposing internal field names, database schema details, or system paths in JSON/XML responses.

06Signs You May Already Be Affected

Check your application's error pages and HTTP response headers. If you see detailed stack traces, database error messages, file paths, or version numbers when you trigger an error, your application is leaking information. Review your web server logs and error logs for patterns of reconnaissance activity (repeated requests to non-existent endpoints, requests for common configuration file names like .env or web.config). Use a browser's developer tools to inspect response headers and look for X-Powered-By, Server, or other version-revealing headers.

07Related Recent Vulnerabilities