A 404 that should have been a 403, and the leak it caused

An endpoint returning 404 for a resource that exists but belongs to somebody else, and 403 for one that exists and is forbidden — which distinguishes the two.

// the leak
$order = Order::find($id) ?? abort(404);
$this->authorize('view', $order) ?: abort(403);

// an attacker enumerating ids learns which exist:
//   404 → no such order
//   403 → exists, not yours

// the fix: one response for both
$order = Order::find($id);

if ($order === null || $user->cannot('view', $order)) {
    abort(404);
}

Returning 404 for forbidden resources is the standard advice and it is worth understanding why rather than applying it everywhere — on a resource whose existence is public, a 403 is more useful and leaks nothing. The rule is about whether the identifier itself is a secret, and for sequential order ids it certainly is.