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.

Medium severity Application Security Updated 2026-05-01 Markdown

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

Free security check

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.

18% have debug mode on
72% missing security headers
12% have exposed .env
Scan My App Free No signup required. Results in 60 seconds.
or category_id=99999. Always validate types and constraints, not just field names." } }, { "@type": "Question", "name": "Do I need validation for API endpoints too?", "acceptedAnswer": { "@type": "Answer", "text": "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." } }, { "@type": "Question", "name": "Is $request->safe() the same as $request->validated()?", "acceptedAnswer": { "@type": "Answer", "text": "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." } }, { "@type": "Question", "name": "Should I validate data in queued jobs that receive user-submitted content?", "acceptedAnswer": { "@type": "Answer", "text": "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." } }, { "@type": "Question", "name": "Can strict validation rules prevent SQL injection in raw queries?", "acceptedAnswer": { "@type": "Answer", "text": "Validation provides a useful supplementary layer \u2014 validating that $id is an integer prevents string-based injection in a raw query \u2014 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." } } ] }