Skip to content

Validation Bypass via Original Property Name in Mapped Inputs #1019

Open
@c-v-c-v

Description

@c-v-c-v

✏️ Describe the bug
If your application uses mapped property names and the property is not required — meaning it can be omitted(e.g., by being set to null, having a default value, lacking a 'required' validation rule, or being conditionally validated with rules like required_if, sometimes, etc.) — then the validator can be bypassed by using the original property name.

This issue arises because the validation logic only checks the mapped property name. When it determines the property is not required and no value is provided under the mapped name, it skips further validation rules.
However, during assignment, the property can still be set using either the mapped name or the original name. This inconsistency between validation (which only looks at the mapped name) and assignment (which accepts both) creates a loophole where validation is bypassed but the property still gets assigned — potentially with invalid or unsafe data.

↪️ To Reproduce
Provide us a pest test like this one which shows the problem:

class Page extends BaseData
{
    #[Min(1)]
    #[MapInputName('page.number')]
    public int $number = 1;

    #[Between(1, 200)]
    #[MapInputName('page.size')]
    public int $size = 10;

    public static function prepareForPipeline(array $properties): array
    {
        // unset($properties['size'], $properties['number']);
    
        return $properties;
    }
}

it('bypasses validator using original attribute name', function () {
    // no error
    $page = Page::validateAndCreate([
        'size' => 300,
    ]);

    // 300
    dd($page->size);
});

✅ Expected behavior
print 10(Do not use the original property name)
or
Illuminate\Validation\ValidationException: The page.size field must be between 1 and 200.(Keep the original property name)

🖥️ Versions

Laravel: 11.44.1
Laravel Data: 4.13.2
PHP: 8.2.20

Confusion Around Mapping Property Names
If a property has a map setting, can its original property name still be used?
If so, it feels more like an alias rather than a strict mapping.

Do not use the original property name
Image

However, this conflicts with the following test case:
Image

Keep the original property name
Image

But this also conflicts with the following test case:
Image

Related link
https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/mapping-property-names

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions