# What changed in sanitize-html

> 25 changes in sanitize-html 2 from its official release notes, upgrade guides and advisories: 7 breaking, 13 security, 1 new APIs and options. Each one cited. Sources checked 2026-10-18. HTML: https://unstale.sh/npm/sanitize-html/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## sanitize-html 2

### Breaking changes

- Removed the dependency because sanitize-html used only a small part of its functionality, so security scanner reports for deepmerge no longer appear for sanitize-html users. (2.18.1) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2181-2026-10-14)
- Fallback markup remains sanitized but is limited to eight nested iframe elements; deeper fallback is escaped as text, and the current nesting depth carries into nested calls so nestingLimit applies to the whole output. (2.18.1) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2181-2026-10-14)
- Diagnostic messages are now single lines without decorative line breaks or a warning icon; their wording is unchanged. (2.18.0) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2180-2026-09-30)
- For allowed meta elements, refresh destinations in content are checked against allowedSchemes or allowedSchemesByTag.meta; rejected or unparseable refresh content is removed. (2.18.0) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2180-2026-09-30)
- Configurations allowing svg or math together with textarea or xmp no longer re-emit raw-text contents unescaped, preventing non-allowlisted markup from surviving sanitization. (2.17.6) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2176-2026-07-10)
- sanitize-html now requires Node.js >=22.12.0 because htmlparser2 is ESM-only from version 11 onward. (2.17.6) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2176-2026-07-10)
- More attributes are protected against unsafe URL types where those URLs are not appropriate. (2.17.5) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2175-2026-06-10)

### Security

- Markup preserved inside a disallowed iframe is no longer escaped and is fully sanitized according to the same rules as the original input. (2.18.0) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2180-2026-09-30)
- Animation elements and attributeName are matched by local name, ignoring prefixes, so namespace-prefixed elements such as svg:animate are recognized when dropping URL-retargeting animations. (2.18.0) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2180-2026-09-30)
- ApostropheCMS: Stored XSS via SVG SMIL URI-list scheme-policy bypass (2.17.7) — [security advisory](https://github.com/advisories/GHSA-G8QQ-57P8-GGW5)
- Fixed an XSS / URL scheme policy bypass when configurations allow SVG animation elements together with attributeName and an animation value attribute. (2.17.7) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2177-2026-08-13)
- ApostropheCMS: Mutation-XSS / allowedTags bypass via literal `</textarea/>` solidus close (2.17.6) — [security advisory](https://github.com/advisories/GHSA-JXWJ-J7WR-GFRW)
- Configurations allowing textarea or xmp are protected against trailing-solidus end tags causing following non-allowlisted markup to be re-emitted as raw text. (2.17.6) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2176-2026-07-10)
- Nonstandard `nonTextTags` configurations no longer let nested tags pass through without sanitization unless they are expressly allowed. (2.17.5) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2175-2026-06-10)
- sanitize-html has incomplete URI scheme validation in that allows javascript: URIs through action, formaction, data, poster, and background attributes (2.17.5) — [security advisory](https://github.com/advisories/GHSA-VCCV-CMXP-4J9H)
- Apostrophe has default XSS via `xmp` raw-text passthrough in `sanitize-html` (2.17.4) — [security advisory](https://github.com/advisories/GHSA-RPR9-RXV7-X643)
- The xmp tag could pass forbidden markup through sanitize-html even when xmp was not explicitly allowed; users should update immediately. (2.17.4) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2174)
- Fixes an XSS vulnerability that affected configurations explicitly permitting option tags. (2.17.3) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2173-2026-04-15)
- sanitize-html allowedTags Bypass via Entity-Decoded Text in nonTextTags Elements (2.17.3) — [security advisory](https://github.com/advisories/GHSA-9MRH-V2V3-XPFM)
- These references are now correctly decoded, preventing them from bypassing javascript: URL detection. (2.17.2) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2172-2026-03-19)

### New APIs and options

- A console-shaped logger option routes sanitize-html diagnostics to an application logging pipeline; missing methods and an omitted option fall back to the console. (2.18.0) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2180-2026-09-30)

### Fixes and other changes

- Per-tag scheme allowlists now apply to srcset and imagesrcset URLs instead of falling back to the global allowedSchemes. (2.18.0) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2180-2026-09-30)
- transformTags can emit text when textFilter is set, even if the tag is initially empty. (2.17.6) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2176-2026-07-10)
- Entities inside raw text elements such as textarea and option are no longer double-encoded. (2.17.2) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2172-2026-03-19)
- Unclosed tags such as `<hello` no longer return an empty string in `escape` and `recursiveEscape` modes. (2.17.1) — [release notes](https://github.com/apostrophecms/apostrophe/blob/761ada7909b528241620d5f158bf2eb5f3618b7c/packages/sanitize-html/CHANGELOG.md#2171-2026-02-18)
