DOM XSS виникає повністю в браузері: JavaScript бере дані з контрольованого нападником джерела (location.hash, location.search, postMessage, відповідь API) і передає в небезпечний приймач (sink):
element.innerHTML = location.hash.slice(1); // HTML-приймач
script.src = params.get('widget'); // URL скрипта
setTimeout(userInput); // рядок як код
document.write(...); eval(...); new Function(...);
Сервер такої вразливості не бачить: шкідливе значення взагалі може не доходити до нього (фрагмент #... не надсилається на сервер). Знайти всі такі місця у великому застосунку й бібліотеках - важко.
Trusted Types змінюють правила гри: з увімкненою політикою небезпечні приймачі відмовляються приймати звичайні рядки. Їм потрібні спеціальні типізовані об'єкти (TrustedHTML, TrustedScript, TrustedScriptURL), які можна створити лише через зареєстровані політики.
Увімкнення - через CSP:
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app-sanitizer
Політика - єдине місце, де рядок стає «довіреним»:
const sanitizer = trustedTypes.createPolicy('app-sanitizer', {
createHTML: (input) => DOMPurify.sanitize(input),
});
element.innerHTML = sanitizer.createHTML(userHtml); // дозволено
element.innerHTML = userHtml; // TypeError - заблоковано
Що це дає:
- кількість місць для перевірки зменшується до кількох політик замість сотень присвоєнь
innerHTMLпо всьому коду; - порушення помітні: спроба записати рядок у приймач кидає помилку (і може звітувати через CSP);
- контроль над бібліотеками: директива
trusted-typesобмежує, які політики можна створювати, - стороння бібліотека не створить «свою» лазівку непомітно.
Впровадження:
Content-Security-Policy-Report-Only: require-trusted-types-for 'script'- зібрати всі місця, де рядки потрапляють у приймачі;- переписати їх на безпечні API (
textContent,setAttributeдля безпечних атрибутів) або пропустити через політику з санітизацією; - увімкнути блокування.
Обмеження:
- підтримка браузерами: Trusted Types давно є в Chromium, інші браузери додавали її пізніше - перед покладанням на них як на основний захист варто перевірити актуальну підтримку. Там, де Trusted Types немає, код має лишатися безпечним сам по собі;
- фреймворки (React, Vue) мають власний захист від XSS у шаблонах; Trusted Types закривають «аварійні виходи» на кшталт
dangerouslySetInnerHTML,v-htmlі прямої роботи з DOM.