Data publikacji: 12 czerwca 2025 r.
20 maja 2025 r. specyfikacja HTML została zaktualizowana, aby ucieczki < i > w atrybutach były traktowane jako ucieczki, co pomaga zapobiegać podatnościom na ataki mutacji XSS (mXSS). Ta zmiana została wprowadzona w Chrome 138, która 28 maja 2025 r. została przeniesiona do wersji beta, a 24 czerwca 2025 r. stanie się stabilną.
W tym poście opisujemy wpływ zmiany dotyczącą ucieczki atrybutów HTML na programistów i potencjalne problemy. Motywy bezpieczeństwa leżące u podstaw tej zmiany zostały opisane w powiązanym poście na blogu poświęconym bezpieczeństwu.
Co się zmieniło?
Załóżmy, że masz element <div>, którego atrybut data-content ma wartość "<u>hello</u>". Co się stanie, gdy przeczytasz div.outerHTML?
Wcześniej otrzymywano taki kod HTML:
<div data-content="<u>hello</u>"></div>
Po wprowadzeniu zmiany otrzymasz następujący kod HTML:
<div data-content="<u>hello</u>"></div>
Wcześniej ani <, ani > nie były ujęte w cudzysłowie w atrybutach. Obecnie oba te znaki są zawsze ujęte w znaki ucieczki.
Co się nie zmienia?
Zmiana dotyczy wyłącznie sposobu, w jaki fragmenty kodu HTML są konwertowane z powrotem na ciąg znaków podczas serializacji. Wpływ jest ograniczony do scenariuszy, w których uzyskuje się dostęp do właściwości innerHTML lub outerHTML, lub gdy wywoływana jest metoda getHTML() elementu. Te operacje wykorzystują istniejącą strukturę DOM i tworzą tekstową reprezentację HTML.
Ta zmiana nie wpływa na analizowanie kodu HTML. Weź pod uwagę ten kod HTML:
<div id="div1" data-content="<u>hello</u>"></div>
<div id="div2" data-content="<u>hello</u>"></div>
Oba div zostaną przeanalizowane dokładnie w ten sam sposób i w obu przypadkach funkcja div.dataset.content zwróci wartość "<u>hello</u>".
Co się nie zepsuje?
Jeśli do pobierania wartości atrybutów używasz dowolnego interfejsu DOM API, np. getAttribute, getAttributeNS, dataset lub attributes, zwróci on te same odkodowane wartości co wcześniej, w szczególności w przypadku atrybutów < i >.
Rozważ ten przykład, w którym wszystkie wiersze console.log będą rejestrowane w "<u>":
<div data-content="<u>"></div>
const div = document.querySelector("div");
// All of the following will log "<u>"
console.log(div.getAttribute("data-content"));
console.log(div.dataset.content);
console.log(div.attributes['data-content'].value);
Co może się zepsuć?
Pobieranie atrybutów za pomocą innerHTML i outerHTML
Jeśli do wyodrębniania wartości atrybutu używasz funkcji innerHTML lub outerHTML, Twój kod może przestać działać. Rozważ ten nieco zawiły przykład:
<div data-content="<u>"></div>
const div = document.querySelector("div");
const content = div.outerHTML.match(/"([^"]+)"/)[1];
console.log(content);
Po tej zmianie kod będzie działał inaczej. Wcześniej content byłoby równe "<u>", ale teraz jest to "<u>".
Pamiętaj, że analizowanie kodu HTML za pomocą wyrażeń regularnych nie jest zalecane. Jeśli chcesz pobrać wartość atrybutu, użyj interfejsów DOM opisanych w poprzednich sekcjach.
Testy kompleksowe
Jeśli masz potok CI/CD, w którym do generowania kodu HTML używasz Chromium, i masz napisane testy porównujące kod HTML ze statyczną wartością oczekiwaną, te testy mogą się nie uruchomić, jeśli jakikolwiek atrybut zawiera znaki < lub >.
Jest to oczekiwane uszkodzenie – musisz zaktualizować oczekiwaną wartość, tak aby wszystkie znaki < i > zostały odpowiednio zastąpione znakami < i >,.
Podsumowanie
W tym poście na blogu opisaliśmy zmianę w specyfikacji HTML, która spowoduje, że przeglądarki zaczną stosować znak ucieczki < i > w atrybutach, aby zwiększyć bezpieczeństwo poprzez zapobieganie niektórym przypadkom mutacji XSS.
Ta zmiana będzie dostępna dla wszystkich użytkowników 24 czerwca 2025 r. w przeglądarce Chromium (w wersji 138) i Firefoksie (w wersji 140). Jest ona też dostępna w wersji beta Safari 26, która powinna zostać wydana we wrześniu 2025 r.
Jeśli uważasz, że ta zmiana spowodowała problemy z Twoją witryną i nie wiesz, jak je łatwo rozwiązać, zgłoś błąd na stronie https://issues.chromium.org/.