프로그래밍/HTML, Javascript, CSS

Trusted Types 적용 기준 정리

포도알77 2026. 6. 17. 11:54

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.

Trusted Types 적용 기준 정리

innerHTML, document.write(), eval() 같은 injection sink에 문자열이 바로 들어가면 DOM 기반 XSS로 이어질 수 있다. 2026년 6월 17일 기준 MDN과 W3C Trusted Types 초안 문서를 보면 Trusted Types는 이런 sink에 들어가는 값을 정책 기반 객체로 제한하고, CSP의 require-trusted-types-fortrusted-types 지시어로 강제할 수 있다.

실무에서 중요한 판단은 세 가지다. 지금 애플리케이션이 문자열 기반 DOM 조작을 얼마나 많이 쓰는지, sanitizer나 템플릿 계층을 어디에 둘지, 그리고 바로 강제 모드로 갈지 report-only로 위반 지점을 먼저 수집할지다. 이 글은 최신 문서 기준으로 Trusted Types의 역할과 적용 순서를 짧게 정리한다.

Trusted Types는 무엇을 막으려는 기능일까?

MDN은 Trusted Types API를 "실행 가능성이 있는 브라우저 API에 값이 들어가기 전에 개발자가 지정한 변환 함수를 거치게 하는 방법"으로 설명한다. 핵심은 문자열을 그냥 sink에 넣지 않고, 정책이 만든 TrustedHTML, TrustedScript, TrustedScriptURL 객체만 통과시키는 데 있다.

이 방식은 서버 측 XSS를 막는 기능이 아니라 클라이언트 측 DOM XSS의 공격 표면을 줄이는 기능에 가깝다. web.dev 문서도 innerHTML, outerHTML, insertAdjacentHTML, eval, setTimeout, HTMLScriptElement.src 같은 위험한 sink를 직접 예로 든다.

어떤 타입이 있고 언제 쓰일까?

타입 대상 대표 예시
TrustedHTML HTML로 해석되는 sink innerHTML, document.write()
TrustedScript JavaScript로 해석되는 sink eval(), script text
TrustedScriptURL 스크립트 URL sink <script src>

MDN 문서에 따르면 개발자는 trustedTypes.createPolicy()로 정책을 만들고, 정책 함수 안에서 입력값을 정제하거나 허용 목록 검사를 수행한 뒤 적절한 trusted type 객체를 만든다. 즉 Trusted Types가 자동으로 안전한 값을 만들어 주는 것이 아니라, 어떤 입력을 안전하다고 볼지 기준을 애플리케이션이 직접 정의해야 한다.

CSP의 require-trusted-types-fortrusted-types는 무엇이 다를까?

W3C 초안은 두 지시어의 역할을 분리한다. require-trusted-types-for는 어떤 injection sink 그룹에 trusted type을 요구할지 정하는 강제 규칙이고, trusted-types는 어떤 정책 이름을 생성할 수 있는지 통제하는 규칙이다.

MDN도 같은 구조를 설명한다. JavaScript API만 도입하면 개발자가 우회해서 문자열을 다시 sink에 넣을 수 있으므로, 실제 강제는 CSP가 맡는다. 그래서 운영 기준으로는 "정책 코드 작성"과 "CSP 강제"를 별도 단계로 보는 편이 맞다.

바로 강제해야 할까, report-only부터 시작해야 할까?

대부분의 기존 서비스는 report-only부터 시작하는 편이 안전하다. web.dev는 먼저 Content-Security-Policy-Report-Only: require-trusted-types-for 'script' 형태로 위반을 수집하고, ReportingObserver 또는 securitypolicyviolation 이벤트로 어떤 코드가 문자열을 sink에 넣는지 확인하는 흐름을 제안한다.

이 접근이 필요한 이유는 코드베이스 안에 직접 작성한 코드뿐 아니라 서드파티 라이브러리, 오래된 위젯, 템플릿 헬퍼가 함께 섞여 있기 때문이다. 강제 모드부터 켜면 브라우저가 TypeError를 던져 화면 기능이 바로 깨질 수 있다.

 

 

정책은 어떻게 잡는 편이 무난할까?

HTML 조각이 꼭 필요한 곳이라면 일반적으로 sanitizer를 정책 안에 두는 방식이 먼저 검토된다. MDN은 HTML sink에 대해 보통 sanitize 함수를 사용한다고 설명하고, web.dev는 DOMPurify가 RETURN_TRUSTED_TYPE 옵션으로 TrustedHTML을 반환할 수 있다고 소개한다.

다만 "sanitizer를 한 번 넣었으니 끝"으로 보면 안 된다. web.dev도 sanitization 로직 자체에 결함이 있으면 여전히 DOM XSS가 남을 수 있다고 경고한다. 그래서 정책 함수는 애플리케이션에서 허용할 HTML 범위와 속성을 좁게 두는 쪽이 유리하다.

default policy는 기본값으로 써도 될까?

기본값으로 두기보다는 이행 단계에서만 제한적으로 쓰는 편이 맞다. W3C 초안은 이름이 default인 정책이 있으면 문자열이 sink로 들어갈 때 이를 암묵적으로 호출한다고 설명하지만, 규칙이 느슨한 default policy는 Trusted Types의 이점을 사실상 무력화할 수 있다고 함께 적고 있다.

web.dev 역시 default policy를 "마지막 수단"으로 다루고, 일반 정책으로 리팩터링하는 것을 우선하라고 권한다. 따라서 운영 기준으로는 default policy를 장기 구조로 삼기보다, 위반 구간을 찾고 옮겨 가는 과도기 장치로 보는 편이 안전하다.

어떤 서비스에서 먼저 도입할 가치가 클까?

상황 도입 우선순위 이유
사용자 입력을 DOM에 자주 렌더링하는 SPA 높음 문자열 기반 DOM 조작이 많아 DOM XSS 완화 효과가 큼
서드파티 위젯과 레거시 스크립트가 많은 앱 중간 효과는 크지만 위반 정리와 호환성 점검 비용이 큼
정적 사이트 + 최소한의 스크립트 낮음 공격 표면 자체가 작아 다른 보안 설정이 우선일 수 있음

MDN은 2026년 2월부터 최신 브라우저 기준 Baseline 2026으로 표시하지만, 동시에 구형 환경에서는 동작하지 않을 수 있다고 적는다. 따라서 브라우저 지원 범위가 넓은 서비스라면 기능 감지, 점진 적용, 폴리필 사용 여부를 같이 검토해야 한다.

자주 헷갈리는 질문

Q. Trusted Types만 켜면 XSS를 모두 막을 수 있을까?

아니다. Trusted Types는 DOM 기반 XSS 완화 수단이다. 서버 측 HTML 생성 단계의 XSS, 잘못된 sanitizer 규칙, 정책 내부의 허용 로직 오류까지 자동으로 해결해 주지는 않는다.

Q. 모든 프로젝트에 무조건 넣는 것이 좋을까?

그렇게 단정하기는 어렵다. 문자열 기반 DOM 조작이 거의 없고 프레임워크가 이미 안전한 렌더링 경로를 강하게 강제하는 프로젝트라면 체감 이익이 작을 수 있다. 반대로 레거시 JS와 직접적인 DOM 조작이 많은 앱은 도입 가치가 더 크다.

Q. 언제 enforcing 모드로 전환하는 것이 좋을까?

report-only에서 주요 위반이 정리되고, 필요한 정책 이름이 고정되고, 핵심 화면 회귀 테스트를 통과한 뒤가 일반적인 전환 시점이다. web.dev도 위반 수집 후 enforcing 헤더로 바꾸는 순서를 안내한다.

정리

Trusted Types는 위험한 DOM sink에 문자열이 바로 들어가는 경로를 줄이기 위한 브라우저 보안 장치다. 실무에서는 sanitizer나 허용 목록을 담은 정책을 먼저 만들고, require-trusted-types-for는 report-only로 시작한 뒤 위반을 정리하고 enforcing으로 옮기는 순서가 가장 무난하다.

2026년 6월 17일 기준 공개 문서를 보면 default policy는 과도기 도구로 보고, 장기적으로는 명시적 정책과 제한된 정책 이름 목록으로 수렴하는 방향이 권장된다. 즉 Trusted Types의 핵심은 "문자열 금지"보다 "어디서 어떤 규칙으로 안전한 값을 만들지 중앙화"에 있다.

참고 자료

반응형
페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사