SecurityFileUploadEventSubscriberTest.php
Same filename in other branches
Namespace
Drupal\Tests\system\Unit\EventFile
-
core/
modules/ system/ tests/ src/ Unit/ Event/ SecurityFileUploadEventSubscriberTest.php
View source
<?php
declare (strict_types=1);
namespace Drupal\Tests\system\Unit\Event;
use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
use Drupal\system\EventSubscriber\SecurityFileUploadEventSubscriber;
use Drupal\Tests\UnitTestCase;
/**
* SecurityFileUploadEventSubscriber tests.
*
* @group system
* @coversDefaultClass \Drupal\system\EventSubscriber\SecurityFileUploadEventSubscriber
*/
class SecurityFileUploadEventSubscriberTest extends UnitTestCase {
/**
* Tests file name sanitization.
*
* @param string $filename
* The original filename.
* @param string $allowed_extensions
* The allowed extensions.
* @param string $expected_filename
* The expected filename if 'allow_insecure_uploads' is set to FALSE.
* @param string|null $expected_filename_with_insecure_uploads
* The expected filename if 'allow_insecure_uploads' is set to TRUE.
*
* @dataProvider provideFilenames
*
* @covers ::sanitizeName
*/
public function testSanitizeName(string $filename, string $allowed_extensions, string $expected_filename, ?string $expected_filename_with_insecure_uploads = NULL) : void {
// Configure insecure uploads to be renamed.
$config_factory = $this->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => FALSE,
],
]);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber->sanitizeName($event);
// Check the results of the configured sanitization.
$this->assertSame($expected_filename, $event->getFilename());
$this->assertSame($expected_filename !== $filename, $event->isSecurityRename());
// Rerun the event allowing insecure uploads.
$config_factory = $this->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => TRUE,
],
]);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber->sanitizeName($event);
// Check the results of the configured sanitization.
$expected_filename_with_insecure_uploads = $expected_filename_with_insecure_uploads ?? $expected_filename;
$this->assertSame($expected_filename_with_insecure_uploads, $event->getFilename());
$this->assertSame($expected_filename_with_insecure_uploads !== $filename, $event->isSecurityRename());
}
/**
* Provides data for testSanitizeName().
*
* @return array
* Arrays with original name, allowed extensions, expected name and
* (optional) expected name 'allow_insecure_uploads' is set to TRUE.
*/
public static function provideFilenames() {
return [
'All extensions allowed filename not munged' => [
'foo.txt',
'',
'foo.txt',
],
'All extensions allowed with .php file' => [
'foo.php',
'',
'foo.php_.txt',
'foo.php',
],
'All extensions allowed with .pHp file' => [
'foo.pHp',
'',
'foo.pHp_.txt',
'foo.pHp',
],
'All extensions allowed with .PHP file' => [
'foo.PHP',
'',
'foo.PHP_.txt',
'foo.PHP',
],
'.php extension allowed with .php file' => [
'foo.php',
'php',
'foo.php',
'foo.php',
],
'.PhP extension allowed with .php file' => [
'foo.php',
'PhP',
'foo.php',
'foo.php',
],
'.php, .txt extension allowed with .php file' => [
'foo.php',
'php txt',
'foo.php_.txt',
'foo.php',
],
'.PhP, .tXt extension allowed with .php file' => [
'foo.php',
'PhP tXt',
'foo.php_.txt',
'foo.php',
],
'no extension produces no errors' => [
'foo',
'',
'foo',
],
'filename is munged' => [
'foo.phar.png.php.jpg',
'jpg png',
'foo.phar_.png_.php_.jpg',
],
'filename is munged regardless of case' => [
'FOO.pHAR.PNG.PhP.jpg',
'jpg png',
'FOO.pHAR_.PNG_.PhP_.jpg',
],
'null bytes are removed' => [
'foo' . chr(0) . '.txt' . chr(0),
'',
'foo.txt',
],
'dot files are renamed' => [
'.git',
'',
'git',
],
'htaccess files are renamed even if allowed' => [
'.htaccess',
'htaccess txt',
'.htaccess_.txt',
'.htaccess',
],
'.phtml extension allowed with .phtml file' => [
'foo.phtml',
'phtml',
'foo.phtml',
],
'.phtml, .txt extension allowed with .phtml file' => [
'foo.phtml',
'phtml txt',
'foo.phtml_.txt',
'foo.phtml',
],
'All extensions allowed with .phtml file' => [
'foo.phtml',
'',
'foo.phtml_.txt',
'foo.phtml',
],
];
}
/**
* Tests file name sanitization without file munging.
*
* @param string $filename
* The original filename.
* @param string $allowed_extensions
* The allowed extensions.
*
* @dataProvider provideFilenamesNoMunge
*
* @covers ::sanitizeName
*/
public function testSanitizeNameNoMunge(string $filename, string $allowed_extensions) : void {
$config_factory = $this->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => FALSE,
],
]);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber->sanitizeName($event);
// Check the results of the configured sanitization.
$this->assertSame($filename, $event->getFilename());
$this->assertFalse($event->isSecurityRename());
$config_factory = $this->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => TRUE,
],
]);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$subscriber->sanitizeName($event);
// Check the results of the configured sanitization.
$this->assertSame($filename, $event->getFilename());
$this->assertFalse($event->isSecurityRename());
}
/**
* Provides data for testSanitizeNameNoMunge().
*
* @return array
* Arrays with original name and allowed extensions.
*/
public static function provideFilenamesNoMunge() {
return [
// The following filename would be rejected by 'FileExtension' constraint
// and therefore remains unchanged.
'.php is not munged when it would be rejected' => [
'foo.php.php',
'jpg',
],
'.php is not munged when it would be rejected and filename contains null byte character' => [
'foo.' . chr(0) . 'php.php',
'jpg',
],
'extension less files are not munged when they would be rejected' => [
'foo',
'jpg',
],
'dot files are not munged when they would be rejected' => [
'.htaccess',
'jpg png',
],
];
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
SecurityFileUploadEventSubscriberTest | SecurityFileUploadEventSubscriber tests. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.