45
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Signature;
|
||||
|
||||
/**
|
||||
* Nettoie le HTML d'un template avant enregistrement (sans dépendance au framework).
|
||||
*
|
||||
* Volontairement basé sur des expressions régulières et non sur DOMDocument :
|
||||
* un parseur HTML déplacerait les marqueurs {{#if}} placés entre deux <tr>,
|
||||
* ce qui casserait les templates.
|
||||
*
|
||||
* Défense en profondeur : les aperçus sont en plus affichés dans des iframes « sandbox ».
|
||||
*/
|
||||
final class TemplateSanitizer
|
||||
{
|
||||
/** Balises retirées avec leur contenu. */
|
||||
private const BLOCK_TAGS = ['script', 'iframe', 'object', 'embed', 'applet', 'form', 'noscript', 'template', 'svg', 'math'];
|
||||
|
||||
/** Balises orphelines retirées. */
|
||||
private const VOID_TAGS = ['base', 'meta', 'link', 'input', 'button', 'select', 'textarea', 'frame', 'frameset'];
|
||||
|
||||
public function clean(string $html): string
|
||||
{
|
||||
foreach (self::BLOCK_TAGS as $tag) {
|
||||
$html = preg_replace('#<'.$tag.'\b[^>]*>.*?</'.$tag.'\s*>#is', '', $html);
|
||||
$html = preg_replace('#<'.$tag.'\b[^>]*/?>#i', '', $html); // balise ouvrante sans fermeture
|
||||
}
|
||||
foreach (self::VOID_TAGS as $tag) {
|
||||
$html = preg_replace('#</?'.$tag.'\b[^>]*>#i', '', $html);
|
||||
}
|
||||
|
||||
// Gestionnaires d'événements : onclick=, onerror=…
|
||||
$html = preg_replace('#\s+on[a-z]+\s*=\s*("[^"]*"|\'[^\']*\'|[^\s>]+)#i', '', $html);
|
||||
|
||||
// URL dangereuses dans href / src / action / style url()
|
||||
$html = preg_replace_callback(
|
||||
'#\s(href|src|action|formaction|xlink:href|background)\s*=\s*("([^"]*)"|\'([^\']*)\'|([^\s>]+))#i',
|
||||
function (array $m) {
|
||||
$value = html_entity_decode($m[3] !== '' ? $m[3] : ($m[4] ?? $m[5] ?? ''), ENT_QUOTES | ENT_HTML5);
|
||||
$normalized = strtolower(preg_replace('/[\s\x00-\x1f]+/', '', $value));
|
||||
|
||||
return preg_match('#^(javascript|vbscript|data):#', $normalized) && ! str_starts_with($normalized, 'data:image/')
|
||||
? ''
|
||||
: $m[0];
|
||||
},
|
||||
$html,
|
||||
);
|
||||
$html = preg_replace('#expression\s*\(|javascript\s*:#i', '', $html);
|
||||
|
||||
return trim($html);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user