
DOMPurify v3.4.13
DOMPurify - HTML, MathML 및 SVG를 위한 DOM 전용, 초고속, 매우 관대한 XSS 새니타이저. DOMPurify는 안전한 기본 설정으로 작동하지만, 다양한 구성 옵션과 훅을 제공합니다. 데모:
DOMPurify
DOMPurify는 HTML, MathML 및 SVG를 위한 DOM 전용, 초고속, 매우 관대한 XSS 새니타이저입니다.
사용하고 시작하기도 매우 간단합니다. DOMPurify는 2014년 2월에 시작되어 현재 버전 v3.4.14에 도달했습니다.
DOMPurify는 JavaScript로 실행되며 모든 최신 브라우저(Safari(10+), Opera(15+), Edge, Firefox 및 Chrome — 그리고 Blink, Gecko 또는 WebKit을 사용하는 거의 모든 브라우저)에서 작동합니다. MSIE나 기타 레거시 브라우저에서는 문제가 발생하지 않습니다. 그저 아무것도 하지 않을 뿐입니다.
참고: DOMPurify v2.5.9는 MSIE를 지원하는 최신 버전입니다. MSIE와 호환되는 중요한 보안 업데이트가 필요하다면 2.x 브랜치를 사용하세요.
자동화된 테스트는 모든 푸시마다 현재 엔진(Ubuntu, macOS 및 Windows에서 Chromium, Firefox 및 WebKit)에서 9가지 브라우저/OS 조합을 다루며, 별도의 매트릭스는 약 3년 전의 Chromium 110, Firefox 108 및 WebKit 16.4까지 거슬러 올라가는 이전 엔진 스냅샷에서도 테스트 스위트를 다시 실행하여 오래된 브라우저에서의 회귀도 잡아냅니다. 또한 jsdom에서 DOMPurify를 사용하여 Node.js v20, v22, v24, v25 및 v26도 실행합니다. 이전 Node 버전도 작동하는 것으로 알려져 있지만, 보장은 없습니다.
DOMPurify는 웹 공격과 XSS에 대한 방대한 배경 지식을 가진 보안 전문가들이 작성했습니다. 걱정하지 마세요. 자세한 내용은 보안 목표 및 위협 모델에 대해서도 읽어보시기 바랍니다. 꼭 읽어보세요. 정말로요. 그리고 자세한 내용을 즐기신다면, 공격 클래스 및 우회 기록 페이지에서 DOMPurify가 방어하는 파서 변형, 네임스페이스, 클로버링 및 템플릿 트릭을 확인할 수 있습니다.
DOMPurify 프로젝트는 HTML Sanitizer API의 탄생에 영감을 주었으며, 이 API는 이미 많은 브라우저에서 제공되고 있습니다. 동일한 기능은 이제 WHATWG HTML 사양에서 직접 표준화되고 있습니다.
목차
- 무엇을 하나요?
- 어떻게 사용하나요?
- 데모가 있나요?
- 보안 버그를 발견하면 어떻게 하나요?
- 정화 샘플을 좀 보여주시겠어요?
- 무엇이 지원되나요?
- Internet Explorer 같은 레거시 브라우저는 어떻게 하나요?
- DOMPurify와 Trusted Types는 어떻게 되나요?
- DOMPurify를 구성할 수 있나요?
- 영구 구성
- 훅
- 제거된 구성
- 지속적 통합
- 보안 메일링 리스트
- 누가 기여했나요?
무엇을 하나요?
DOMPurify는 HTML을 새니타이즈하고 XSS 공격을 방지합니다. 예를 들어 더러운 HTML로 가득 찬 문자열을 DOMPurify에 넣으면 (다르게 구성하지 않는 한) 깨끗한 HTML이 포함된 문자열을 반환합니다. DOMPurify는 위험한 HTML을 포함하는 모든 것을 제거하여 XSS 공격과 기타 위험한 요소를 방지합니다. 또한 엄청나게 빠릅니다. 우리는 브라우저가 제공하는 기술을 사용하여 이를 XSS 필터로 전환합니다. 브라우저가 빠를수록 DOMPurify도 빨라집니다.
어떻게 사용하나요?
간단합니다. 웹사이트에 DOMPurify를 포함하기만 하면 됩니다.
축소되지 않은 버전 사용 (소스 맵 제공)```html
### 축소되고 테스트된 프로덕션 버전 사용하기 (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>');
The resulting HTML can be written into a DOM element using innerHTML or the DOM using document.write(). That is fully up to you.
Note that by default, we permit HTML, SVG and MathML. If you only need HTML, which might be a very common use-case, you can easily set that up as well:```js
const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
### 함정이 될 만한 요소가 있나요?
주의하세요. HTML을 _먼저_ 살균한 뒤 _이후에_ 수정하면 살균 효과를 쉽게 **무효화**할 수 있습니다. 살균된 마크업을 다른 라이브러리에 전달할 때는, 그 라이브러리가 HTML을 자체적으로 건드리지 않는지 반드시 확인하세요. 안전한 사용법과 신중히 검토해야 할 태그·속성 목록은 [보안 목표 및 위협 모델](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model)을, 후처리와 마크업 컨텍스트 변경이 살균을 무력화하는 이유는 [공격 클래스 및 우회 기록](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History)을 참고하세요.
### 알겠습니다. 이해했으니 넘어가죠
마크업을 살균한 뒤에는 `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이 신뢰 컴퓨팅 기반의 일부인 이유에 대한 배경은 [공격 클래스 및 우회 기록](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History)을 참고하세요.
그 외에는 서버에서 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('hello there');
또는 import를 사용하여 작업하는 것을 선호한다면 이렇게 할 수도 있습니다:```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 프로젝트를 살펴보는 것을 고려해 보세요.```bash npm install isomorphic-dompurify
I need the input content to translate. Please provide the chunk of Markdown content you'd like me to translate from English to Korean.```js
import DOMPurify from 'isomorphic-dompurify';
const clean = DOMPurify.sanitize('<s>hello</s>');
데모가 있나요?
물론 데모가 있습니다! DOMPurify로 직접 사용해 보세요
보안 버그를 발견하면 어떻게 하나요?
우선, 이메일을 통해 즉시 연락해 주시면 수정 작업을 진행하겠습니다. PGP 키
또한, 버그 바운티 자격이 될 가능성이 높습니다! Fastmail의 좋은 분들이 DOMPurify를 서비스에 사용하고 있으며, 저희 라이브러리를 버그 바운티 범위에 추가했습니다. 따라서 DOMPurify를 우회하거나 약화시킬 방법을 찾으셨다면, 그들의 웹사이트와 버그 바운티 정보도 확인해 보시기 바랍니다.
정화 샘플 몇 가지를 보여주실 수 있나요?
정화된 마크업은 어떻게 생겼을까요? 음, 데모에서 수많은 악성 요소에 대한 결과를 보여줍니다. 하지만 여기서 몇 가지 작은 예시도 보여드리겠습니다!```js
DOMPurify.sanitize(''); // becomes
DOMPurify.sanitize('<g/onload=alert(2)//
'); // becomes DOMPurify.sanitize('
abcdef
'); // becomesabc
DOMPurify.sanitize('<mi//xlink:href="data:x,">'); // becomes DOMPurify.sanitize(''); // becomes| HELLO |
| HELLO |
- <A HREF=//google.com>click
이것들은 그저 맛보기에 불과합니다. 이러한 샘플이 비롯된 공격 클래스의 전체 분류(변이 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 템플릿을 재귀적으로 살균합니다. 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가 제 역할을 수행할 수 있는지 여부를 알려주므로 자체 백업 계획을 세울 수 있습니다.
## 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)가 정의되어 있어 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는 집중된 정화기로 유지되고, DOMFortify는 의도적으로 DOMPurify의 범위를 벗어난 문서 전체 적용 계층을 처리합니다.
## DOMPurify를 구성할 수 있나요?
네. 포함된 기본 구성 값은 이미 꽤 좋습니다. 물론 이를 재정의할 수도 있습니다. [`/demos`](https://github.com/cure53/DOMPurify/tree/main/demos) 폴더에서 [DOMPurify를 사용자 정의](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this)하는 방법에 대한 다양한 예제를 확인하십시오.
허용 목록(`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 elements, very strict const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b'] });
// allow only and 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 elements to block-list const clean = DOMPurify.sanitize(dirty, { FORBID_TAGS: ['style'] });
// 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 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( '', { ADD_TAGS: (tagName) => { return Object.keys(allowlist).includes(tagName); }, ADD_ATTR: (attributeName, tagName) => { return allowlist[tagName]?.includes(attributeName) || false; }, } ); //
// 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 });
### 커스텀 엘리먼트와 관련된 제어 동작```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):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
const clean = DOMPurify.sanitize(dirty, {
ALLOWED_URI_REGEXP:
/^(?:(?:(?:f|ht)tps?|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',
});
영향력을 행사하는 곳에서 삭제 처리```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
[더 많은 예시는 여기](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this)에서 확인할 수 있으며, DOMPurify를 실행하고 사용자 정의하고 구성하는 방법을 보여줍니다.
## 영구 구성
`DOMPurify.sanitize`에 동일한 구성을 반복해서 전달하는 대신 `DOMPurify.setConfig` 메서드를 사용할 수 있습니다. 구성은 다음 `DOMPurify.setConfig` 호출까지, 또는 `DOMPurify.clearConfig`를 호출하여 재설정할 때까지 유지됩니다. 활성 구성은 하나만 있다는 점을 기억하세요. 즉, 설정된 후에는 `DOMPurify.sanitize`에 전달되는 추가 구성 매개변수는 모두 무시됩니다.
## 훅
DOMPurify를 사용하면 `DOMPurify.addHook` 메서드를 사용하여 다음 훅 중 하나에 하나 이상의 함수를 연결하여 기능을 확장할 수 있습니다:
- `beforeSanitizeElements`
- `uponSanitizeElement` ('s' 없음 - 모든 요소에 대해 호출됨)
- `afterSanitizeElements`
- `beforeSanitizeAttributes`
- `uponSanitizeAttribute`
- `afterSanitizeAttributes`
- `beforeSanitizeShadowDOM`
- `uponSanitizeShadowNode`
- `afterSanitizeShadowDOM`
현재 처리 중인 DOM 노드, 필요한 경우 검증된 노드 및 속성 데이터가 포함된 리터럴, 그리고 DOMPurify 구성을 콜백에 전달합니다. API가 어떻게 유용하게 사용될 수 있는지 확인하려면 [MentalJS 훅 데모](https://github.com/cure53/DOMPurify/blob/main/demos/hooks-mentaljs-demo.html)를 확인하세요.
_예시_:```js
DOMPurify.addHook(
'uponSanitizeAttribute',
function (currentNode, hookEvent, config) {
// Do something with the current node
// You can also mutate hookEvent for current node (i.e. set hookEvent.forceKeepAttr = true)
// For other than 'uponSanitizeAttribute' hook types hookEvent equals to null
}
);
훅에서 sanitize() 호출에 관한 참고 사항
DOMPurify.sanitize()는 재진입(re-entrant)이 불가능합니다. 훅 내부나 CUSTOM_ELEMENT_HANDLING.tagNameCheck 또는 attributeNameCheck와 같은 구성 콜백에서 호출하지 마십시오. 이러한 콜백은 활성화된 살균 패스(sanitizer pass)의 중간 에 실행됩니다.
중첩된 sanitize() 호출은 전달된 구성을 다시 읽으며, 그 과정에서 외부 패스가 여전히 사용 중인 구성을 대체합니다. 이후의 외부 문서 나머지 부분은 사용자의 구성이 아닌 중첩 호출의 구성에 따라 살균됩니다. 중첩 호출은 일반적으로 기본 구성으로 실행되므로, 엄격한 ALLOWED_TAGS 허용 목록이 문서 중간에 오류나 경고 없이 조용히 기본값으로 확장될 수 있습니다.
속성 값에 포함된 HTML 조각과 같은 중첩 마크업을 살균해야 하는 경우, 두 가지 안전한 옵션이 있습니다. 호출마다 구성을 전달하는 대신 DOMPurify.setConfig로 구성을 한 번 설정하십시오. 영구 구성은 중첩 호출과 공유되며 전체 패스 동안 유효하기 때문입니다. 또는 훅 중에 조각을 수집하고 외부 호출이 반환된 후에 별도의 sanitize() 호출로 살균하십시오.
제거된 구성
| 옵션 | 이후 버전 | 참고 |
|---|---|---|
| SAFE_FOR_JQUERY | 2.1.0 | 대체 필요 없음. |
지속적 통합
현재 GitHub Actions와 Playwright를 조합하여 사용하고 있습니다. 이를 통해 모든 커밋에서 관련 최신 브라우저에서 모든 것이 작동하는지 확인할 수 있으며, 별도의 예약 및 병합 시 워크플로우가 이전 엔진 스냅샷에서 테스트 스위트를 다시 실행하여 오래된 브라우저에서의 손상도 포착합니다. 빌드 로그는 여기에서 확인하십시오: https://github.com/cure53/DOMPurify/actions
npm run test를 실행하여 로컬 테스트를 추가로 실행할 수 있습니다.
모든 관련 커밋은 추가 보안을 위해 키 0x24BB6BF4로 서명됩니다 (2016년 4월 8일 이후).
개발 및 기여
설치 (npm i)
공식적으로 npm을 지원합니다. GitHub Actions 워크플로우는 npm을 사용하여 종속성을 설치하도록 구성되어 있습니다. 더 이상 사용되지 않는 버전의 npm을 사용하는 경우 설치된 종속성의 버전을 완전히 보장할 수 없으며, 이로 인해 예기치 않은 문제가 발생할 수 있습니다.
스크립트
코드 일관성을 보장하기 위해 사전 커밋 워크플로우의 일부로 xo를 통한 ESLint를 사용합니다. 또한 소스 및 Markdown 서식에는 Prettier를 사용하며, /dist 자산은 rollup을 통해 빌드됩니다.
다음은 npm 스크립트입니다:
npm run dev— 소스 변경을 감시하면서 압축되지 않은 UMD 번들을 빌드합니다.npm run test— 소스를 린트하고, jsdom을 통해 테스트를 실행하며, Playwright를 통해 Chromium에서 브라우저 테스트를 실행합니다.npm run test:jsdom— jsdom을 통해서만 테스트를 실행합니다.npm run test:happydom— happy-dom을 통해 스위트를 실행합니다 (지원되지 않는 환경; 호환성 약속이 아닌 견고성 검사로 유지됨).npm run test:browser— Playwright를 통해서만 테스트를 실행합니다.npm run test:browser:legacy— 이전 브라우저 엔진에서 스위트를 실행합니다 (PW_MODULE를 고정된 이전 Playwright 설치로 지정;.github/workflows/legacy-browsers.yml참조).npm run test:ci— jsdom 및 Playwright에 대한 CI 테스트 흐름을 실행합니다.npm run test:fuzz—sanitize()및 CONFIG를 다루는 소규모 퍼저를 실행합니다.
npm run bench— 빌드된dist/purify.cjs에 대해 jsdom 마이크로 벤치마크를 실행합니다 (먼저 빌드;--json및--compare a.json b.json은 브랜치 간 A/B 실행을 지원합니다 — 결과는 방향성이며, 실제 브라우저에서 사용자 대상 주장을 확인하십시오).npm run coverage— 계측된 번들을 빌드하고, jsdom 스위트를 실행하며, 로컬 HTML 라인/브랜치 커버리지 보고서를coverage/index.html에 작성합니다 (jsdom 범위만 해당, CI에서는 실행되지 않음).npm run build:cov— 계측된 커버리지 번들만 빌드합니다.
npm run lint— xo를 통한 ESLint로 소스를 린트합니다.npm run format— Prettier로 JavaScript/TypeScript 및 Markdown 소스를 서식화합니다.npm run format:js— JavaScript/TypeScript 소스만 서식화합니다.npm run format:md— Markdown 파일만 서식화합니다.
npm run build— 타입 선언 및 배포 번들을 빌드한 다음, 생성된 타입을 수정하고 정리합니다.npm run build:types— TypeScript 선언 파일만 생성합니다.npm run build:rollup— 모든 Rollup 번들을 빌드합니다.npm run build:umd— 압축되지 않은 UMD 번들만 빌드합니다.npm run build:umd:min— 압축된 UMD 번들만 빌드합니다.npm run build:es— ES 모듈 번들만 빌드합니다.npm run build:cjs— CommonJS 번들만 빌드합니다.npm run build:fix-types— 생성된 타입 파일을 후처리합니다.npm run build:cleanup— 임시 생성된 타입 출력을 정리합니다.
npm run verify-typescript— TypeScript 검증 스크립트를 실행합니다.npm run commit-amend-build— 빌드 출력을 수정하기 위한 관리자 도우미 스크립트를 실행합니다.
참고: 모든 실행 스크립트는 npm run <script>로 실행됩니다.
더 많은 npm 스크립트가 있지만 주로 CI와 통합하거나 예를 들어 모든 커밋에서 배포 파일을 수정하는 "비공개" 용도로 사용됩니다.
보안 메일링 리스트
DOMPurify의 보안에 중요한 릴리스가 게시될 때마다 알리는 메일링 리스트를 운영합니다. 즉, 누군가 우회(bypass)를 발견하고 릴리스로 수정한 경우(우회가 발견될 때마다 항상 발생) 해당 목록으로 메일이 발송됩니다. 이는 일반적으로 우회를 알게 된 후 몇 분 또는 몇 시간 내에 이루어집니다. 리스트는 여기에서 구독할 수 있습니다:
https://lists.ruhr-uni-bochum.de/mailman/listinfo/dompurify-security
기능 릴리스는 이 목록에 공지되지 않습니다.
누가 기여했나요?
많은 사람들이 DOMPurify가 오늘날의 모습이 되도록 도왔으며, 그들은 인정받을 자격이 있습니다!
offset, Bankde, lukewarlow, DEMON1A, fg0x0, kodareef5, DavidOliver, 1Jesper1, bencalif, trace37labs, eddieran, christos-eth, researchatfluidattacks, frevadiscor, Rotzbua, binhpv, MariusRumpf, prasadrajandran, Cybozu 💛💸, hata6502 💸, openclaw 💸, intra-mart-dh 💸, nelstrom ❤️, hash_kitten ❤️, kevin_mizu ❤️, icesfont ❤️, reduckted ❤️, dcramer 💸, JGraph 💸, baekilda 💸, Healthchecks 💸, Sentry 💸, jarrodldavis 💸, CynegeticIO, ssi02014 ❤️, GrantGryczan, Lowdefy, granlem, oreoshake, tdeekens ❤️, peernohell ❤️, is2ei, SoheilKhodayari, franktopel, NateScarlet, neilj, fhemberger, Joris-van-der-Wel, ydaniv, terjanq, filedescriptor, ConradIrwin, gibson042, choumx, 0xSobky, styfle, koto, tlau88, strugee, oparoz, mathiasbynens, edg2s, dnkolegov, dhardtke, wirehead, thorn0, styu, mozfreddyb ❤️, mikesamuel, jorangreef, jimmyhchan, jameydeorio, jameskraus, hyderali, hansottowirtz, hackvertor, freddyb, flavorjones, djfarrelly, devd, camerondunford, buu700, buildog, alabiaga, Vector919, Robbert, GreLI, FuzzySockets, ArtemBernatskyy, @garethheyes, @shafigullin, @mmrupp, @irsdl, ShikariSenpai, ansjdnakjdnajkd, @asutherland, @mathias, @cgvwzq, @robbertatwork, @giutro, @CmdEngineer_, @avr4mit, davecardwell, Develop-KIM, asamuzaK, fishjojo1 ❤️, Rikuxx0, donmccurdy, hhk-png, elrion018, michalnieruchalski-tiugo, reey, KanhaKanhaiya, odaysec, Akokonunes, alirezarouhbakhsh, Jaybhade 그리고 특히 @securitymb ❤️ & @masatokinugawa ❤️ 님께 감사드립니다.