security
Mass Assignment And Insecure Direct Object Reference
Mass assignment accepts more fields than a user should control. Insecure direct object reference, often called IDOR, exposes a record because code loads it by ID without checking ownership or permission.
Core Controls
- Map accepted request fields explicitly instead of passing whole request arrays into models.
- Treat IDs from URLs and forms as untrusted references, not proof of access.
- Authorise the loaded record against the current user and requested action.
- Keep admin-only fields such as role, owner ID, and approval status out of ordinary update payloads.
- Test with another user's valid record ID.
Map Editable Fields Explicitly
Do not pass a whole request array into a model update.
<?php
declare(strict_types=1);
function editableProjectFields(array $input): array
{
return [
'name' => trim((string) ($input['name'] ?? '')),
'description' => trim((string) ($input['description'] ?? '')),
];
}
print_r(editableProjectFields([
'name' => ' Website refresh ',
'description' => 'Update the product pages.',
'owner_id' => 999,
'is_admin' => true,
]));
The result does not contain owner_id or is_admin, even though the client submitted them.
Load, Then Authorise
An ID in a URL identifies a record. It does not prove access.
<?php
declare(strict_types=1);
function canEditProject(int $currentUserId, array $project): bool
{
return $project['owner_id'] === $currentUserId;
}
var_dump(canEditProject(10, ['id' => 42, 'owner_id' => 10]));
var_dump(canEditProject(11, ['id' => 42, 'owner_id' => 10]));
// Prints:
// bool(true)
// bool(false)
Framework policies or voters are preferable in larger applications because they centralise the rule and make it harder for one route to forget the check.
In Application Work
Profile updates, invoice downloads, project URLs, and JSON APIs are common places to find these bugs. Test with another user's real record ID, not only malformed values.
What To Check
Before moving on, make sure you can map editable fields explicitly, treat IDs as untrusted references, authorise loaded records, and test access with another user's valid ID.
Practice
Practice: Review A Project Update
Requirements
- Allow only editable project fields.
- Reject owner ID and role fields from ordinary updates.
- Load the project and authorise the current user.
- Test access with a different user's project ID.
Show solution
Review Points
- Map accepted request fields explicitly instead of passing whole request arrays into models.
- Treat IDs from URLs and forms as untrusted references, not proof of access.
- Authorise the loaded record against the current user and requested action.
- Keep admin-only fields such as role, owner ID, and approval status out of ordinary update payloads.
- Test with another user's valid record ID.