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.