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 example
<?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 example
<?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.