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/.