2

Laravel Form Validation is great, except that it doesn't filter out extraneous keys when array notation is used.

I am type hinting the form request in my controller.

public function saveEdit(Post\EditRequest $request)
{
    $valid = $request->validated();
}

If my form has address_1 and address_2, and the user spoofs address_3, the spoofed value will not turn up in $valid.

However, if my form uses array notation, such as venue[address_1], and venue[address_2], then the user can spoof venue[address_3], and it will turn up in $valid.

Has anyone else come across this? How did you deal with it?

It seems like the validated() method on the form request class needs to operate recursively.

0

2 Answers 2

1

Unfortunately, Laravel doesn't include built-in support for validating array keys yet, only array values. To do so, we need to add custom validation rules.

However, with alternative protection like $fillable model attributes and the array_only() helper function, creating these rules is a lot of extra work for a very unlikely edge case. We provide validation feedback for expected user error and sanitize to protect our data from unexpected input.

If the user spoofs a key, as long as we don't save it, or we filter it out, they won't be too concerned if they don't see a pretty validation message—it doesn't make sense to validate a field that shouldn't exist in the first place.

To illustrate how sanitization works, here's a Venue model that declares its fillable attributes:

class Venue extends Model 
{
    protected $fillable = [ 'address_1', 'address_2' ]; 
    ...
}

Now, if a malicious user attempts to spoof another attribute in the array:

<input name="venue[address_1]" value="...">
<input name="venue[address_2]" value="...">
<input name="venue[address_3]" value="spoof!">

...and we use the input array directly to update a model:

public function update(Request $request, $venueId)
{
    $venue = Venue::find($venueId); 
    $venue->update($request->venue);
    ...
}

...the model will strip out the additional address_3 element from the input array because we never declared it as a fillable field. In other words, the model sanitized the input.

In some cases, we may need to simply sanitize array elements without using Eloquent models. We can use the array_only() function (or Arr:only()) to do this:

$venueAddress = array_only($request->venue, [ 'address_1', 'address_2' ]);
Sign up to request clarification or add additional context in comments.

Comments

1

you can use dot notation

 public function rules()
    {
        return [
            'venue.address_1' => 'required',
            'venue.address_2' => 'required',
            'venue.address_3'=>'required',
        ];
    }

and if you are using dynamic array you can do same by

 public function rules()
     {
         return [
             'venue.address_.*' => 'required'
         ];
     }

2 Comments

Hi Ankit, I am using dot notation.
Can you please update your question and share you code?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.