mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-30 05:21:08 +01:00
Fix anchors and data images in extension pages
Fixes #144897 Refactors to have a single `hookDomPurifyHrefAndSrcSanitizer` function that handles sanitizing the href and src attributes. Also updates this function to allow fragment links `#` and data images
This commit is contained in:
@@ -1417,6 +1417,49 @@ export function detectFullscreen(): IDetectedFullscreen | null {
|
||||
|
||||
// -- sanitize and trusted html
|
||||
|
||||
/**
|
||||
* Hooks dompurify using `afterSanitizeAttributes` to check that all `href` and `src`
|
||||
* attributes are valid.
|
||||
*/
|
||||
export function hookDomPurifyHrefAndSrcSanitizer(allowedProtocols: readonly string[], allowDataImages = false): IDisposable {
|
||||
// https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html
|
||||
|
||||
// build an anchor to map URLs to
|
||||
const anchor = document.createElement('a');
|
||||
|
||||
dompurify.addHook('afterSanitizeAttributes', (node) => {
|
||||
// check all href/src attributes for validity
|
||||
for (const attr of ['href', 'src']) {
|
||||
if (node.hasAttribute(attr)) {
|
||||
const attrValue = node.getAttribute(attr) as string;
|
||||
if (attr === 'href' && attrValue.startsWith('#')) {
|
||||
// Allow fragment links
|
||||
continue;
|
||||
}
|
||||
|
||||
anchor.href = attrValue;
|
||||
if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ''))) {
|
||||
if (allowDataImages && attr === 'src' && anchor.href.startsWith('data:')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
node.removeAttribute(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return toDisposable(() => {
|
||||
dompurify.removeHook('afterSanitizeAttributes');
|
||||
});
|
||||
}
|
||||
|
||||
const defaultSafeProtocols = [
|
||||
Schemas.http,
|
||||
Schemas.https,
|
||||
Schemas.command,
|
||||
];
|
||||
|
||||
/**
|
||||
* Sanitizes the given `value` and reset the given `node` with it.
|
||||
*/
|
||||
@@ -1428,29 +1471,12 @@ export function safeInnerHtml(node: HTMLElement, value: string): void {
|
||||
RETURN_DOM_FRAGMENT: false,
|
||||
};
|
||||
|
||||
const allowedProtocols = [Schemas.http, Schemas.https, Schemas.command];
|
||||
|
||||
// https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html
|
||||
dompurify.addHook('afterSanitizeAttributes', (node) => {
|
||||
// build an anchor to map URLs to
|
||||
const anchor = document.createElement('a');
|
||||
|
||||
// check all href/src attributes for validity
|
||||
for (const attr in ['href', 'src']) {
|
||||
if (node.hasAttribute(attr)) {
|
||||
anchor.href = node.getAttribute(attr) as string;
|
||||
if (!allowedProtocols.includes(anchor.protocol)) {
|
||||
node.removeAttribute(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const hook = hookDomPurifyHrefAndSrcSanitizer(defaultSafeProtocols);
|
||||
try {
|
||||
const html = dompurify.sanitize(value, { ...options, RETURN_TRUSTED_TYPE: true });
|
||||
node.innerHTML = html as unknown as string;
|
||||
} finally {
|
||||
dompurify.removeHook('afterSanitizeAttributes');
|
||||
hook.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user