Description
Swagger UI calls DOMPurify.addHook(...) on the global DOMPurify object. This is a side effect that leaks beyond Swagger UI's scope β any other code sharing the same DOMPurify instance will unexpectedly inherit the hook, which can cause subtle bugs or unintended behaviour in host applications.
Location
This occurs in src/core/components/providers/markdown.jsx.
Known impact
This is causing a bug in Backstage where the globally registered beforeSanitizeElements hook overwrites the rel attribute on any element with an href, including <link> stylesheet elements. As a result, stylesheet links have their rel="stylesheet" replaced with rel="noopener noreferrer", preventing stylesheets from loading and causing TechDocs pages to render as a blank white screen. See backstage/backstage#34037 (comment) for details.
Current behaviour
if (DomPurify.addHook) {
DomPurify.addHook("beforeSanitizeElements", function (current) {
if (current.href) {
current.setAttribute("rel", "noopener noreferrer")
}
return current
})
}
return DomPurify.sanitize(str, {
ADD_ATTR: ["target"],
FORBID_TAGS: ["style", "form"],
ALLOW_DATA_ATTR,
FORBID_ATTR,
})
Expected behaviour
Swagger UI should create a scoped DOMPurify instance using DOMPurify(), so hooks are registered only on that instance and the global object is never modified.
Proposed fix
const customDomPurify = DomPurify(window)
customDomPurify.addHook("beforeSanitizeElements", function (current) {
if (current.href) {
current.setAttribute("rel", "noopener noreferrer")
}
return current
})
return customDomPurify.sanitize(str, {
ADD_ATTR: ["target"],
FORBID_TAGS: ["style", "form"],
ALLOW_DATA_ATTR,
FORBID_ATTR,
})
This is the approach recommended by the DOMPurify docs for library authors β creating a fresh instance via DOMPurify(window) ensures hooks are scoped and do not pollute the global object.
Description
Swagger UI calls
DOMPurify.addHook(...)on the global DOMPurify object. This is a side effect that leaks beyond Swagger UI's scope β any other code sharing the same DOMPurify instance will unexpectedly inherit the hook, which can cause subtle bugs or unintended behaviour in host applications.Location
This occurs in
src/core/components/providers/markdown.jsx.Known impact
This is causing a bug in Backstage where the globally registered
beforeSanitizeElementshook overwrites therelattribute on any element with anhref, including<link>stylesheet elements. As a result, stylesheet links have theirrel="stylesheet"replaced withrel="noopener noreferrer", preventing stylesheets from loading and causing TechDocs pages to render as a blank white screen. See backstage/backstage#34037 (comment) for details.Current behaviour
Expected behaviour
Swagger UI should create a scoped DOMPurify instance using
DOMPurify(), so hooks are registered only on that instance and the global object is never modified.Proposed fix
This is the approach recommended by the DOMPurify docs for library authors β creating a fresh instance via
DOMPurify(window)ensures hooks are scoped and do not pollute the global object.