Aller au contenu

Assainir

phil/svg-sanitizer

Une image

SvgSanitizer::sanitize() prend le contenu d'un fichier .svg, ou un élément <svg> écrit en XML, et retourne un Sanitized :

$sanitized = $sanitizer->sanitize(file_get_contents($upload->getPathname()));

if ($sanitized->isRefused()) {
    // Nothing to store: the one removal says why.
}

file_put_contents($target, $sanitized->svg);
MembreSens
svgL'image : un élément <svg> dans l'espace de noms SVG, sans déclaration XML ; vide quand elle est refusée en entier
removalsChaque Removal, dans l'ordre de la source, jusqu'à Sanitized::MAX_REMOVALS (100)
omittedRemovalsLes retraits au-delà des 100 premiers, comptés mais non listés
isClean()Si rien n'a été retiré : l'image a été permise telle quelle
isRefused()Si l'image a été refusée en entier

La sortie est construite à partir d'un document vide : chaque élément de la source que permet la politique est recréé, avec les attributs que permet la politique et son texte ; tout le reste est laissé derrière. Les commentaires, la déclaration XML et le type de document sont omis sans retrait signalé. Une image dont l'élément racine n'a pas d'espace de noms est lue comme du SVG et écrite dans l'espace de noms SVG, comme c'est souvent le cas d'un <svg> tiré d'une page HTML.

Un élément retiré emporte son contenu : le texte d'un <script>, les enfants d'un <metadata> ou d'un élément d'un autre espace de noms n'atteignent jamais la sortie.

Retraits

Une image de quelques mégaoctets peut contenir des centaines de milliers d'attributs à retirer : les 100 premiers retraits sont listés, dans l'ordre de la source, ceux de son CSS compris, et omittedRemovals compte les autres. Une image dont les retraits dépassent les 100 premiers n'est pas plus refusée qu'une image qui en a moins.

Un Removal contient une RemovalReason, un sujet — le nom de l'élément ou de l'attribut, l'adresse, ou l'attribut et le sujet CSS, coupé à 80 caractères — et la ligne de la source où commence son élément.

RaisonSujetCe qui est retiré
Elementmetadata, i:namedUn élément que la politique ne permet pas, ou un élément d'un autre espace de noms, avec son contenu
DeniedElementscriptUn élément qui exécute du code ou intègre un autre document, avec son contenu
Attributedata-x, xml:baseUn attribut que la politique ne permet pas, d'un autre espace de noms, ou avec un préfixe non déclaré
EventHandleronclickUn gestionnaire d'événements
ExternalReferenceother.svg#a, fill: http://x.test/pUn href ou un url() qui n'est pas un fragment
DangerousUrljavascript:alert(1)Une adresse dont le schéma exécute du code ou contient un document
Linkftp://x.test/Un lien dont la politique ne permet pas le schéma, ou un lien relatif
Animationset href, to: url(x)Une animation d'une référence, d'un style ou d'un gestionnaire, avec son élément ; une valeur d'animation qui contient une fonction ou un schéma
Stylestyle: positionDu CSS que la politique CSS a retiré, sous l'attribut ou l'élément qui le contenait
ProcessingInstructionxml-stylesheetUne instruction de traitement

Certaines raisons refusent l'image en entier : svg est vide, et le retrait est le seul. RemovalReason::refusesWhole() les distingue.

RaisonQuand
TooLargeL'image est plus grande que maxBytes
EntityDeclarationL'image déclare une entité
MalformedL'image n'est pas du XML bien formé en UTF-8, contient un octet nul, ou est vide
NotSvgL'élément racine n'est pas <svg>, dans l'espace de noms SVG ou dans aucun
TooManyElementsL'image contient plus de maxElements éléments, conservés ou non
TooManyAttributesUn élément contient plus de maxAttributes attributs, conservés ou non ; compté avant l'analyse de l'image
TooDeepLes éléments conservés s'imbriquent plus profondément que maxDepth

describe() donne chaque raison en quelques mots, pour un message :

foreach ($sanitized->removals as $removal) {
    $messages[] = sprintf('Line %d: %s (%s).', $removal->line, ucfirst($removal->reason->describe()), $removal->subject);
}