HtmlSanitizer has a bypass via template tag
Description
HtmlSanitizer is a .NET library for cleaning HTML fragments and documents from constructs that can lead to XSS attacks. Prior to versions 9.0.892 and 9.1.893-beta, if the template tag is allowed, its contents are not sanitized. The template tag is a special tag that does not usually render its contents, unless the shadowrootmode attribute is set to open or closed. This issue has been patched in versions 9.0.892 and 9.1.893-beta.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
HtmlSanitizer for .NET fails to sanitize content inside allowed tags, enabling XSS when shadowrootmode is set.
Vulnerability
Overview
CVE-2026-25543 is a cross-site scripting (XSS) vulnerability in the HtmlSanitizer .NET library. The root cause is that when the ` tag is included in the allowed tags list, the library does not sanitize the contents of that tag. The element is a special HTML container that normally does not render its children, but when the shadowrootmode attribute is set to open or closed`, the browser creates a shadow root and renders the template's content, making any unsanitized markup executable [1][2].
Exploitation
An attacker can exploit this by injecting a ` tag with a shadowrootmode attribute and malicious HTML or JavaScript inside it. If the application uses HtmlSanitizer to process user-supplied HTML and has ` in its allowed tags, the sanitizer will pass the template's inner content through unchanged. When the resulting HTML is rendered in a browser, the shadow root is created and the attacker's payload is executed, bypassing the sanitizer's intended protection [2][3].
Impact
Successful exploitation allows an attacker to inject arbitrary JavaScript into the context of the application's origin, leading to full XSS attacks. This can result in session hijacking, data theft, defacement, or other malicious actions performed in the context of the victim user's session. The vulnerability affects all versions prior to the patched releases [2].
Mitigation
The issue has been fixed in HtmlSanitizer versions 9.0.892 and 9.1.893-beta. Users should upgrade to one of these versions immediately. If upgrading is not possible, administrators can temporarily mitigate the risk by removing the `` tag from the allowed tags list in the sanitizer configuration [2][3][4].
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
HtmlSanitizerNuGet | < 9.0.892 | 9.0.892 |
HtmlSanitizerNuGet | >= 9.1.878-beta, < 9.1.893-beta | 9.1.893-beta |
Affected products
2- Range: <9.0.892
- mganss/HtmlSanitizerv5Range: < 9.0.892
Patches
10ac53dca30ddSanitize contents of template tag
2 files changed · +27 −4
src/HtmlSanitizer/HtmlSanitizer.cs+14 −4 modified@@ -498,7 +498,7 @@ private static void DefaultEncodeLiteralTextElementContent(IElement tag) tag.SetInnerText(escapedHtml); } - private void DoSanitize(IHtmlDocument dom, IParentNode context, string baseUrl = "") + private void DoSanitize(INode dom, IParentNode context, string baseUrl = "") { // remove disallowed tags foreach (var tag in context.QuerySelectorAll("*").Where(t => !IsAllowedTag(t)).ToList()) @@ -520,6 +520,11 @@ private void DoSanitize(IHtmlDocument dom, IParentNode context, string baseUrl = // cleanup attributes foreach (var tag in context.QuerySelectorAll("*").ToList()) { + if (tag is IHtmlTemplateElement templateElement && templateElement.Content is IDocumentFragment fragment) + { + DoSanitize(fragment, fragment, baseUrl); + } + // remove disallowed attributes foreach (var attribute in tag.Attributes.Where(a => !IsAllowedAttribute(a)).ToList()) { @@ -575,12 +580,17 @@ private void DoSanitize(IHtmlDocument dom, IParentNode context, string baseUrl = RemoveComments(node); } - DoPostProcess(dom, context as INode); + var doc = dom as IHtmlDocument ?? dom.Owner as IHtmlDocument; + + if (doc != null) + { + DoPostProcess(doc, context as INode); + } } - private void SanitizeStyleSheets(IHtmlDocument dom, string baseUrl) + private void SanitizeStyleSheets(INode node, string baseUrl) { - foreach (var styleSheet in dom.StyleSheets.OfType<ICssStyleSheet>()) + foreach (var styleSheet in node.GetStyleSheets().OfType<ICssStyleSheet>()) { var styleTag = styleSheet.OwnerNode; var i = 0;
test/HtmlSanitizer.Tests/Tests.cs+13 −0 modified@@ -3629,4 +3629,17 @@ public void DisallowStyleTagCssCustomPropertiesTest() var sanitized = sanitizer.Sanitize(input); Assert.Equal("<style>:root { }</style>", sanitized); } + + [Fact] + public void TemplateTest() + { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedTags.Add("template"); + sanitizer.AllowedTags.Add("style"); + + var html = "<div><template><style>div { display: none }</style><script>alert('xss')</script></template></div>"; + var sanitized = sanitizer.Sanitize(html); + var expected = "<div><template><style>div { display: none }</style></template></div>"; + Assert.Equal(expected, sanitized); + } }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-j92c-7v7g-gj3fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-25543ghsaADVISORY
- developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/templateghsaWEB
- github.com/mganss/HtmlSanitizer/commit/0ac53dca30ddad963f2b243669a5066933d82b81ghsax_refsource_MISCWEB
- github.com/mganss/HtmlSanitizer/releases/tag/v9.0.892ghsaWEB
- github.com/mganss/HtmlSanitizer/security/advisories/GHSA-j92c-7v7g-gj3fghsax_refsource_CONFIRMWEB
- www.nuget.org/packages/HtmlSanitizer/9.0.892ghsax_refsource_MISCWEB
- www.nuget.org/packages/HtmlSanitizer/9.1.893-betaghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.