Look up user-supplied IDs through the relationship
Problem. When an ID arrives in a request, Task::findOrFail($id) will load any task in the database. Change the number in the form or the URL and you can reach a task in somebody else's project. This is an insecure direct object reference, one of the most common access-control bugs.
The usual guard is a manual check after the query that compares project_id with the current project. It works until someone adds a new endpoint and forgets it.
Fix. Query through the relationship instead. $project->tasks() already constrains the query with where project_id = ?, so findOrFail() only searches that project's tasks, and a task from another project is simply not found.
// Before: any task in the database will do$task = Task::findOrFail($request->integer('task_id'));// The check every endpoint has to rememberif ($task->project_id !== $project->id) { abort(404);}// After: the relationship adds "where project_id = ?"$task = $project->tasks()->findOrFail($request->integer('task_id'));Result. There is no ownership check left to forget, and a foreign ID gets the same 404 as one that does not exist, so the response gives nothing away. The project itself still needs its own authorization check; this covers everything below it. For IDs in the URL, scoped route model binding does the same job: add ->scopeBindings() to a route like /projects/{project}/tasks/{task} and Laravel resolves the task through $project->tasks().