laravel/framework: Ignore _token and _method when failing on unknown fields
Contributed by xurshudyan
Part of the framework v13.35.0 release
Pull request #61891 patches a false positive in FormRequest::failOnUnknownFields(), the strict mode that rejects requests carrying fields you never declared in rules(). If you turned that feature on and your app still uses classic Blade forms, every real browser submission started failing with messages like "The _token field is prohibited." and "The _method field is prohibited." — even though those hidden inputs are generated by Laravel's own @csrf and @method directives. The fix removes _token and _method from the unknown-fields check, bringing HTML form input in line with how query parameters were already exempted in #59728. For anyone upgrading from v13.34.0, this is a pure bug fix: no API changes, no new configuration, nothing to migrate.
What changed
FormRequest::validateNoUnknownFields() walks every dot-notated input key and fails validation if a key is missing from your rules. The patch strips the two framework-managed hidden fields before that walk:
// src/Illuminate/Foundation/Http/FormRequest.php
$input = $this->isJson() ? $this->json()->all() : $this->request->all();
$input = Arr::except($input, ['_token', '_method']); // new
foreach ($this->dotInputKeys($input) as $inputKey) {
if (! $this->isKnownField($inputKey, $allowedKeys)) {
// ...adds "prohibited" error
}
}
That is the entire runtime change: one Arr::except() call, plus two new tests covering the exemption itself and the "still strict about everything else" case.
The bug, in practice
Enable strict mode the usual way, for example in a service provider:
use Illuminate\Foundation\Http\FormRequest;
public function boot(): void
{
FormRequest::failOnUnknownFields();
}
Then consider a Blade form:
<form method="POST" action="{{ route('profile.update') }}">
@csrf
@method('PUT')
<input name="name" value="{{ old('name') }}">
<button type="submit">Save</button>
</form>
With a request class that only knows about name:
class UpdateProfileRequest extends FormRequest
{
public function rules(): array
{
return ['name' => ['required', 'string']];
}
}
@csrf renders <input type="hidden" name="_token" ...> and @method('PUT') renders name="_method". Those fields are framework plumbing and never appear in rules(), so the strict check flagged them and the user was bounced back with "The _token field is prohibited." on every submission. Nothing about your validation logic was wrong — the check simply didn't account for fields Laravel itself injects.
Why your test suite stayed green
Here's the sneaky part: feature tests using $this->post() or $this->put() never send _token. CSRF verification is skipped during tests, and the test client submits only the fields you pass explicitly. Your tests exercise the request class with just ['name' => 'Taylor'], which validates fine, so the suite passes — while real browsers submit the rendered HTML including its hidden inputs and fail. This bug ships past CI and only surfaces in the browser, which is worth remembering whenever a validation feature depends on the exact shape of the incoming payload.
Behavior after the fix
Two guarantees, both locked in by new tests:
_tokenand_methodare ignored entirely. The request validates, andvalidated()still returns only your rule keys.- Every other undeclared field is still rejected, even when the CSRF fields are present.
// Passes now:
$this->post('/profile', [
'_token' => 'valid-token',
'_method' => 'PUT',
'name' => 'Taylor',
]); // validated() === ['name' => 'Taylor']
// Still fails:
$this->post('/profile', [
'_token' => 'valid-token',
'name' => 'Taylor',
'unexpected' => 'value',
]); // "The unexpected field is prohibited."
JSON API payloads are effectively unaffected: a client that sent _token would now have it quietly ignored rather than rejected, but that was never a meaningful use case. The exemption also mirrors the existing one for query parameters on GET requests from #59728, so the unknown-fields check now consistently tolerates all framework-managed input.
Upgrade impact
- Not using
failOnUnknownFields()? Nothing changes for you at all. - Enabled it with Blade forms? Upgrade and the "prohibited" errors on
_tokenand_methoddisappear. No code, config, or test changes required. - Relying on those fields being rejected? There's no opt-out, but rejecting Laravel's own CSRF and method-spoofing scaffolding was never a workable position — those fields must be present for the framework to function.
- Optional hardening: add a smoke test that includes
_tokenand_methodin the payload, so your suite mirrors what browsers actually send and catches regressions like this one next time.
Takeaways
FormRequest::failOnUnknownFields()no longer treats_tokenand_methodas unknown fields, fixing false rejections for forms using@csrfand@method.- All other undeclared fields are still rejected; the feature's strictness is otherwise unchanged.
- Feature tests can mask this class of bug because CSRF is skipped in tests — simulate the hidden fields if you rely on strict mode.
- Upgrading from v13.34.0 is a drop-in fix with no migration steps.