Laravel Framework XSS in Blade templating engine
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
Details
A security researcher has disclosed a possible XSS vulnerability in the Blade templating engine. Given the following two Blade templates: resources/views/parent.blade.php: ```html @section('content') <input value="{{ $value }}"> @show ``` resources/views/child.blade.php: ```html @extends('parent') @section('content') <input value="{{ $value }}"> @endsection ``` And a route like the following: ```php Route::get('/example', function() { $value = '//localhost/###parent-placeholder-040f06fd774092478d450774f5ba30c5da78acc8## onclick=location.assign(this.value);//'; return view('child', ['value' => $value]); }); ``` The broken HTML element may be clicked and the user is taken to another location in their browser due to XSS. This is due to the user being able to guess the parent placeholder SHA-1 hash by trying common names of sections. If the parent template contains an exploitable HTML structure an XSS vulnerability can be exposed. This vulnerability has been patched by determining the parent placeholder at runtime and using a random hash that is unique to each request.
The fix
adjust how parent replacements are made
src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php+3 −1
@@ -67,7 +67,9 @@ protected function compileSection($expression)*/protected function compileParent(){-return ViewFactory::parentPlaceholder($this->lastSection ?: '');+$escapedLastSection = str_replace("'", "\\'", $this->lastSection);++return "<?php echo \Illuminate\View\Factory::parentPlaceholder('{$escapedLastSection}'); ?>";}/**
src/Illuminate/View/Concerns/ManagesLayouts.php+16 −1
@@ -2,6 +2,7 @@namespace Illuminate\View\Concerns;+use Illuminate\Container\Container;use Illuminate\Contracts\View\View;use InvalidArgumentException;@@ -168,12 +169,26 @@ public function yieldContent($section, $default = '')public static function parentPlaceholder($section = ''){if (! isset(static::$parentPlaceholder[$section])) {-static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($section).'##';+$salt = static::parentPlaceholderSalt();++static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($salt.$section).'##';}return static::$parentPlaceholder[$section];}+/**+* Get the parent placeholder salt.+*+* @return string+*/+protected static function parentPlaceholderSalt()+{+$container = Container::getInstance();++return $container->bound('config') ? $container->make('config')->get('app.key', '') : '';+}+/*** Check if the section exists.*src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php | 2 --1 file changed, 2 deletions(-)
src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php+0 −2
@@ -2,8 +2,6 @@namespace Illuminate\View\Compilers\Concerns;-use Illuminate\View\Factory as ViewFactory;-trait CompilesLayouts{/**src/Illuminate/View/Concerns/ManagesLayouts.php | 15 ++++++++++++---1 file changed, 12 insertions(+), 3 deletions(-)
src/Illuminate/View/Concerns/ManagesLayouts.php+12 −3
@@ -2,8 +2,8 @@namespace Illuminate\View\Concerns;-use Illuminate\Container\Container;use Illuminate\Contracts\View\View;+use Illuminate\Support\Str;use InvalidArgumentException;trait ManagesLayouts@@ -29,6 +29,13 @@ trait ManagesLayouts*/protected static $parentPlaceholder = [];+/**+* The parent placeholder salt for the request.+*+* @var string+*/+protected static $parentPlaceholderSalt;+/*** Start injecting content into a section.*@@ -184,9 +191,11 @@ public static function parentPlaceholder($section = '')*/protected static function parentPlaceholderSalt(){-$container = Container::getInstance();+if (! static::$parentPlaceholderSalt) {+return static::$parentPlaceholderSalt = Str::random(40);+}-return $container->bound('config') ? $container->make('config')->get('app.key', '') : '';+return static::$parentPlaceholderSalt;}/**src/Illuminate/View/Compilers/Compiler.php | 2 +-1 file changed, 1 insertion(+), 1 deletion(-)
src/Illuminate/View/Compilers/Compiler.php+1 −1
@@ -48,7 +48,7 @@ public function __construct(Filesystem $files, $cachePath)*/public function getCompiledPath($path){-return $this->cachePath.'/'.sha1($path).'.php';+return $this->cachePath.'/'.sha1('v2'.$path).'.php';}/**tests/View/ViewBladeCompilerTest.php | 20 ++++++++++----------1 file changed, 10 insertions(+), 10 deletions(-)
tests/View/ViewBladeCompilerTest.php+10 −10
@@ -18,7 +18,7 @@ protected function tearDown(): voidpublic function testIsExpiredReturnsTrueIfCompiledFileDoesntExist(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);-$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(false);+$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('v2'.'foo').'.php')->andReturn(false);$this->assertTrue($compiler->isExpired('foo'));}@@ -33,16 +33,16 @@ public function testCannotConstructWithBadCachePath()public function testIsExpiredReturnsTrueWhenModificationTimesWarrant(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);-$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(true);+$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(true);$files->shouldReceive('lastModified')->once()->with('foo')->andReturn(100);-$files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(0);+$files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(0);$this->assertTrue($compiler->isExpired('foo'));}public function testCompilePathIsProperlyCreated(){$compiler = new BladeCompiler($this->getFiles(), __DIR__);-$this->assertEquals(__DIR__.'/'.sha1('foo').'.php', $compiler->getCompiledPath('foo'));+$this->assertEquals(__DIR__.'/'.sha1('v2foo').'.php', $compiler->getCompiledPath('foo'));}public function testCompileCompilesFileAndReturnsContents()@@ -50,7 +50,7 @@ public function testCompileCompilesFileAndReturnsContents()$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');$files->shouldReceive('exists')->once()->with(__DIR__)->andReturn(true);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');}@@ -60,7 +60,7 @@ public function testCompileCompilesFileAndReturnsContentsCreatingDirectory()$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');$files->shouldReceive('exists')->once()->with(__DIR__)->andReturn(false);$files->shouldReceive('makeDirectory')->once()->with(__DIR__, 0777, true, true);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');}@@ -69,7 +69,7 @@ public function testCompileCompilesAndGetThePath()$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');$files->shouldReceive('exists')->once()->with(__DIR__)->andReturn(true);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');$this->assertSame('foo', $compiler->getPath());}@@ -86,7 +86,7 @@ public function testCompileWithPathSetBefore()$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');$files->shouldReceive('exists')->once()->with(__DIR__)->andReturn(true);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');// set path before compilation$compiler->setPath('foo');// trigger compilation with $path@@ -117,7 +117,7 @@ public function testIncludePathToTemplate($content, $compiled)$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn($content);$files->shouldReceive('exists')->once()->with(__DIR__)->andReturn(true);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', $compiled);+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', $compiled);$compiler->compile('foo');}@@ -172,7 +172,7 @@ public function testDontIncludeEmptyPath()$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('')->andReturn('Hello World');$files->shouldReceive('exists')->once()->with(__DIR__)->andReturn(true);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('').'.php', 'Hello World');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2').'.php', 'Hello World');$compiler->setPath('');$compiler->compile();}src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php | 2 +-1 file changed, 1 insertion(+), 1 deletion(-)
src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php+1 −1
@@ -65,7 +65,7 @@ protected function compileSection($expression)*/protected function compileParent(){-$escapedLastSection = str_replace("'", "\\'", $this->lastSection);+$escapedLastSection = strtr($this->lastSection, ['\\' => '\\\\', "'" => "\\'"]);return "<?php echo \Illuminate\View\Factory::parentPlaceholder('{$escapedLastSection}'); ?>";}
Fix parent call
src/Illuminate/View/Compilers/Compiler.php+1 −1
@@ -48,7 +48,7 @@ public function __construct(Filesystem $files, $cachePath)*/public function getCompiledPath($path){-return $this->cachePath.'/'.sha1($path).'.php';+return $this->cachePath.'/'.sha1('v2'.$path).'.php';}/**
src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php+3 −3
@@ -2,8 +2,6 @@namespace Illuminate\View\Compilers\Concerns;-use Illuminate\View\Factory as ViewFactory;-trait CompilesLayouts{/**@@ -50,7 +48,9 @@ protected function compileSection($expression)*/protected function compileParent(){-return ViewFactory::parentPlaceholder($this->lastSection ?: '');+$escapedLastSection = strtr($this->lastSection, ['\\' => '\\\\', "'" => "\\'"]);++return "<?php echo \Illuminate\View\Factory::parentPlaceholder('{$escapedLastSection}'); ?>";}/**
src/Illuminate/View/Concerns/ManagesLayouts.php+26 −1
@@ -3,6 +3,7 @@namespace Illuminate\View\Concerns;use Illuminate\Contracts\View\View;+use Illuminate\Support\Str;use InvalidArgumentException;trait ManagesLayouts@@ -28,6 +29,13 @@ trait ManagesLayouts*/protected static $parentPlaceholder = [];+/**+* The parent placeholder salt for the request.+*+* @var string+*/+protected static $parentPlaceholderSalt;+/*** Start injecting content into a section.*@@ -168,12 +176,29 @@ public function yieldContent($section, $default = '')public static function parentPlaceholder($section = ''){if (! isset(static::$parentPlaceholder[$section])) {-static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($section).'##';+$salt = static::parentPlaceholderSalt();++static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($salt.$section).'##';}return static::$parentPlaceholder[$section];}++/**+* Get the parent placeholder salt.+*+* @return string+*/+protected static function parentPlaceholderSalt()+{+if (! static::$parentPlaceholderSalt) {+return static::$parentPlaceholderSalt = Str::random(40);+}++return static::$parentPlaceholderSalt;+}+/*** Check if section exists.*
tests/View/ViewBladeCompilerTest.php+10 −10
@@ -18,7 +18,7 @@ protected function tearDown(): voidpublic function testIsExpiredReturnsTrueIfCompiledFileDoesntExist(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);-$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(false);+$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(false);$this->assertTrue($compiler->isExpired('foo'));}@@ -33,23 +33,23 @@ public function testCannotConstructWithBadCachePath()public function testIsExpiredReturnsTrueWhenModificationTimesWarrant(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);-$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(true);+$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(true);$files->shouldReceive('lastModified')->once()->with('foo')->andReturn(100);-$files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(0);+$files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(0);$this->assertTrue($compiler->isExpired('foo'));}public function testCompilePathIsProperlyCreated(){$compiler = new BladeCompiler($this->getFiles(), __DIR__);-$this->assertEquals(__DIR__.'/'.sha1('foo').'.php', $compiler->getCompiledPath('foo'));+$this->assertEquals(__DIR__.'/'.sha1('v2foo').'.php', $compiler->getCompiledPath('foo'));}public function testCompileCompilesFileAndReturnsContents(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');}@@ -57,7 +57,7 @@ public function testCompileCompilesAndGetThePath(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');$this->assertSame('foo', $compiler->getPath());}@@ -73,7 +73,7 @@ public function testCompileWithPathSetBefore(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');// set path before compilation$compiler->setPath('foo');// trigger compilation with $path@@ -103,7 +103,7 @@ public function testIncludePathToTemplate($content, $compiled){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn($content);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', $compiled);+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', $compiled);$compiler->compile('foo');}@@ -157,7 +157,7 @@ public function testDontIncludeEmptyPath(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('').'.php', 'Hello World');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2').'.php', 'Hello World');$compiler->setPath('');$compiler->compile();}@@ -166,7 +166,7 @@ public function testDontIncludeNullPath(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with(null)->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1(null).'.php', 'Hello World');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2').'.php', 'Hello World');$compiler->setPath(null);$compiler->compile();}src/Illuminate/View/Concerns/ManagesLayouts.php | 1 -1 file changed, 1 deletion(-)
src/Illuminate/View/Concerns/ManagesLayouts.php+0 −1
@@ -184,7 +184,6 @@ public static function parentPlaceholder($section = '')return static::$parentPlaceholder[$section];}-/*** Get the parent placeholder salt.*
CS fixes
.styleci.yml+1 −0
@@ -1,5 +1,6 @@php:preset: laravel+version: 8.0js:finder:not-name:
src/Illuminate/Support/Collection.php+1 −1
@@ -808,7 +808,7 @@ public function prepend($value, $key = null)/*** Push one or more items onto the end of the collection.*-* @param mixed $values [optional]+* @param mixed $values* @return $this*/public function push(...$values)
tests/Database/DatabaseEloquentCollectionTest.php+14 −11
@@ -465,19 +465,22 @@ public function testQueueableCollectionImplementationThrowsExceptionOnMultipleMopublic function testQueueableRelationshipsReturnsOnlyRelationsCommonToAllModels(){// This is needed to prevent loading non-existing relationships on polymorphic model collections (#26126)-$c = new Collection([new class-{-public function getQueueableRelations()+$c = new Collection([+new class{-return ['user'];-}-}, new class-{-public function getQueueableRelations()+public function getQueueableRelations()+{+return ['user'];+}+},+new class{-return ['user', 'comments'];-}-}, ]);+public function getQueueableRelations()+{+return ['user', 'comments'];+}+},+]);$this->assertEquals(['user'], $c->getQueueableRelations());}src/Illuminate/View/Compilers/Compiler.php | 2 +-.../Compilers/Concerns/CompilesLayouts.php | 6 ++---.../View/Concerns/ManagesLayouts.php | 26 ++++++++++++++++++-tests/View/ViewBladeCompilerTest.php | 20 +++++++-------4 files changed, 39 insertions(+), 15 deletions(-)
src/Illuminate/View/Compilers/Compiler.php+1 −1
@@ -48,7 +48,7 @@ public function __construct(Filesystem $files, $cachePath)*/public function getCompiledPath($path){-return $this->cachePath.'/'.sha1($path).'.php';+return $this->cachePath.'/'.sha1('v2'.$path).'.php';}/**
src/Illuminate/View/Compilers/Concerns/CompilesLayouts.php+3 −3
@@ -2,8 +2,6 @@namespace Illuminate\View\Compilers\Concerns;-use Illuminate\View\Factory as ViewFactory;-trait CompilesLayouts{/**@@ -50,7 +48,9 @@ protected function compileSection($expression)*/protected function compileParent(){-return ViewFactory::parentPlaceholder($this->lastSection ?: '');+$escapedLastSection = strtr($this->lastSection, ['\\' => '\\\\', "'" => "\\'"]);++return "<?php echo \Illuminate\View\Factory::parentPlaceholder('{$escapedLastSection}'); ?>";}/**
src/Illuminate/View/Concerns/ManagesLayouts.php+25 −1
@@ -3,6 +3,7 @@namespace Illuminate\View\Concerns;use Illuminate\Contracts\View\View;+use Illuminate\Support\Str;use InvalidArgumentException;trait ManagesLayouts@@ -28,6 +29,13 @@ trait ManagesLayouts*/protected static $parentPlaceholder = [];+/**+* The parent placeholder salt for the request.+*+* @var string+*/+protected static $parentPlaceholderSalt;+/*** Start injecting content into a section.*@@ -168,12 +176,28 @@ public function yieldContent($section, $default = '')public static function parentPlaceholder($section = ''){if (! isset(static::$parentPlaceholder[$section])) {-static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($section).'##';+$salt = static::parentPlaceholderSalt();++static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($salt.$section).'##';}return static::$parentPlaceholder[$section];}+/**+* Get the parent placeholder salt.+*+* @return string+*/+protected static function parentPlaceholderSalt()+{+if (! static::$parentPlaceholderSalt) {+return static::$parentPlaceholderSalt = Str::random(40);+}++return static::$parentPlaceholderSalt;+}+/*** Check if section exists.*
tests/View/ViewBladeCompilerTest.php+10 −10
@@ -18,7 +18,7 @@ protected function tearDown(): voidpublic function testIsExpiredReturnsTrueIfCompiledFileDoesntExist(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);-$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(false);+$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(false);$this->assertTrue($compiler->isExpired('foo'));}@@ -33,23 +33,23 @@ public function testCannotConstructWithBadCachePath()public function testIsExpiredReturnsTrueWhenModificationTimesWarrant(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);-$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(true);+$files->shouldReceive('exists')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(true);$files->shouldReceive('lastModified')->once()->with('foo')->andReturn(100);-$files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.sha1('foo').'.php')->andReturn(0);+$files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.sha1('v2foo').'.php')->andReturn(0);$this->assertTrue($compiler->isExpired('foo'));}public function testCompilePathIsProperlyCreated(){$compiler = new BladeCompiler($this->getFiles(), __DIR__);-$this->assertEquals(__DIR__.'/'.sha1('foo').'.php', $compiler->getCompiledPath('foo'));+$this->assertEquals(__DIR__.'/'.sha1('v2foo').'.php', $compiler->getCompiledPath('foo'));}public function testCompileCompilesFileAndReturnsContents(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');}@@ -57,7 +57,7 @@ public function testCompileCompilesAndGetThePath(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');$compiler->compile('foo');$this->assertSame('foo', $compiler->getPath());}@@ -73,7 +73,7 @@ public function testCompileWithPathSetBefore(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', 'Hello World<?php /**PATH foo ENDPATH**/ ?>');// set path before compilation$compiler->setPath('foo');// trigger compilation with $path@@ -103,7 +103,7 @@ public function testIncludePathToTemplate($content, $compiled){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('foo')->andReturn($content);-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('foo').'.php', $compiled);+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2foo').'.php', $compiled);$compiler->compile('foo');}@@ -157,7 +157,7 @@ public function testDontIncludeEmptyPath(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with('')->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('').'.php', 'Hello World');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2').'.php', 'Hello World');$compiler->setPath('');$compiler->compile();}@@ -166,7 +166,7 @@ public function testDontIncludeNullPath(){$compiler = new BladeCompiler($files = $this->getFiles(), __DIR__);$files->shouldReceive('get')->once()->with(null)->andReturn('Hello World');-$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1(null).'.php', 'Hello World');+$files->shouldReceive('put')->once()->with(__DIR__.'/'.sha1('v2').'.php', 'Hello World');$compiler->setPath(null);$compiler->compile();}tests/Http/HttpMimeTypeTest.php | 2 +-1 file changed, 1 insertion(+), 1 deletion(-)
tests/Http/HttpMimeTypeTest.php+1 −1
@@ -35,7 +35,7 @@ public function testMimeTypeSymfonyInstance()public function testSearchExtensionFromMimeType(){-$this->assertSame('qt', MimeType::search('video/quicktime'));+$this->assertContains(MimeType::search('video/quicktime'), ['qt', 'mov']);$this->assertNull(MimeType::search('foo/bar'));}}
References
- WEBhttps://github.com/laravel/framework/security/advisories/GHSA-66hf-2p6w-jqfw
- ADVISORYhttps://nvd.nist.gov/vuln/detail/CVE-2021-43808
- WEBhttps://github.com/laravel/framework/pull/39906
- WEBhttps://github.com/laravel/framework/pull/39908
- WEBhttps://github.com/laravel/framework/pull/39909
- WEBhttps://github.com/laravel/framework/commit/b8174169b1807f36de1837751599e2828ceddb9b
- WEBhttps://github.com/FriendsOfPHP/security-advisories/blob/master/illuminate/view/CVE-2021-43808.yaml
- WEBhttps://github.com/FriendsOfPHP/security-advisories/blob/master/laravel/framework/CVE-2021-43808.yaml
- PACKAGEhttps://github.com/laravel/framework
- WEBhttps://github.com/laravel/framework/releases/tag/v6.20.42
- WEBhttps://github.com/laravel/framework/releases/tag/v7.30.6
- WEBhttps://github.com/laravel/framework/releases/tag/v8.75.0