Trusted Types와 CSP로 DOM XSS 경계를 좁히기
Trusted Types 객체는 정책 변환을 거친 값을 표시하고, 실제 문자열 차단은 지원 브라우저에서 CSP enforcement를 설정해야 합니다.
발행·오류 제보: infostoa · 편집 기준
이 글의 개별 작성자와 전문 검토자 정보는 제공되지 않습니다.
Trusted Types를 만든다고 모든 DOM 문자열이 자동 차단되는 것은 아닙니다. 적용 브라우저가 CSP require-trusted-types-for 'script'를 enforcement로 받으면 지정된 injection sink에서 일반 문자열을 거부하고 Trusted Types 객체를 요구할 수 있습니다. Trusted Types 명세와 CSP Level 3가 정책 모델을 정의하며, web.dev 전문 가이드가 도입 과정을 설명합니다.
개념도이며 실제 보안 테스트나 UI 캡처가 아닙니다.
타입과 sink의 관계
TrustedHTML은 HTML을 받는 sink, TrustedScript는 특정 script sink, TrustedScriptURL은 script URL sink에 쓰는 타입입니다. 'script'라는 CSP 값이 모든 DOM 메서드를 막는다는 뜻은 아닙니다. 어떤 sink가 적용 대상인지 명세와 대상 브라우저에서 확인해야 합니다. 일반 텍스트를 표시할 때는 textContent처럼 HTML 해석이 필요 없는 API를 우선합니다.
정책 이름은 안전 인증서가 아니다
trustedTypes.createPolicy는 개발자가 변환 함수를 제공하도록 합니다. 브라우저는 그 함수가 실제로 안전한 정제를 하는지 검증하지 않습니다. 정책이 입력을 그대로 반환하면 TrustedHTML로 감쌌다는 사실만으로 XSS가 해결되지 않습니다. HTML 정제에는 검토된 sanitizer를 사용하고, 허용 태그·속성·URL 정책을 용도에 맞게 제한합니다.
CSP enforcement와 report-only
require-trusted-types-for는 sink에서 타입을 요구하는 시행 지시문입니다. trusted-types 지시문은 만들 수 있는 정책 이름을 제한합니다. report-only는 위반 관찰을 위한 모드이므로 실제 입력을 차단한다고 간주하지 마세요. 먼저 보고를 수집해 레거시 sink를 파악하고, 정책·sanitizer·브라우저 호환성을 시험한 뒤 enforcement로 전환합니다.
다른 방어와 함께 적용
Trusted Types는 DOM XSS 공격면을 줄이는 한 계층이며 입력 검증, 출력 문맥 인코딩, 안전한 DOM API, CSP의 다른 지시문을 대체하지 않습니다. 미지원 브라우저에서는 enforcement가 같은 방식으로 동작한다고 가정할 수 없습니다. 중요한 sink와 정책 생성 지점을 중앙에서 검토하고, 허용 목록이 필요 이상으로 넓어지지 않게 유지하세요.
기존 코드에 단계적으로 적용
먼저 report-only나 비강제 관찰로 어떤 sink가 일반 문자열을 전달하는지 수집하고, 호출 경로별로 사용자 입력·서버 데이터·신뢰된 템플릿을 구분합니다. 타입을 적용할 경계마다 정책 함수가 실제 sanitizer를 호출하는지 테스트하고, 정책 생성 이름은 CSP 허용 목록으로 제한합니다. default policy를 두면 누락된 호출을 관찰하거나 호환을 돕는 데 쓸 수 있지만, 광범위하게 문자열을 통과시키면 enforcement의 목적을 약화합니다.
enforcement 전환 뒤에는 지원 브라우저와 기존 브라우저를 모두 점검하고, 차단된 sink가 사용자 기능을 깨는지 확인해야 합니다. 정책을 추가할 때마다 모든 입력이 안전해졌다고 표시하지 말고 변환의 허용 범위, URL scheme, 오류 동작을 리뷰하세요. 브라우저가 거부한 입력을 무조건 안전한 대체 HTML로 재시도하는 코드는 새로운 우회점이 될 수 있습니다.