---
title: Return Generic Error Messages
impact: HIGH
impactDescription: prevents information disclosure and user enumeration
tags: error-messages, information-disclosure, security, php
---

## Return Generic Error Messages

Detailed error messages (e.g., database stack traces, file paths, or specific missing user notifications) provide attackers with valuable information about your system's architecture and user accounts. While detailed logs are great for developers, they must never be shown to the end-user in production.

**Incorrect (detailed or revealing errors):**

```php
try {
    $db->execute("SELECT * FROM users WHERE id = ?", [$id]);
} catch (\Exception $e) {
    // VULNERABLE: Exposes SQL structure, file paths, and potential credentials
    die("Database Error: " . $e->getMessage() . " at " . $e->getFile());
}

// User Enumeration Vulnerability
if (!$userExists) {
    return response()->json(['error' => 'Email not found'], 404);
}
if (!$passwordMatches) {
    return response()->json(['error' => 'Incorrect password'], 401);
}
```

**Correct (generic messages for users):**

```php
try {
    $db->execute("SELECT * FROM users WHERE id = ?", [$id]);
} catch (\Exception $e) {
    // 1. Log the full details for developers
    Log::error("Database query failed", ['exception' => $e]);

    // 2. Return a generic message to the user
    return response()->json([
        'error' => 'A system error occurred. Please contact support.',
        'request_id' => $requestId // Provide a reference for support
    ], 500);
}

// 3. Prevent User Enumeration (Auth)
// Use the same message and timing for both cases
if (!$userExists || !$passwordMatches) {
    return response()->json(['error' => 'Invalid email or password'], 401);
}
```

**Global Configuration:**
- **`display_errors`**: Ensure this is set to `Off` in your production `php.ini`.
- **Laravel**: Ensure `APP_DEBUG` is set to `false` in production. This automatically swaps detailed "Whoops" pages for a generic "500 | Server Error" page.
- **Custom Exceptions**: Use custom exceptions and map them to generic messages in a central handler (e.g., `App\Exceptions\Handler`).

**Tools:** PHP `php.ini` settings, Laravel Exception Handler, OWASP ZAP (to check for information leakage)
