Block Phar Only

This commit is contained in:
oleibman
2026-05-23 19:47:24 -07:00
parent b9ec538e72
commit 2b89a7bb7a
4 changed files with 29 additions and 7 deletions
+6 -2
View File
@@ -143,9 +143,13 @@ class File
*/
public static function prohibitWrappers(string $filename): void
{
if (str_contains($filename, '://')) {
if (
preg_match('~^phar://~i', $filename)
|| (preg_match('/^([\w\s\x00-\x1f]+):/u', $filename) && !preg_match('/^([\w]+):/u', $filename))
|| preg_match('~^php://.*phar:~i', $filename)
) {
throw new Exception(
"Stream wrappers are not permitted as file paths: {$filename}"
"Disallowed stream wrapper used for {$filename}"
);
}
}
+5 -1
View File
@@ -117,7 +117,11 @@ class Drawing extends BaseDrawing
}
}
// Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979
} elseif (filter_var($path, FILTER_VALIDATE_URL) || str_contains($path, '://') || (preg_match('/^([\w\s\x00-\x1f]+):/u', $path) && !preg_match('/^([\w]+):/u', $path))) {
} elseif (
filter_var($path, FILTER_VALIDATE_URL)
|| preg_match('~^phar://~i', $path)
|| (preg_match('/^([\w\s\x00-\x1f]+):/u', $path) && !preg_match('/^([\w]+):/u', $path))
) {
if (!Preg::isMatch('/^(http|https|file|ftp|s3):/', $path)) {
throw new PhpSpreadsheetException('Invalid protocol for linked drawing');
}
@@ -157,8 +157,10 @@ class HtmlImage2Test extends TestCase
'mailto' => ['mailto:xyz@example.com'],
'mailto whitespace' => ['mail to:xyz@example.com'],
'phar' => ['phar://example.com/image.phar'],
'phar mixed case' => ['Phar://example.com/image.phar'],
'phar with 3 slashes' => ['phar:///example.com/image.phar'],
'phar control' => ["\x14phar://example.com/image.phar"],
'filter with phar' => ['php://filter/read=convert.base64-encode/resource=phar:///tmp/x.Phar'],
];
}
}
@@ -19,7 +19,7 @@ class NoPharTest extends TestCase
public function testNoPhar(string $reader): void
{
$this->expectException(SpreadsheetException::class);
$this->expectExceptionMessage('Stream wrappers are not permitted');
$this->expectExceptionMessage('Disallowed stream wrapper');
$reader = new $reader();
$reader->load('phar://anyoldname');
}
@@ -30,10 +30,22 @@ class NoPharTest extends TestCase
#[DataProvider('providerReaders')]
public function testPhar3Slashes(string $reader): void
{
$this->expectException(SpreadsheetException::class);
$this->expectExceptionMessage('Stream wrappers are not permitted');
$invalidProtocol = [
'3 slashes' => 'phar:///anyoldname',
'mixed case' => 'Phar:///anyoldname',
'embedded space' => 'ph ar://anyoldname',
'embedded control character' => "ph\x04ar://anyoldname",
'filter with phar' => 'php://filter/read=convert.base64-encode/resource=phar:///tmp/x.Phar',
];
$reader = new $reader();
$reader->load('phar:///anyoldname');
foreach ($invalidProtocol as $key => $value) {
try {
$reader->load($value);
self::fail("Should have thrown exception - $key");
} catch (SpreadsheetException $e) {
self::assertStringContainsString('Disallowed stream wrapper', $e->getMessage(), $key);
}
}
}
/**