VYPR
Moderate severityNVD Advisory· Published Mar 5, 2025· Updated Mar 5, 2025

Laravel has a File Validation Bypass

CVE-2025-27515

Description

Laravel is a web application framework. When using wildcard validation to validate a given file or image field (files.*), a user-crafted malicious request could potentially bypass the validation rules. This vulnerability is fixed in 11.44.1 and 12.1.1.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Laravel's wildcard file validation could be bypassed due to a per-instance placeholder, fixed by using a static hash in versions 11.44.1 and 12.1.1.

Vulnerability

Overview

Laravel's Validator class, when processing wildcard validation rules for file or image fields (e.g., files.*), uses internal placeholders to replace dots and asterisks in field names. In vulnerable versions, this placeholder was generated per Validator instance ($this->dotPlaceholder = Str::random()). An attacker could craft a malicious request that manipulates the placeholder value, causing the validation logic to misinterpret field names and bypass the intended validation rules [1][2].

Exploitation

The attack requires no special privileges; any endpoint using wildcard validation for file uploads is potentially affected. By sending a request with field keys that match the placeholder pattern, an attacker can trick the Validator into treating malicious input as valid. The vulnerability is triggered during the parsing of request data, where the placeholder is replaced back to dots and asterisks [1][2].

Impact

Successful exploitation allows an attacker to bypass file validation rules, such as file type, size, or MIME type restrictions. This could lead to arbitrary file uploads, potentially enabling remote code execution or other severe consequences depending on the application's handling of uploaded files [1].

Mitigation

The vulnerability is fixed in Laravel versions 11.44.1 and 12.1.1. The fix changes the placeholder from a per-instance random string to a static hash (static::$placeholderHash) shared across all Validator instances, preventing manipulation by external input [2][3]. Users are strongly advised to upgrade to the patched versions immediately.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
laravel/frameworkPackagist
>= 12.0.0, < 12.1.112.1.1
laravel/frameworkPackagist
>= 11.0.0, < 11.44.111.44.1
laravel/frameworkPackagist
< 10.48.2910.48.29

Affected products

4

Patches

2
a4f7a8f9b83e

[10.x] Fix attribute name used on `Validator` instance within certain rule classes (#54943)

https://github.com/laravel/frameworkMior Muhammad ZakiMar 10, 2025via ghsa
3 files changed · +129 12
  • src/Illuminate/Validation/Validator.php+26 12 modified
    @@ -302,11 +302,11 @@ class Validator implements ValidatorContract
         protected $defaultNumericRules = ['Numeric', 'Integer', 'Decimal'];
     
         /**
    -     * The current placeholder for dots in rule keys.
    +     * The current random hash for the validator.
          *
          * @var string
          */
    -    protected $dotPlaceholder;
    +    protected static $placeholderHash;
     
         /**
          * The exception to throw upon failure.
    @@ -335,7 +335,9 @@ class Validator implements ValidatorContract
         public function __construct(Translator $translator, array $data, array $rules,
                                     array $messages = [], array $attributes = [])
         {
    -        $this->dotPlaceholder = Str::random();
    +        if (! isset(static::$placeholderHash)) {
    +            static::$placeholderHash = Str::random();
    +        }
     
             $this->initialRules = $rules;
             $this->translator = $translator;
    @@ -363,7 +365,7 @@ public function parseData(array $data)
     
                 $key = str_replace(
                     ['.', '*'],
    -                [$this->dotPlaceholder, '__asterisk__'],
    +                ['__dot__'.static::$placeholderHash, '__asterisk__'.static::$placeholderHash],
                     $key
                 );
     
    @@ -401,7 +403,7 @@ protected function replacePlaceholders($data)
         protected function replacePlaceholderInString(string $value)
         {
             return str_replace(
    -            [$this->dotPlaceholder, '__asterisk__'],
    +            ['__dot__'.static::$placeholderHash, '__asterisk__'.static::$placeholderHash],
                 ['.', '*'],
                 $value
             );
    @@ -720,7 +722,7 @@ protected function getPrimaryAttribute($attribute)
         protected function replaceDotInParameters(array $parameters)
         {
             return array_map(function ($field) {
    -            return str_replace('\.', $this->dotPlaceholder, $field);
    +            return str_replace('\.', '__dot__'.static::$placeholderHash, $field);
             }, $parameters);
         }
     
    @@ -846,11 +848,23 @@ protected function hasNotFailedPreviousRuleIfPresenceRule($rule, $attribute)
          */
         protected function validateUsingCustomRule($attribute, $value, $rule)
         {
    -        $attribute = $this->replacePlaceholderInString($attribute);
    +        $originalAttribute = $this->replacePlaceholderInString($attribute);
    +
    +        $attribute = match (true) {
    +            $rule instanceof Rules\File => $attribute,
    +            $rule instanceof Rules\Password => $attribute,
    +            default => $originalAttribute,
    +        };
     
             $value = is_array($value) ? $this->replacePlaceholders($value) : $value;
     
             if ($rule instanceof ValidatorAwareRule) {
    +            if ($attribute !== $originalAttribute) {
    +                $this->addCustomAttributes([
    +                    $attribute => $this->customAttributes[$originalAttribute] ?? $originalAttribute,
    +                ]);
    +            }
    +
                 $rule->setValidator($this);
             }
     
    @@ -863,14 +877,14 @@ protected function validateUsingCustomRule($attribute, $value, $rule)
                     get_class($rule->invokable()) :
                     get_class($rule);
     
    -            $this->failedRules[$attribute][$ruleClass] = [];
    +            $this->failedRules[$originalAttribute][$ruleClass] = [];
     
    -            $messages = $this->getFromLocalArray($attribute, $ruleClass) ?? $rule->message();
    +            $messages = $this->getFromLocalArray($originalAttribute, $ruleClass) ?? $rule->message();
     
                 $messages = $messages ? (array) $messages : [$ruleClass];
     
                 foreach ($messages as $key => $message) {
    -                $key = is_string($key) ? $key : $attribute;
    +                $key = is_string($key) ? $key : $originalAttribute;
     
                     $this->messages->add($key, $this->makeReplacements(
                         $message, $key, $ruleClass, []
    @@ -1159,7 +1173,7 @@ public function getRulesWithoutPlaceholders()
         {
             return collect($this->rules)
                 ->mapWithKeys(fn ($value, $key) => [
    -                str_replace($this->dotPlaceholder, '\\.', $key) => $value,
    +                str_replace('__dot__'.static::$placeholderHash, '\\.', $key) => $value,
                 ])
                 ->all();
         }
    @@ -1173,7 +1187,7 @@ public function getRulesWithoutPlaceholders()
         public function setRules(array $rules)
         {
             $rules = collect($rules)->mapWithKeys(function ($value, $key) {
    -            return [str_replace('\.', $this->dotPlaceholder, $key) => $value];
    +            return [str_replace('\.', '__dot__'.static::$placeholderHash, $key) => $value];
             })->toArray();
     
             $this->initialRules = $rules;
    
  • tests/Integration/Validation/Rules/FileValidationTest.php+54 0 added
    @@ -0,0 +1,54 @@
    +<?php
    +
    +namespace Illuminate\Tests\Integration\Validation\Rules;
    +
    +use Illuminate\Http\UploadedFile;
    +use Illuminate\Support\Facades\Validator;
    +use Illuminate\Validation\Rules\File;
    +use Orchestra\Testbench\TestCase;
    +use PHPUnit\Framework\Attributes\TestWith;
    +
    +class FileValidationTest extends TestCase
    +{
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array(string $attribute)
    +    {
    +        $file = UploadedFile::fake()->create('laravel.png', 1, 'image/png');
    +
    +        $validator = Validator::make([
    +            'files' => [
    +                $attribute => $file,
    +            ],
    +        ], [
    +            'files.*' => ['required', File::types(['image/png', 'image/jpeg'])],
    +        ]);
    +
    +        $this->assertTrue($validator->passes());
    +    }
    +
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array_when_validation_should_fails(string $attribute)
    +    {
    +        $file = UploadedFile::fake()->create('laravel.php', 1, 'image/php');
    +
    +        $validator = Validator::make([
    +            'files' => [
    +                $attribute => $file,
    +            ],
    +        ], [
    +            'files.*' => ['required', File::types($mimes = ['image/png', 'image/jpeg'])],
    +        ]);
    +
    +        $this->assertFalse($validator->passes());
    +
    +        $this->assertSame([
    +            0 => __('validation.mimetypes', ['attribute' => sprintf('files.%s', str_replace('_', ' ', $attribute)), 'values' => implode(', ', $mimes)]),
    +        ], $validator->messages()->all());
    +    }
    +}
    
  • tests/Integration/Validation/Rules/PasswordValidationTest.php+49 0 added
    @@ -0,0 +1,49 @@
    +<?php
    +
    +namespace Illuminate\Tests\Integration\Validation\Rules;
    +
    +use Illuminate\Support\Facades\Validator;
    +use Illuminate\Validation\Rules\Password;
    +use Orchestra\Testbench\TestCase;
    +use PHPUnit\Framework\Attributes\TestWith;
    +
    +class PasswordValidationTest extends TestCase
    +{
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array(string $attribute)
    +    {
    +        $validator = Validator::make([
    +            'passwords' => [
    +                $attribute => 'secret',
    +            ],
    +        ], [
    +            'passwords.*' => ['required', Password::default()->min(6)],
    +        ]);
    +
    +        $this->assertTrue($validator->passes());
    +    }
    +
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array_when_validation_should_fails(string $attribute)
    +    {
    +        $validator = Validator::make([
    +            'passwords' => [
    +                $attribute => 'secret',
    +            ],
    +        ], [
    +            'passwords.*' => ['required', Password::default()->min(8)],
    +        ]);
    +
    +        $this->assertFalse($validator->passes());
    +
    +        $this->assertSame([
    +            0 => sprintf('The passwords.%s field must be at least 8 characters.', str_replace('_', ' ', $attribute)),
    +        ], $validator->messages()->all());
    +    }
    +}
    
2d133034fefd

fix conflicts

https://github.com/laravel/frameworkTaylor OtwellMar 5, 2025via ghsa
20 files changed · +202 38
  • src/Illuminate/Collections/Traits/EnumeratesValues.php+1 1 modified
    @@ -342,7 +342,7 @@ public function value($key, $default = null)
          *
          * @template TEnsureOfType
          *
    -     * @param  class-string<TEnsureOfType>|array<array-key, class-string<TEnsureOfType>>  $type
    +     * @param  class-string<TEnsureOfType>|array<array-key, class-string<TEnsureOfType>>|scalar|'array'|'null'  $type
          * @return static<TKey, TEnsureOfType>
          *
          * @throws \UnexpectedValueException
    
  • src/Illuminate/Foundation/Application.php+1 1 modified
    @@ -257,7 +257,7 @@ public static function inferBasePath()
                 isset($_ENV['APP_BASE_PATH']) => $_ENV['APP_BASE_PATH'],
                 default => dirname(array_values(array_filter(
                     array_keys(ClassLoader::getRegisteredLoaders()),
    -                fn ($path) => ! str_contains($path, '/vendor/'),
    +                fn ($path) => ! str_starts_with($path, 'phar://'),
                 ))[0]),
             };
         }
    
  • src/Illuminate/Validation/Validator.php+28 13 modified
    @@ -307,11 +307,11 @@ class Validator implements ValidatorContract
         protected $defaultNumericRules = ['Numeric', 'Integer', 'Decimal'];
     
         /**
    -     * The current placeholder for dots in rule keys.
    +     * The current random hash for the validator.
          *
          * @var string
          */
    -    protected $dotPlaceholder;
    +    protected static $placeholderHash;
     
         /**
          * The exception to throw upon failure.
    @@ -344,7 +344,9 @@ public function __construct(
             array $messages = [],
             array $attributes = [],
         ) {
    -        $this->dotPlaceholder = Str::random();
    +        if (! isset(static::$placeholderHash)) {
    +            static::$placeholderHash = Str::random();
    +        }
     
             $this->initialRules = $rules;
             $this->translator = $translator;
    @@ -372,7 +374,7 @@ public function parseData(array $data)
     
                 $key = str_replace(
                     ['.', '*'],
    -                [$this->dotPlaceholder, '__asterisk__'],
    +                ['__dot__'.static::$placeholderHash, '__asterisk__'.static::$placeholderHash],
                     $key
                 );
     
    @@ -410,7 +412,7 @@ protected function replacePlaceholders($data)
         protected function replacePlaceholderInString(string $value)
         {
             return str_replace(
    -            [$this->dotPlaceholder, '__asterisk__'],
    +            ['__dot__'.static::$placeholderHash, '__asterisk__'.static::$placeholderHash],
                 ['.', '*'],
                 $value
             );
    @@ -425,7 +427,7 @@ protected function replacePlaceholderInString(string $value)
         protected function replaceDotPlaceholderInParameters(array $parameters)
         {
             return array_map(function ($field) {
    -            return str_replace($this->dotPlaceholder, '.', $field);
    +            return str_replace('__dot__'.static::$placeholderHash, '.', $field);
             }, $parameters);
         }
     
    @@ -746,7 +748,7 @@ protected function getPrimaryAttribute($attribute)
         protected function replaceDotInParameters(array $parameters)
         {
             return array_map(function ($field) {
    -            return str_replace('\.', $this->dotPlaceholder, $field);
    +            return str_replace('\.', '__dot__'.static::$placeholderHash, $field);
             }, $parameters);
         }
     
    @@ -872,11 +874,24 @@ protected function hasNotFailedPreviousRuleIfPresenceRule($rule, $attribute)
          */
         protected function validateUsingCustomRule($attribute, $value, $rule)
         {
    -        $attribute = $this->replacePlaceholderInString($attribute);
    +        $originalAttribute = $this->replacePlaceholderInString($attribute);
    +
    +        $attribute = match (true) {
    +            $rule instanceof Rules\Email => $attribute,
    +            $rule instanceof Rules\File => $attribute,
    +            $rule instanceof Rules\Password => $attribute,
    +            default => $originalAttribute,
    +        };
     
             $value = is_array($value) ? $this->replacePlaceholders($value) : $value;
     
             if ($rule instanceof ValidatorAwareRule) {
    +            if ($attribute !== $originalAttribute) {
    +                $this->addCustomAttributes([
    +                    $attribute => $this->customAttributes[$originalAttribute] ?? $originalAttribute,
    +                ]);
    +            }
    +
                 $rule->setValidator($this);
             }
     
    @@ -889,14 +904,14 @@ protected function validateUsingCustomRule($attribute, $value, $rule)
                     get_class($rule->invokable()) :
                     get_class($rule);
     
    -            $this->failedRules[$attribute][$ruleClass] = [];
    +            $this->failedRules[$originalAttribute][$ruleClass] = [];
     
    -            $messages = $this->getFromLocalArray($attribute, $ruleClass) ?? $rule->message();
    +            $messages = $this->getFromLocalArray($originalAttribute, $ruleClass) ?? $rule->message();
     
                 $messages = $messages ? (array) $messages : [$ruleClass];
     
                 foreach ($messages as $key => $message) {
    -                $key = is_string($key) ? $key : $attribute;
    +                $key = is_string($key) ? $key : $originalAttribute;
     
                     $this->messages->add($key, $this->makeReplacements(
                         $message, $key, $ruleClass, []
    @@ -1189,7 +1204,7 @@ public function getRulesWithoutPlaceholders()
         {
             return (new Collection($this->rules))
                 ->mapWithKeys(fn ($value, $key) => [
    -                str_replace($this->dotPlaceholder, '\\.', $key) => $value,
    +                str_replace('__dot__'.static::$placeholderHash, '\\.', $key) => $value,
                 ])
                 ->all();
         }
    @@ -1203,7 +1218,7 @@ public function getRulesWithoutPlaceholders()
         public function setRules(array $rules)
         {
             $rules = (new Collection($rules))->mapWithKeys(function ($value, $key) {
    -            return [str_replace('\.', $this->dotPlaceholder, $key) => $value];
    +            return [str_replace('\.', '__dot__'.static::$placeholderHash, $key) => $value];
             })->toArray();
     
             $this->initialRules = $rules;
    
  • tests/Integration/Cache/DynamoDbStoreTest.php+1 1 modified
    @@ -65,7 +65,7 @@ public function testLocksCanBeAcquired()
          * @param  \Illuminate\Foundation\Application  $app
          * @return void
          */
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             if (! env('DYNAMODB_CACHE_TABLE')) {
                 $this->markTestSkipped('DynamoDB not configured.');
    
  • tests/Integration/Cookie/CookieTest.php+1 1 modified
    @@ -42,7 +42,7 @@ public function test_cookie_is_sent_back_with_proper_expire_time_with_respect_to
             $this->assertEquals(Carbon::now()->getTimestamp() + 60, $response->headers->getCookies()[1]->getExpiresTime());
         }
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app->instance(
                 ExceptionHandler::class,
    
  • tests/Integration/Database/EloquentTransactionWithAfterCommitUsingDatabaseTransactionsTest.php+1 1 modified
    @@ -32,7 +32,7 @@ protected function setUp(): void
             }
         }
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $connection = $app->make('config')->get('database.default');
     
    
  • tests/Integration/Database/MariaDb/DatabaseEmulatePreparesMariaDbConnectionTest.php+2 2 modified
    @@ -10,9 +10,9 @@
     #[RequiresPhpExtension('pdo_mysql')]
     class DatabaseEmulatePreparesMariaDbConnectionTest extends DatabaseMariaDbConnectionTest
     {
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
    -        parent::getEnvironmentSetUp($app);
    +        parent::defineEnvironment($app);
     
             $app['config']->set('database.connections.mariadb.options', [
                 PDO::ATTR_EMULATE_PREPARES => true,
    
  • tests/Integration/Database/MySql/DatabaseEmulatePreparesMySqlConnectionTest.php+2 2 modified
    @@ -10,9 +10,9 @@
     #[RequiresPhpExtension('pdo_mysql')]
     class DatabaseEmulatePreparesMySqlConnectionTest extends DatabaseMySqlConnectionTest
     {
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
    -        parent::getEnvironmentSetUp($app);
    +        parent::defineEnvironment($app);
     
             $app['config']->set('database.connections.mysql.options', [
                 PDO::ATTR_EMULATE_PREPARES => true,
    
  • tests/Integration/Database/Postgres/PostgresSchemaBuilderTest.php+2 2 modified
    @@ -13,9 +13,9 @@
     #[RequiresPhpExtension('pdo_pgsql')]
     class PostgresSchemaBuilderTest extends PostgresTestCase
     {
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
    -        parent::getEnvironmentSetUp($app);
    +        parent::defineEnvironment($app);
     
             $app['config']->set('database.connections.pgsql.search_path', 'public,private');
         }
    
  • tests/Integration/Mail/SendingMarkdownMailTest.php+1 1 modified
    @@ -12,7 +12,7 @@
     
     class SendingMarkdownMailTest extends TestCase
     {
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app['config']->set('mail.driver', 'array');
     
    
  • tests/Integration/Mail/SendingQueuedMailTest.php+1 1 modified
    @@ -11,7 +11,7 @@
     
     class SendingQueuedMailTest extends TestCase
     {
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app['config']->set('mail.driver', 'array');
     
    
  • tests/Integration/Queue/JobEncryptionTest.php+2 2 modified
    @@ -21,9 +21,9 @@ class JobEncryptionTest extends DatabaseTestCase
     {
         use DatabaseMigrations;
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
    -        parent::getEnvironmentSetUp($app);
    +        parent::defineEnvironment($app);
     
             $app['config']->set('app.key', Str::random(32));
             $app['config']->set('queue.default', 'database');
    
  • tests/Integration/Queue/ModelSerializationTest.php+1 1 modified
    @@ -18,7 +18,7 @@ class ModelSerializationTest extends TestCase
     {
         use RefreshDatabase;
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app['config']->set('database.connections.custom', [
                 'driver' => 'sqlite',
    
  • tests/Integration/Queue/QueueConnectionTest.php+3 6 modified
    @@ -8,17 +8,14 @@
     use Illuminate\Foundation\Bus\Dispatchable;
     use Illuminate\Support\Facades\Bus;
     use Mockery as m;
    +use Orchestra\Testbench\Attributes\WithConfig;
     use Orchestra\Testbench\TestCase;
     use Throwable;
     
    +#[WithConfig('queue.default', 'sqs')]
    +#[WithConfig('queue.connections.sqs.after_commit', true)]
     class QueueConnectionTest extends TestCase
     {
    -    protected function getEnvironmentSetUp($app)
    -    {
    -        $app['config']->set('queue.default', 'sqs');
    -        $app['config']->set('queue.connections.sqs.after_commit', true);
    -    }
    -
         protected function tearDown(): void
         {
             QueueConnectionTestJob::$ran = false;
    
  • tests/Integration/Validation/Rules/EmailValidationTest.php+49 0 added
    @@ -0,0 +1,49 @@
    +<?php
    +
    +namespace Illuminate\Tests\Integration\Validation\Rules;
    +
    +use Illuminate\Support\Facades\Validator;
    +use Illuminate\Validation\Rules\Email;
    +use Orchestra\Testbench\TestCase;
    +use PHPUnit\Framework\Attributes\TestWith;
    +
    +class EmailValidationTest extends TestCase
    +{
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array(string $attribute)
    +    {
    +        $validator = Validator::make([
    +            'emails' => [
    +                $attribute => 'taylor@laravel.com',
    +            ],
    +        ], [
    +            'emails.*' => ['required', Email::default()->rfcCompliant()],
    +        ]);
    +
    +        $this->assertTrue($validator->passes());
    +    }
    +
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array_when_validation_should_fails(string $attribute)
    +    {
    +        $validator = Validator::make([
    +            'emails' => [
    +                $attribute => 'taylor[at]laravel.com',
    +            ],
    +        ], [
    +            'emails.*' => ['required', Email::default()->rfcCompliant()],
    +        ]);
    +
    +        $this->assertFalse($validator->passes());
    +
    +        $this->assertSame([
    +            0 => __('validation.email', ['attribute' => sprintf('emails.%s', str_replace('_', ' ', $attribute))]),
    +        ], $validator->messages()->all());
    +    }
    +}
    
  • tests/Integration/Validation/Rules/FileValidationTest.php+54 0 added
    @@ -0,0 +1,54 @@
    +<?php
    +
    +namespace Illuminate\Tests\Integration\Validation\Rules;
    +
    +use Illuminate\Http\UploadedFile;
    +use Illuminate\Support\Facades\Validator;
    +use Illuminate\Validation\Rules\File;
    +use Orchestra\Testbench\TestCase;
    +use PHPUnit\Framework\Attributes\TestWith;
    +
    +class FileValidationTest extends TestCase
    +{
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array(string $attribute)
    +    {
    +        $file = UploadedFile::fake()->create('laravel.png', 1, 'image/png');
    +
    +        $validator = Validator::make([
    +            'files' => [
    +                $attribute => $file,
    +            ],
    +        ], [
    +            'files.*' => ['required', File::types(['image/png', 'image/jpeg'])],
    +        ]);
    +
    +        $this->assertTrue($validator->passes());
    +    }
    +
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array_when_validation_should_fails(string $attribute)
    +    {
    +        $file = UploadedFile::fake()->create('laravel.php', 1, 'image/php');
    +
    +        $validator = Validator::make([
    +            'files' => [
    +                $attribute => $file,
    +            ],
    +        ], [
    +            'files.*' => ['required', File::types($mimes = ['image/png', 'image/jpeg'])],
    +        ]);
    +
    +        $this->assertFalse($validator->passes());
    +
    +        $this->assertSame([
    +            0 => __('validation.mimetypes', ['attribute' => sprintf('files.%s', str_replace('_', ' ', $attribute)), 'values' => implode(', ', $mimes)]),
    +        ], $validator->messages()->all());
    +    }
    +}
    
  • tests/Integration/Validation/Rules/PasswordValidationTest.php+49 0 added
    @@ -0,0 +1,49 @@
    +<?php
    +
    +namespace Illuminate\Tests\Integration\Validation\Rules;
    +
    +use Illuminate\Support\Facades\Validator;
    +use Illuminate\Validation\Rules\Password;
    +use Orchestra\Testbench\TestCase;
    +use PHPUnit\Framework\Attributes\TestWith;
    +
    +class PasswordValidationTest extends TestCase
    +{
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array(string $attribute)
    +    {
    +        $validator = Validator::make([
    +            'passwords' => [
    +                $attribute => 'secret',
    +            ],
    +        ], [
    +            'passwords.*' => ['required', Password::default()->min(6)],
    +        ]);
    +
    +        $this->assertTrue($validator->passes());
    +    }
    +
    +    #[TestWith(['0'])]
    +    #[TestWith(['.'])]
    +    #[TestWith(['*'])]
    +    #[TestWith(['__asterisk__'])]
    +    public function test_it_can_validate_attribute_as_array_when_validation_should_fails(string $attribute)
    +    {
    +        $validator = Validator::make([
    +            'passwords' => [
    +                $attribute => 'secret',
    +            ],
    +        ], [
    +            'passwords.*' => ['required', Password::default()->min(8)],
    +        ]);
    +
    +        $this->assertFalse($validator->passes());
    +
    +        $this->assertSame([
    +            0 => sprintf('The passwords.%s field must be at least 8 characters.', str_replace('_', ' ', $attribute)),
    +        ], $validator->messages()->all());
    +    }
    +}
    
  • tests/Integration/View/BladeAnonymousComponentTest.php+1 1 modified
    @@ -41,7 +41,7 @@ public function test_anonymous_components_with_custom_paths_cant_be_rendered_as_
             $view = View::make('panel')->render();
         }
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app['config']->set('view.paths', [__DIR__.'/anonymous-components-templates']);
         }
    
  • tests/Integration/View/BladeTest.php+1 1 modified
    @@ -210,7 +210,7 @@ public function testViewCacheCommandHandlesConfiguredBladeExtensions()
             $this->artisan('view:clear');
         }
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app['config']->set('view.paths', [__DIR__.'/templates']);
         }
    
  • tests/Integration/View/RenderableViewExceptionTest.php+1 1 modified
    @@ -21,7 +21,7 @@ public function testRenderMethodOfExceptionThrownInViewGetsHandled()
             $response->assertSee('This is a renderable exception.');
         }
     
    -    protected function getEnvironmentSetUp($app)
    +    protected function defineEnvironment($app)
         {
             $app['config']->set('view.paths', [__DIR__.'/templates']);
         }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.