Make sure to escape cspSource

Good practice

Also makes sure we don't include full file uris in the csp
This commit is contained in:
Matt Bierner
2025-05-22 00:01:01 -07:00
parent 1d7ad01f17
commit 73f244c82b
2 changed files with 14 additions and 10 deletions

View File

@@ -94,7 +94,7 @@ export class MdDocumentRenderer {
<html style="${escapeAttribute(this._getSettingsOverrideStyles(config))}">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
${csp}
<meta http-equiv="Content-Security-Policy" content="${escapeAttribute(csp)}">
<meta id="vscode-markdown-preview-data"
data-settings="${escapeAttribute(JSON.stringify(initialData))}"
data-strings="${escapeAttribute(JSON.stringify(previewStrings))}"
@@ -230,20 +230,20 @@ export class MdDocumentRenderer {
resource: vscode.Uri,
nonce: string
): string {
const rule = provider.cspSource;
const rule = provider.cspSource.split(';')[0];
switch (this._cspArbiter.getSecurityLevelForResource(resource)) {
case MarkdownPreviewSecurityLevel.AllowInsecureContent:
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${rule} http: https: data:; media-src 'self' ${rule} http: https: data:; script-src 'nonce-${nonce}'; style-src 'self' ${rule} 'unsafe-inline' http: https: data:; font-src 'self' ${rule} http: https: data:;">`;
return `default-src 'none'; img-src 'self' ${rule} http: https: data:; media-src 'self' ${rule} http: https: data:; script-src 'nonce-${nonce}'; style-src 'self' ${rule} 'unsafe-inline' http: https: data:; font-src 'self' ${rule} http: https: data:;`;
case MarkdownPreviewSecurityLevel.AllowInsecureLocalContent:
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*; media-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*; script-src 'nonce-${nonce}'; style-src 'self' ${rule} 'unsafe-inline' https: data: http://localhost:* http://127.0.0.1:*; font-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*;">`;
return `default-src 'none'; img-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*; media-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*; script-src 'nonce-${nonce}'; style-src 'self' ${rule} 'unsafe-inline' https: data: http://localhost:* http://127.0.0.1:*; font-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*;`;
case MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent:
return '<meta http-equiv="Content-Security-Policy" content="">';
return ``;
case MarkdownPreviewSecurityLevel.Strict:
default:
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${rule} https: data:; media-src 'self' ${rule} https: data:; script-src 'nonce-${nonce}'; style-src 'self' ${rule} 'unsafe-inline' https: data:; font-src 'self' ${rule} https: data:;">`;
return `default-src 'none'; img-src 'self' ${rule} https: data:; media-src 'self' ${rule} https: data:; script-src 'nonce-${nonce}'; style-src 'self' ${rule} 'unsafe-inline' https: data:; font-src 'self' ${rule} https: data:;`;
}
}
}

View File

@@ -430,10 +430,14 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
get cspSource() {
return [
this._webviewPanel.webview.cspSource,
...this._contributionProvider.contributions.previewResourceRoots.map(root => {
const dirRoot = root.path.endsWith('/') ? root : root.with({ path: root.path + '/' });
return dirRoot.toString();
}),
// On web, we also need to allow loading of resources from contributed extensions
...this._contributionProvider.contributions.previewResourceRoots
.filter(root => root.scheme === 'http' || root.scheme === 'https')
.map(root => {
const dirRoot = root.path.endsWith('/') ? root : root.with({ path: root.path + '/' });
return dirRoot.toString();
}),
].join(' ');
}