Merge branch 'develop' into feature/media

This commit is contained in:
Djamil Legato
2022-03-03 10:26:29 -08:00
8 changed files with 47 additions and 6 deletions

View File

@@ -11,11 +11,15 @@
1. [](#new)
* Added support to get image size for SVG vector images [#3533](https://github.com/getgrav/grav/pull/3533)
* Added XSS check for uploaded SVG files before they get stored
* Fixed phpstan issues (All level 2, Framework level 5)
2. [](#bugfix)
* Fixed `'mbstring' extension is not loaded` error, use Polyfill instead [#3504](https://github.com/getgrav/grav/pull/3504)
* Fixed new `Utils::pathinfo()` and `Utils::basename()` being too strict for legacy use [#3542](https://github.com/getgrav/grav/issues/3542)
* Fixed non-standard video html atributes generated by `{{ media.html() }}` [#3540](https://github.com/getgrav/grav/issues/3540)
* Fixed entity sanitization for XSS detection
* Fixed avatar save location when `account://` stream points to custom directory
* Fixed bug in `Utils::url()` when path contains root
# v1.7.30
## 02/07/2022

View File

@@ -11,7 +11,7 @@ form:
avatar:
type: file
size: large
destination: 'user://accounts/avatars'
destination: 'account://avatars'
multiple: false
random_name: true

View File

@@ -666,7 +666,7 @@ class UserObject extends FlexObject implements UserInterface, Countable
// Check for shared media
if (!$folder && !$this->getFlexDirectory()->getMediaFolder()) {
$this->_loadMedia = false;
$folder = $this->getBlueprint()->fields()['avatar']['destination'] ?? 'user://accounts/avatars';
$folder = $this->getBlueprint()->fields()['avatar']['destination'] ?? 'account://avatars';
}
return $folder;

View File

@@ -100,6 +100,10 @@ trait MediaUploadTrait
'size' => $uploadedFile->getSize(),
];
if ($uploadedFile instanceof FormFlashFile) {
$uploadedFile->checkXss();
}
return $this->checkFileMetadata($metadata, $filename, $settings);
}

View File

@@ -25,6 +25,22 @@ use function is_string;
*/
class Security
{
/**
* @param string $filepath
* @param array|null $options
* @return string|null
*/
public static function detectXssFromSvgFile(string $filepath, array $options = null): ?string
{
if (file_exists($filepath) && Grav::instance()['config']->get('security.sanitize_svg')) {
$content = file_get_contents($filepath);
return static::detectXss($content, $options);
}
return null;
}
/**
* Sanitize SVG string for XSS code
*
@@ -200,7 +216,7 @@ class Security
}, $string);
// Clean up entities
$string = preg_replace('!(&#0+[0-9]+)!u', '$1;', $string);
$string = preg_replace('!(&#[0-9]+);?!u', '$1;', $string);
// Decode entities
$string = html_entity_decode($string, ENT_NOQUOTES | ENT_HTML5, 'UTF-8');

View File

@@ -193,7 +193,7 @@ class User extends Data implements UserInterface
*/
public function getMediaFolder()
{
return $this->blueprints()->fields()['avatar']['destination'] ?? 'user://accounts/avatars';
return $this->blueprints()->fields()['avatar']['destination'] ?? 'account://avatars';
}
/**

View File

@@ -134,10 +134,10 @@ abstract class Utils
$resource = $locator->findResource($input, false);
}
} else {
$root = $uri->rootUrl();
$root = $uri->rootUrl() . '/';
if (static::startsWith($input, $root)) {
$input = static::replaceFirstOccurrence($root, '', $input);
$input = static::replaceFirstOccurrence($root, '/', $input);
}
$input = ltrim($input, '/');

View File

@@ -9,6 +9,8 @@
namespace Grav\Framework\Form;
use Grav\Common\Security;
use Grav\Common\Utils;
use Grav\Framework\Psr7\Stream;
use InvalidArgumentException;
use JsonSerializable;
@@ -182,6 +184,21 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
return $this->upload;
}
/**
* @return void
*/
public function checkXss(): void
{
$tmpFile = $this->getTmpFile();
$mime = $this->getClientMediaType();
if (Utils::contains($mime, 'svg', false)) {
$response = Security::detectXssFromSvgFile($tmpFile);
if ($response) {
throw new RuntimeException(sprintf('SVG file XSS check failed on %s', $response));
}
}
}
/**
* @return string|null
*/