Laravel Request Validation: How to Stop Using Raw $request Input in Controllers
Controllers using $request->input() or $request->all() without validation expose your app to type juggling, injection, and data corruption attacks.
Unvalidated request input refers to using data from HTTP requests — form fields, query parameters, JSON bodies, headers, or cookies — without verifying it conforms to expected types, formats, lengths, and values. Client-side validation (JavaScript form checks) is purely cosmetic: any attacker with cURL or a proxy tool can bypass it completely and send arbitrary data directly to your endpoints.
The consequences span multiple vulnerability categories. Unvalidated string input carries XSS payloads into your database. Unvalidated integer inputs cause type juggling bugs that bypass authentication comparisons. Unvalidated file names cause path traversal. Unvalidated array inputs cause memory exhaustion. Unvalidated foreign key IDs let users access records they should not own. A single missing validation can open several attack vectors simultaneously.
According to Veracode's State of Software Security report, input validation failures appear in over 30% of web applications. Laravel's validation system has 90+ built-in rules covering types, formats, database lookups, file attributes, and conditional logic. The infrastructure exists; the vulnerability occurs when developers bypass it by accessing raw request data with $request->all() or $request->input() without a preceding validate() call.
The Problem
Using raw request data — $request->input(), $request->all(), $request->get(), or $_POST/$_GET — without validation lets attackers send unexpected types, overlong strings, or malicious values. Even if you have frontend validation, attackers bypass it trivially with cURL or browser dev tools. Every controller action that modifies data should validate input server-side before processing.
How to Fix
-
1
Use $request->validate() in controller methods
Replace raw input access with validated data:
// BEFORE — raw input, no validation public function store(Request $request) { Post::create($request->all()); }// AFTER — validated input public function store(Request $request) { $validated = $request->validate([ 'title' => 'required|string|max:255', 'body' => 'required|string|max:10000', 'category_id' => 'required|exists:categories,id', ]);Post::create($validated); }
-
2
Use Form Request classes for complex validation
For controllers with many validation rules, extract to a Form Request:php artisan make:request StorePostRequest// app/Http/Requests/StorePostRequest.php public function rules(): array { return [ 'title' => 'required|string|max:255', 'body' => 'required|string|max:10000', 'category_id' => 'required|exists:categories,id', 'tags' => 'array|max:10', 'tags.*' => 'string|max:50', ]; }// Controller — type-hint the Form Request public function store(StorePostRequest $request) { Post::create($request->validated()); } -
3
Validate route parameters too
Route parameters can also be manipulated:
// In RouteServiceProvider or route definition Route::get('/users/{user}', [UserController::class, 'show']) ->whereNumber('user');// Or validate in the controller public function show(string $id) { $validated = validator(['id' => $id], [ 'id' => 'required|integer|exists:users,id', ])->validate(); }
How to Verify
Search for unvalidated input usage:
grep -rn 'request->all()\|request->input(\|request->get(' app/Http/Controllers/ --include='*.php'
Every occurrence should either use ->validate(), ->validated(), or a Form Request. Run php artisan stackshield:scan --check=SS007 to verify.
Prevention
Establish a team convention: never use $request->all() or $request->input() without prior validation. Use Form Requests for all store/update actions. Add a PHPStan rule or code review checklist item to catch raw input usage.
Frequently Asked Questions
Is $request->only() safe enough?
$request->only() limits which fields are accepted but does not validate their types or values. An attacker can still send title=<script>alert(1)</script> or category_id=99999. Always validate types and constraints, not just field names.
Do I need validation for API endpoints too?
Absolutely. API endpoints are even more vulnerable because there is no browser-enforced CSRF protection or form structure. Always validate API input with the same rigor as web form input.
Is $request->safe() the same as $request->validated()?
They return the same data but $request->safe() returns a ValidatedInput object that prevents accidental access of non-validated fields, while $request->validated() returns a plain array. $request->safe()->only(["name"]) makes intent explicit and is the safer choice when you only need a subset of validated fields.
Should I validate data in queued jobs that receive user-submitted content?
Yes. Jobs may process data long after the HTTP request, and the data may have passed through storage or queue serialization. Validate the data shape at job execution time, or ensure thorough validation happens before the data enters the queue payload. Never assume data in a queue is safe because it was submitted through a form.
Can strict validation rules prevent SQL injection in raw queries?
Validation provides a useful supplementary layer — validating that $id is an integer prevents string-based injection in a raw query — but it should never be the only defense. Parameterized queries or Eloquent must be used as the primary protection. Use both: parameterized queries to prevent injection, and validation to enforce business logic constraints.
Related Guides
Laravel Mass Assignment Vulnerability: How to Protect Eloquent Models with $fillable and $guarded
Eloquent models without $fillable or $guarded allow attackers to set any database column through request input, including is_admin, role, or email_verified_at.
How to Prevent SQL Injection in Laravel
SQL injection vulnerabilities in raw queries and improper Eloquent usage can expose your database. Learn how to write secure queries.
Laravel XSS Prevention Guide: Blade Escaping, {!! !!} Risks & CSP Headers
Prevent cross-site scripting in Laravel. Learn when {!! !!} is safe, how to sanitize HTML input, encode output in Blade templates, and add Content Security Policy headers.
Is your Laravel app exposed right now?
34% of Laravel apps we scan have at least one critical issue. Most teams don't find out until something breaks. Our free scan checks your live application in under 60 seconds.