Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
DOMPurify — DOMPurify - HTML, MathML 및 SVG를 위한 DOM 전용, 초고속, 매우 관대한 XSS 새니타이저. DOMPurify는 안전한 기본 설정으로 작동하지만, 다양한 구성 옵션과 훅을 제공합니다. 데모: | Kitploit
도구/GitHubGitHub/cure53/dompurify
Defensive ToolsStatic AnalysisCode AnalysisWeb SecurityLearning & EducationAPI Security
GitHubcure53/dompurify

DOMPurify

DOMPurify - HTML, MathML 및 SVG를 위한 DOM 전용, 초고속, 매우 관대한 XSS 새니타이저. DOMPurify는 안전한 기본 설정으로 작동하지만, 다양한 구성 옵션과 훅을 제공합니다. 데모:

저장소 보기
17.3k8601693일 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
웹사이트
# DOMPurify

[![npm](https://img.shields.io/npm/v/dompurify.svg)](https://www.npmjs.com/package/dompurify) [![License](https://img.shields.io/badge/license-MPL--2.0%20OR%20Apache--2.0-blue.svg)](https://github.com/cure53/DOMPurify/blob/main/LICENSE) [![Downloads](https://img.shields.io/npm/dm/dompurify.svg)](https://www.npmjs.com/package/dompurify) [![dependents](https://badgen.net/github/dependents-repo/cure53/dompurify?color=green&label=dependents)](https://github.com/cure53/DOMPurify/network/dependents) ![npm package minimized gzipped size (select exports)](https://img.shields.io/bundlejs/size/dompurify?color=%233C1&label=gzip) [![Cloudback](https://app.cloudback.it/badge/cure53/DOMPurify)](https://cloudback.it)

[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/12162/badge)](https://www.bestpractices.dev/projects/12162) [![Build & Test](https://github.com/cure53/DOMPurify/actions/workflows/build-and-test.yml/badge.svg?branch=main)](https://github.com/cure53/DOMPurify/actions/workflows/build-and-test.yml) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/cure53/DOMPurify/badge)](https://scorecard.dev/viewer/?uri=github.com/cure53/DOMPurify) [![Socket Badge](https://badge.socket.dev/npm/package/dompurify/latest)](https://badge.socket.dev/npm/package/dompurify/latest) [![snyk.io package health](https://img.shields.io/badge/snyk.io%20package%20health-97/100-brightgreen)](https://security.snyk.io/package/npm/dompurify)

DOMPurify는 HTML, MathML 및 SVG를 위한 DOM 전용의 초고속이며 매우 관대한 XSS 새니타이저입니다.

사용법과 시작 방법도 매우 간단합니다. DOMPurify는 [2014년 2월에 시작되었으며](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b), 그동안 **v3.4.17** 버전에 도달했습니다.

DOMPurify는 JavaScript로 실행되며 모든 최신 브라우저(Safari (10+), Opera (15+), Edge, Firefox 및 Chrome - 그리고 Blink, Gecko 또는 WebKit을 사용하는 거의 모든 것)에서 작동합니다. MSIE나 다른 레거시 브라우저에서도 깨지지 않습니다. 그저 아무것도 하지 않을 뿐입니다.

**참고로 [DOMPurify v2.5.9](https://github.com/cure53/DOMPurify/releases/tag/2.5.9)는 MSIE를 지원하는 최신 버전입니다. MSIE와 호환되는 중요한 보안 업데이트를 위해서는 [2.x 브랜치](https://github.com/cure53/DOMPurify/tree/2.x)를 사용하시기 바랍니다.**

당사의 자동화된 테스트는 매 푸시마다 현재 엔진(Ubuntu, macOS, Windows 전반의 Chromium, Firefox, WebKit)에서 9개의 브라우저/OS 조합을 커버하며, 별도의 매트릭스가 오래된 엔진 스냅샷(대략 Chromium 110, Firefox 108, WebKit 16.4로 약 3년 전)에서도 스위트를 재실행하여 구형 브라우저에서의 회귀도 잡아냅니다. 또한 [jsdom](https://github.com/jsdom/jsdom)에서 DOMPurify와 함께 Node.js v20, v22, v24, v25 및 v26을 실행합니다. 더 오래된 Node 버전도 작동하는 것으로 알려져 있지만, 뭐... 보장은 없습니다.

DOMPurify는 웹 공격과 XSS에 대한 방대한 배경 지식을 가진 보안 전문가들이 작성했습니다. 걱정하지 마세요. 자세한 내용은 [보안 목표 및 위협 모델](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model)도 읽어보시기 바랍니다. 꼭 읽어보세요. 정말로요. 그리고 잔혹한 세부 사항을 즐기신다면, [공격 클래스 및 우회 이력](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History) 페이지에서 DOMPurify가 방어하는 파서 변이, 네임스페이스, 클로버링 및 템플릿 트릭을 정리해 두었습니다.

DOMPurify 프로젝트는 [HTML Sanitizer API](https://wicg.github.io/sanitizer-api/#sanitizer)의 탄생에 영감을 주었으며, 이는 이미 [많은 브라우저](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Sanitizer_API#browser_compatibility)에서 제공되고 있습니다. 동일한 기능이 이제 [WHATWG HTML 명세](https://html.spec.whatwg.org/#html-sanitization)에서 직접 표준화되고 있습니다.

## 목차

- [무엇을 하나요?](#what-does-it-do)
- [어떻게 사용하나요?](#how-do-i-use-it)
- [데모가 있나요?](#is-there-a-demo)
- [_보안_ 버그를 발견하면 어떻게 하나요?](#what-if-i-find-a-security-bug)
- [정화 샘플 몇 가지 보여주시겠어요?](#some-purification-samples-please)
- [무엇이 지원되나요?](#what-is-supported)
- [Internet Explorer와 같은 레거시 브라우저는 어떻게 하나요?](#what-about-legacy-browsers-like-internet-explorer)
- [DOMPurify와 Trusted Types는 어떻게 되나요?](#what-about-dompurify-and-trusted-types)
- [DOMPurify를 구성할 수 있나요?](#can-i-configure-dompurify)
- [영구 구성](#persistent-configuration)
- [훅](#hooks)
- [제거된 구성](#removed-configuration)
- [지속적 통합](#continuous-integration)
- [보안 메일링 리스트](#security-mailing-list)
- [누가 기여했나요?](#who-contributed)

## 무엇을 하나요?

DOMPurify는 HTML을 정화하고 XSS 공격을 방지합니다. 예를 들어 위험한 HTML로 가득 찬 문자열을 DOMPurify에 입력하면 깨끗한 HTML이 담긴 문자열을 반환합니다(별도로 구성하지 않는 한). DOMPurify는 위험한 HTML을 포함하는 모든 것을 제거하여 XSS 공격 및 기타 위험 요소를 방지합니다. 또한 굉장히 빠릅니다. 브라우저가 제공하는 기술을 활용하여 XSS 필터로 전환합니다. 브라우저가 빠를수록 DOMPurify도 더 빨라집니다.

## 어떻게 사용하나요?

간단합니다. 웹사이트에 DOMPurify를 포함하기만 하면 됩니다.

### 축소되지 않은 버전 사용 (source-map 사용 가능)

```html
<script type="text/javascript" src="dist/purify.js"></script>
```

### 축소되고 테스트된 프로덕션 버전 사용하기 (source-map 사용 가능)

```html
<script type="text/javascript" src="dist/purify.min.js"></script>
```

그런 다음 다음 코드를 실행하여 문자열을 정리할 수 있습니다:

```js
const clean = DOMPurify.sanitize(dirty);
```

또는 Angular 같은 것을 다루는 걸 좋아한다면 이렇게 할 수도 있습니다:

```js
import DOMPurify from 'dompurify';

const clean = DOMPurify.sanitize('<b>hello there</b>');
```

결과 HTML은 `innerHTML`을 사용하여 DOM 요소에 작성하거나 `document.write()`를 사용하여 DOM에 작성할 수 있습니다. 이는 전적으로 사용자에게 달려 있습니다.
기본적으로 HTML, SVG **그리고** MathML을 허용한다는 점에 유의하십시오. HTML만 필요한 경우(매우 일반적인 사용 사례일 수 있음) 다음과 같이 쉽게 설정할 수 있습니다:

```js
const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
```

### 함정이 될 가능성이 있나요?

음, 주의하세요. HTML을 _먼저_ 정리(sanitize)한 다음 _그 이후에_ 수정하면, **정리 효과를 무효화**하기 쉽습니다. 정리된 마크업을 정리 _후에_ 다른 라이브러리에 넘긴다면, 그 라이브러리가 자체적으로 HTML을 건드리지 않는지 반드시 확인하세요. 안전한 사용법과 두 번 생각해봐야 할 태그/속성에 대해서는 [보안 목표 및 위협 모델](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model)을, 후처리와 마크업 컨텍스트 변경이 왜 정리를 무력화하는지에 대해서는 [공격 클래스 및 우회 이력](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History)을 참고하세요.

### 문자열 대신 DOM 노드를 전달하면 어떻게 되나요?

`DOMPurify.sanitize()`는 DOM 노드(`Element`, `DocumentFragment` 또는 `Document`)도 받아들입니다. 3.4.14부터 이 경로는 HTML 파서에서 나오지 않은 노드에 대해 강화되었습니다. DOM API로 만들었거나 XML/XHTML로 파싱된 노드(예: `application/xhtml+xml`과 `importNode()`를 사용하는 `DOMParser`를 통해)는 `ONERROR`처럼 대소문자가 보존된 속성 이름을 가질 수 있고, 또는 `<style>` 같은 rawtext 요소가 텍스트 안에 자식 요소나 자체 종료 태그를 가질 수 있습니다. 두 형태 모두 HTML 파서가 절대 만들 수 없기 때문에 문자열 정리기에는 보이지 않지만, 재파싱 시 빠져나옵니다. 이제 DOMPurify는 정확한 `Attr` 노드로 속성을 제거하고 이러한 리터럴 텍스트 트리를 안전하지 않은 것으로 취급하므로, 입력 측에서 문서 컨텍스트를 섞는 경우도 커버됩니다. _출력_ 측에서 컨텍스트를 섞지 않는 것은 여전히 여러분의 몫입니다. 위 단락을 참고하세요.

### 좋아요, 이해됩니다. 계속 진행하죠

마크업을 정리한 후에는 `DOMPurify.removed` 속성을 살펴보고 어떤 요소와 속성이 제거되었는지 확인할 수도 있습니다. 이 속성을 **보안상 중요한 결정**을 내리는 데 **사용하지 마세요**. 이것은 호기심 많은 사람들을 위한 작은 도우미일 뿐입니다.

### 서버에서 DOMPurify 실행하기

DOMPurify는 기술적으로 Node.js와 함께 서버 측에서도 작동합니다. 우리의 지원은 [Node.js 릴리스 주기](https://nodejs.org/en/about/previous-releases)를 따르기 위해 노력합니다.

서버에서 DOMPurify를 실행하려면 DOM이 존재해야 하는데, 이는 아마 놀랍지 않을 것입니다. 보통 [jsdom](https://github.com/jsdom/jsdom)이 선택되는 도구이며, 우리는 최신 버전의 _jsdom_ 사용을 **강력히 권장**합니다.

왜일까요? 오래된 버전의 _jsdom_은 DOMPurify가 100% 올바르게 동작하더라도 XSS를 초래하는 방식으로 버그가 있는 것으로 알려져 있기 때문입니다. 예를 들어 _jsdom v19.0.0_에는 **알려진 공격 벡터**가 있으며 이는 _jsdom v20.0.0_에서 수정되었습니다. 그렇기 때문에 _jsdom_을 최신 상태로 유지할 것을 정말 권장합니다.

또한 [happy-dom](https://github.com/capricorn86/happy-dom) 같은 도구가 존재하지만 현재 시점에서는 **안전한 것으로 간주되지 않는다**는 점을 유의하세요. DOMPurify를 _happy-dom_과 결합하는 것은 현재 권장되지 않으며 XSS로 이어질 가능성이 높습니다. 선택한 서버 측 DOM이 왜 신뢰 컴퓨팅 기반(trusted computing base)의 일부인지에 대한 배경은 [공격 클래스 및 우회 이력](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History)을 참고하세요.

Cloudflare Workers나 Vercel Edge처럼 _jsdom_이 실행될 수 없는 런타임에서는 [purify-edge](https://github.com/anzal1/purify-edge)가 parse5 기반 window에서 수정되지 않은 DOMPurify를 실행하는 서드파티 프로젝트입니다. 우리의 테스트 스위트는 호환성 검사로 `npm run test:purify-edge`를 통해 이에 대해 실행할 수 있습니다. 이는 우리가 유지 관리하지 않으며, 통과 실행은 보증도 보안 보장도 아닙니다.

그 외에는 서버에서 DOMPurify를 사용해도 괜찮습니다. 아마도요. 이는 정말로 _jsdom_ 또는 서버 측에서 사용하는 DOM에 달려 있습니다. 이를 감수할 수 있다면, 작동시키는 방법은 다음과 같습니다:

```bash
npm install dompurify
npm install jsdom
```

_jsdom_의 경우(최신 버전을 사용하세요), 다음이면 충분합니다:

```js
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');

const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);
const clean = DOMPurify.sanitize('<b>hello there</b>');
```

또는 임포트로 작업하는 것을 선호한다면 다음과 같이 할 수도 있습니다:

```js
import { JSDOM } from 'jsdom';
import DOMPurify from 'dompurify';

const window = new JSDOM('').window;
const purify = DOMPurify(window);
const clean = purify.sanitize('<b>hello there</b>');
```

특정 환경에서 작동시키는 데 문제가 있다면, 많은 사람들이 겪을 수 있는 문제를 해결해 주는 훌륭한 [isomorphic-dompurify](https://github.com/kkomelin/isomorphic-dompurify) 프로젝트를 참고해 보세요.

```bash
npm install isomorphic-dompurify
```

```js
import DOMPurify from 'isomorphic-dompurify';

const clean = DOMPurify.sanitize('<s>hello</s>');
```

## 데모가 있나요?

물론 데모가 있습니다! [DOMPurify로 직접 사용해 보세요](https://cure53.de/purify)

## 보안 버그를 발견하면 어떻게 해야 하나요?

우선, 수정 작업을 진행할 수 있도록 즉시 [이메일](mailto:[email protected])로 저희에게 연락해 주세요. [PGP 키](https://keyserver.ubuntu.com/pks/lookup?op=vindex&search=0xC26C858090F70ADA)

또한, 버그 바운티 대상이 될 가능성이 높습니다! [Fastmail](https://www.fastmail.com/)의 훌륭한 분들이 자사 서비스에 DOMPurify를 사용하고 있으며, 저희 라이브러리를 버그 바운티 범위에 추가했습니다. 따라서 DOMPurify를 우회하거나 약화시키는 방법을 발견하셨다면, 그들의 웹사이트와 [버그 바운티 정보](https://www.fastmail.com/about/bugbounty/)도 함께 확인해 주세요.

## 정화 샘플 몇 가지를 보여주실 수 있나요?

정화된 마크업은 어떻게 보일까요? [데모](https://cure53.de/purify)에서 다양한 악성 요소들을 대상으로 보여줍니다. 하지만 더 작은 예시 몇 가지도 보여드리겠습니다!

```js
DOMPurify.sanitize(''); // becomes <img src="https://raw.githubusercontent.com/cure53/dompurify/main/x">
DOMPurify.sanitize('<svg><g/onload=alert(2)//<p>'); // becomes <svg><g></g></svg>
DOMPurify.sanitize('<p>abcdef</p>'); // becomes <p>abc</p>
DOMPurify.sanitize('<math><mi//xlink:href="data:x,<script>alert(4)</script>">'); // becomes <math><mi></mi></math>
DOMPurify.sanitize('<TABLE><tr><td>HELLO</tr></TABL>'); // becomes <table><tbody><tr><td>HELLO</td></tr></tbody></table>
DOMPurify.sanitize('<UL><li><A HREF=//google.com>click</UL>'); // becomes <ul><li><a href="//google.com">click</a></li></ul>
```

이것들은 맛보기에 불과합니다. 이 샘플들이 비롯된 공격 클래스의 전체 분류 체계 - mutation XSS, 네임스페이스 혼동, DOM 클로버링, rawtext 브레이크아웃 등 - 는 [Attack Classes & Bypass History](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History)를 참조하세요.

## 무엇이 지원되나요?

DOMPurify는 현재 HTML5, SVG, MathML을 지원합니다. DOMPurify는 기본적으로 CSS와 HTML 사용자 정의 데이터 속성을 허용합니다. DOMPurify는 Shadow DOM도 지원하며 - DOM 템플릿을 재귀적으로 정화합니다. 이는 열린 shadow root만을 다룹니다. 닫힌 shadow root는 스크립트에서 읽을 수 없으므로, DOMPurify는 그 내부를 보거나 정화할 수 없습니다. 문자열은 영향을 받지 않습니다. DOMPurify 자체 파서가 선언적 shadow root(`<template shadowrootmode>`)를 무시하기 때문입니다. 그러나 `setHTMLUnsafe()`와 `Document.parseHTMLUnsafe()`는 그렇지 않습니다. 신뢰할 수 없는 마크업을 이들로 파싱한 뒤 결과 노드를 DOMPurify에 전달하면(`IN_PLACE`, `RETURN_DOM`, `RETURN_DOM_FRAGMENT`), 해당 마크업 내의 닫힌 shadow root는 정화되지 않은 채로 반환됩니다. 대신 신뢰할 수 없는 마크업을 문자열로 DOMPurify에 전달하세요. DOMPurify는 또한 jQuery `$()` 및 `elm.html()` API와 함께 사용할 HTML을 알려진 문제 없이 정화할 수 있게 해줍니다. 기본적으로 허용되는 요소와 속성의 정확한 집합은 [Default TAGs & ATTRIBUTEs allow-list & blocklist](https://github.com/cure53/DOMPurify/wiki/Default-TAGs-ATTRIBUTEs-allow-list-&-blocklist) 위키 페이지를 참조하세요.

## Internet Explorer 같은 레거시 브라우저는 어떻게 되나요?

DOMPurify는 아무것도 하지 않습니다. 단순히 입력한 문자열을 그대로 반환합니다. DOMPurify는 `isSupported`라는 속성을 노출하여 자신이 제 역할을 할 수 있는지 알려주므로, 자체적인 대비책을 마련할 수 있습니다.

## DOMPurify와 Trusted Types는 어떻게 되나요?

버전 1.0.9에서 [Trusted Types API](https://github.com/w3c/webappsec-trusted-types)([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API))에 대한 지원이 DOMPurify에 추가되었습니다.
버전 2.0.0에서는 이와 관련된 DOMPurify의 동작을 제어하는 설정 플래그가 추가되었습니다.

`DOMPurify.sanitize`가 Trusted Types API를 사용할 수 있는 환경에서 사용되고 `RETURN_TRUSTED_TYPE`이 `true`로 설정되면, 문자열 대신 `TrustedHTML` 값을 반환하려고 시도합니다(`RETURN_DOM` 및 `RETURN_DOM_FRAGMENT` 설정 옵션의 동작은 변경되지 않습니다).

DOMPurify를 사용하여 `trustedTypes`에서 정책을 생성하려면 `RETURN_TRUSTED_TYPE: false`가 필요합니다. `createHTML`은 `TrustedHTML`이 아닌 일반 문자열을 기대하기 때문입니다. 아래 예제에서 이를 확인할 수 있습니다.

```js
window.trustedTypes.createPolicy('default', {
  createHTML: (to_escape) =>
    DOMPurify.sanitize(to_escape, { RETURN_TRUSTED_TYPE: false }),
});
```

`TRUSTED_TYPES_POLICY`가 제공되지 않으면 DOMPurify는 `dompurify`라는 이름의 자체 내부 Trusted Types 정책을 생성하려고 시도합니다. 페이지에서 이미 자체 정책을 정의하고 있고, 엄격한 CSP(예: `trusted-types my-organization`)와 함께 사용 중인데 이 CSP가 `dompurify`라는 이름의 정책을 허용하지 않는다면, 이 시도는 브라우저에 의해 차단되며 `TrustedTypes policy dompurify could not be created.` 경고와 함께 CSP 위반이 기록됩니다.

DOMPurify가 내부 폴백 정책을 생성하지 않도록 하려면 `TRUSTED_TYPES_POLICY: null`을 전달하세요. 이는 자체 정책의 `createHTML` 내부에서 `DOMPurify.sanitize`를 호출할 때 적절한 선택이며, CSP의 `trusted-types` 허용 목록에 `dompurify`를 추가할 필요가 없다는 뜻입니다.

```js
window.trustedTypes.createPolicy('my-organization', {
  createHTML: (input) =>
    DOMPurify.sanitize(input, { TRUSTED_TYPES_POLICY: null }),
});
```

자신의 래핑 정책을 DOMPurify의 `TRUSTED_TYPES_POLICY`로 다시 전달하지 **마십시오**(예: `DOMPurify.setConfig({ TRUSTED_TYPES_POLICY: myPolicy })`). 해당 정책의 `createHTML`이 이미 `DOMPurify.sanitize`를 호출하고 있는 경우에는 특히 그렇습니다. 이는 정의상 순환 구조입니다. 즉, 정화(sanitize)가 정책을 호출하고, 그 정책이 다시 DOMPurify를 호출하여 정화하는 구조입니다. DOMPurify는 무한 재귀를 방지하기 위해 설명이 포함된 `TypeError`를 발생시킵니다. 자신의 정책이 DOMPurify를 호출해야 하며, DOMPurify가 자신의 정책을 호출하도록 구성되어서는 안 됩니다.

이 `default` 정책 패턴을 전체 페이지에 자동으로 적용하고 싶다면 - 즉, 레거시 코드, 서드파티 위젯, 그리고 쉽게 찾거나 다시 작성할 수 없는 수천 개의 `innerHTML` 할당을 포함한 모든 HTML 싱크가 정화되도록 하려면 - [DOMFortify](https://github.com/cure53/DOMFortify)를 살펴보십시오. 이 프로젝트는 DOMPurify를 기반으로 하는 바로 그런 Trusted Types `default` 정책을 설치하며, 스크립트 싱크(`eval`, `script.src`, ...)를 완전히 거부합니다. 이는 의도적으로 별도의 프로젝트입니다. DOMPurify는 집중된 정화기(sanitizer)로 남아 있고, DOMFortify는 의도적으로 DOMPurify의 범위를 벗어나는 문서 전체 적용 계층을 처리합니다.

## DOMPurify를 구성할 수 있나요?

예. 포함된 기본 구성 값은 이미 상당히 좋지만, 물론 재정의할 수 있습니다. DOMPurify를 [사용자 정의](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this)하는 방법에 대한 여러 예시를 보려면 [`/demos`](https://github.com/cure53/DOMPurify/tree/main/demos) 폴더를 확인하십시오.

허용 목록(`ADD_TAGS`, `ADD_ATTR`, `CUSTOM_ELEMENT_HANDLING`, …)을 넓히거나 기본값을 완화하기 전에, [두 번 생각해야 할 태그와 속성](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model#dangerous-tags-and-attributes-think-twice-before-allow-listing)을 훑어보는 것이 좋습니다. 일부는 예상치 못한 방식으로 위험합니다.

### 일반 설정

```js
// strip {{ ... }}, ${ ... } and <% ... %> to make output safe for template systems
// be careful please, this mode is not recommended for production usage.
// allowing template parsing in user-controlled HTML is not advised at all.
// only use this mode if there is really no alternative.
const clean = DOMPurify.sanitize(dirty, { SAFE_FOR_TEMPLATES: true });

// change how e.g. comments containing risky HTML characters are treated.
// be very careful, this setting should only be set to `false` if you really only handle
// HTML and nothing else, no SVG, MathML or the like.
// Otherwise, changing from `true` to `false` will lead to XSS in this or some other way.
const clean = DOMPurify.sanitize(dirty, { SAFE_FOR_XML: false });
```

### 허용 목록과 차단 목록 제어

```js
// allow only <b> elements, very strict
const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b'] });

// allow only <b> and <q> with style attributes
const clean = DOMPurify.sanitize(dirty, {
  ALLOWED_TAGS: ['b', 'q'],
  ALLOWED_ATTR: ['style'],
});

// allow all safe HTML elements but neither SVG nor MathML
// note that the USE_PROFILES setting will override the ALLOWED_TAGS setting
// so don't use them together
const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });

// allow all safe SVG elements and SVG Filters, no HTML or MathML
const clean = DOMPurify.sanitize(dirty, {
  USE_PROFILES: { svg: true, svgFilters: true },
});

// allow all safe MathML elements and SVG, but no SVG Filters
const clean = DOMPurify.sanitize(dirty, {
  USE_PROFILES: { mathMl: true, svg: true },
});

// change the default namespace from HTML to something different
const clean = DOMPurify.sanitize(dirty, {
  NAMESPACE: 'http://www.w3.org/2000/svg',
});

// leave all safe HTML as it is and add <style> elements to block-list
const clean = DOMPurify.sanitize(dirty, { FORBID_TAGS: ['style'] });

// note: while <table> is allowed, <tbody> is always allowed too and cannot be
// forbidden - browsers insert it on their own, and forbidding it used to make
// sanitize() loop (see #365). Forbid 'table' as well to drop tables entirely.

// leave all safe HTML as it is and add style attributes to block-list
const clean = DOMPurify.sanitize(dirty, { FORBID_ATTR: ['style'] });

// extend the existing array of allowed tags and add <my-tag> to allow-list
const clean = DOMPurify.sanitize(dirty, { ADD_TAGS: ['my-tag'] });

// extend the existing array of allowed attributes and add my-attr to allow-list
const clean = DOMPurify.sanitize(dirty, { ADD_ATTR: ['my-attr'] });

// use functions to control which additional tags and attributes are allowed
const allowlist = {
  one: ['attribute-one'],
  two: ['attribute-two'],
};
const clean = DOMPurify.sanitize(
  '<one attribute-one="1" attribute-two="2"></one><two attribute-one="1" attribute-two="2"></two>',
  {
    ADD_TAGS: (tagName) => {
      return Object.keys(allowlist).includes(tagName);
    },
    ADD_ATTR: (attributeName, tagName) => {
      return allowlist[tagName]?.includes(attributeName) || false;
    },
  }
); // <one attribute-one="1"></one><two attribute-two="2"></two>

// prohibit ARIA attributes, leave other safe HTML as is (default is true)
const clean = DOMPurify.sanitize(dirty, { ALLOW_ARIA_ATTR: false });

// prohibit HTML5 data attributes, leave other safe HTML as is (default is true)
const clean = DOMPurify.sanitize(dirty, { ALLOW_DATA_ATTR: false });
```

### Custom Elements와 관련된 동작 제어

```js
// DOMPurify allows to define rules for Custom Elements. When using the CUSTOM_ELEMENT_HANDLING
// literal, it is possible to define exactly what elements you wish to allow (by default, none are allowed).
//
// The same goes for their attributes. By default, the built-in or configured allow.list is used.
//
// You can use a RegExp literal to specify what is allowed or a predicate, examples for both can be seen below.
// When using a predicate function for attributeNameCheck, it can optionally receive the tagName as a second parameter
// for more granular control over which attributes are allowed for specific elements.
// The default values are very restrictive to prevent accidental XSS bypasses. Handle with great care!

const clean = DOMPurify.sanitize(
  '<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: null, // no custom elements are allowed
      attributeNameCheck: null, // default / standard attribute allow-list is used
      allowCustomizedBuiltInElements: false, // no customized built-ins allowed
    },
  }
); // <div is=""></div>

const clean = DOMPurify.sanitize(
  '<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: /^foo-/, // allow all tags starting with "foo-"
      attributeNameCheck: /baz/, // allow all attributes containing "baz"
      allowCustomizedBuiltInElements: true, // customized built-ins are allowed
    },
  }
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>

const clean = DOMPurify.sanitize(
  '<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: (tagName) => tagName.match(/^foo-/), // allow all tags starting with "foo-"
      attributeNameCheck: (attr) => attr.match(/baz/), // allow all containing "baz"
      allowCustomizedBuiltInElements: true, // allow customized built-ins
    },
  }
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>

// Example with attributeNameCheck receiving tagName as a second parameter
const clean = DOMPurify.sanitize(
  '<element-one attribute-one="1" attribute-two="2"></element-one><element-two attribute-one="1" attribute-two="2"></element-two>',
  {
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: (tagName) => tagName.match(/^element-(one|two)$/),
      attributeNameCheck: (attr, tagName) => {
        if (tagName === 'element-one') {
          return ['attribute-one'].includes(attr);
        } else if (tagName === 'element-two') {
          return ['attribute-two'].includes(attr);
        } else {
          return false;
        }
      },
      allowCustomizedBuiltInElements: false,
    },
  }
); // <element-one attribute-one="1"></element-one><element-two attribute-two="2"></element-two>
```

### URI 값과 관련된 동작 제어

```js
// extend the existing array of elements that can use Data URIs
const clean = DOMPurify.sanitize(dirty, { ADD_DATA_URI_TAGS: ['a', 'area'] });

// extend the existing array of elements that are safe for URI-like values (be careful, XSS risk)
const clean = DOMPurify.sanitize(dirty, { ADD_URI_SAFE_ATTR: ['my-attr'] });
```

### 허용되는 속성 값 제어

```js
// allow external protocol handlers in URL attributes (default is false, be careful, XSS risk)
// by default only http, https, ftp, ftps, tel, mailto, callto, sms, cid, xmpp and matrix are allowed.
const clean = DOMPurify.sanitize(dirty, { ALLOW_UNKNOWN_PROTOCOLS: true });

// allow specific protocol handlers in URL attributes via regex (default is false, be careful, XSS risk)
// by default only (protocol-)relative URLs, http, https, ftp, ftps, tel, mailto, callto, sms, cid, xmpp and matrix are allowed.
// Default RegExp: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
// The example below extends the default with one additional scheme (sftp).
// Keep the pattern linear-time: it runs against attacker-controlled values.
const clean = DOMPurify.sanitize(dirty, {
  ALLOWED_URI_REGEXP:
    /^(?:(?:(?:f|ht)tps?|sftp|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
});
```

### 반환 타입에 영향 주기

```js
// return a DOM HTMLBodyElement instead of an HTML string (default is false)
const clean = DOMPurify.sanitize(dirty, { RETURN_DOM: true });

// return a DOM DocumentFragment instead of an HTML string (default is false)
const clean = DOMPurify.sanitize(dirty, { RETURN_DOM_FRAGMENT: true });

// use the RETURN_TRUSTED_TYPE flag to turn on Trusted Types support if available
const clean = DOMPurify.sanitize(dirty, { RETURN_TRUSTED_TYPE: true }); // will return a TrustedHTML object instead of a string if possible

// use a provided Trusted Types policy
const clean = DOMPurify.sanitize(dirty, {
  // supplied policy must define createHTML and createScriptURL
  TRUSTED_TYPES_POLICY: trustedTypes.createPolicy('dompurify', {
    createHTML(s) {
      return s;
    },
    createScriptURL(s) {
      return s;
    },
  }),
});

// opt out of DOMPurify's internal `dompurify` Trusted Types policy entirely
// (useful when your CSP `trusted-types` allowlist does not include `dompurify`)
const clean = DOMPurify.sanitize(dirty, { TRUSTED_TYPES_POLICY: null });
```

### 정화 방식에 영향 주기

```js
// return entire document including <html> tags (default is false)
const clean = DOMPurify.sanitize(dirty, { WHOLE_DOCUMENT: true });

// disable DOM Clobbering protection on output (default is true, handle with care, minor XSS risks here)
const clean = DOMPurify.sanitize(dirty, { SANITIZE_DOM: false });

// enforce strict DOM Clobbering protection via namespace isolation (default is false)
// when enabled, isolates the namespace of named properties (i.e., `id` and `name` attributes)
// from JS variables by prefixing them with the string `user-content-`
const clean = DOMPurify.sanitize(dirty, { SANITIZE_NAMED_PROPS: true });

// keep an element's content when the element is removed (default is true)
const clean = DOMPurify.sanitize(dirty, { KEEP_CONTENT: false });

// glue elements like style, script or others to document.body and prevent unintuitive browser behavior in several edge-cases (default is false)
const clean = DOMPurify.sanitize(dirty, { FORCE_BODY: true });

// remove all <a> elements under <p> elements that are removed
const clean = DOMPurify.sanitize(dirty, {
  FORBID_CONTENTS: ['a'],
  FORBID_TAGS: ['p'],
});

// extend the default FORBID_CONTENTS list to also remove <a> elements under <p> elements
const clean = DOMPurify.sanitize(dirty, {
  ADD_FORBID_CONTENTS: ['a'],
  FORBID_TAGS: ['p'],
});

// change the parser type so sanitized data is treated as XML and not as HTML, which is the default
const clean = DOMPurify.sanitize(dirty, {
  PARSER_MEDIA_TYPE: 'application/xhtml+xml',
});
```

### 정제(sanitize)를 수행하는 위치에 대한 영향

```js
// use the IN_PLACE mode to sanitize a node "in place", which is much faster depending on how you use DOMPurify
const dirty = document.createElement('a');
dirty.setAttribute('href', 'javascript:alert(1)');

const clean = DOMPurify.sanitize(dirty, { IN_PLACE: true }); // see https://github.com/cure53/DOMPurify/issues/288 for more info
```

`IN_PLACE`에 관해 알아두어야 할 몇 가지 사항:

- 전달하는 루트 노드는 그 자체로 허용된 태그여야 하며 DOM-clobbering이 발생해서는 안 됩니다(예: `nodeName` 또는 `ownerDocument`라는 자식이 있는 `<form>`). 그럴 경우 DOMPurify는 루트의 하위 트리에서 허용 목록에 없는 모든 속성을 제거한 뒤 `TypeError`를 발생시키므로, 거부된 루트가 무장된 상태로 반환되는 일은 결코 없습니다.
- 순회 도중 예외가 발생하면, 오류가 전파되기 전에 동일한 fail-closed 무력화가 루트와 해당 순회 중 이미 분리된 모든 하위 트리에 대해 실행됩니다.

---

[Read more](https://github.com/cure53/dompurify)
도구 다운로드