Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/markdown-language-features/src/preview/security.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as vscode from 'vscode';
7
import { MarkdownPreviewManager } from './previewManager';
8
9
10
export const enum MarkdownPreviewSecurityLevel {
11
Strict = 0,
12
AllowInsecureContent = 1,
13
AllowScriptsAndAllContent = 2,
14
AllowInsecureLocalContent = 3
15
}
16
17
export interface ContentSecurityPolicyArbiter {
18
getSecurityLevelForResource(resource: vscode.Uri): MarkdownPreviewSecurityLevel;
19
20
setSecurityLevelForResource(resource: vscode.Uri, level: MarkdownPreviewSecurityLevel): Thenable<void>;
21
22
shouldAllowSvgsForResource(resource: vscode.Uri): void;
23
24
shouldDisableSecurityWarnings(): boolean;
25
26
setShouldDisableSecurityWarning(shouldShow: boolean): Thenable<void>;
27
}
28
29
export class ExtensionContentSecurityPolicyArbiter implements ContentSecurityPolicyArbiter {
30
private readonly _old_trusted_workspace_key = 'trusted_preview_workspace:';
31
private readonly _security_level_key = 'preview_security_level:';
32
private readonly _should_disable_security_warning_key = 'preview_should_show_security_warning:';
33
34
constructor(
35
private readonly _globalState: vscode.Memento,
36
private readonly _workspaceState: vscode.Memento
37
) { }
38
39
public getSecurityLevelForResource(resource: vscode.Uri): MarkdownPreviewSecurityLevel {
40
// Use new security level setting first
41
const level = this._globalState.get<MarkdownPreviewSecurityLevel | undefined>(this._security_level_key + this._getRoot(resource), undefined);
42
if (typeof level !== 'undefined') {
43
return level;
44
}
45
46
// Fallback to old trusted workspace setting
47
if (this._globalState.get<boolean>(this._old_trusted_workspace_key + this._getRoot(resource), false)) {
48
return MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent;
49
}
50
return MarkdownPreviewSecurityLevel.Strict;
51
}
52
53
public setSecurityLevelForResource(resource: vscode.Uri, level: MarkdownPreviewSecurityLevel): Thenable<void> {
54
return this._globalState.update(this._security_level_key + this._getRoot(resource), level);
55
}
56
57
public shouldAllowSvgsForResource(resource: vscode.Uri) {
58
const securityLevel = this.getSecurityLevelForResource(resource);
59
return securityLevel === MarkdownPreviewSecurityLevel.AllowInsecureContent || securityLevel === MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent;
60
}
61
62
public shouldDisableSecurityWarnings(): boolean {
63
return this._workspaceState.get<boolean>(this._should_disable_security_warning_key, false);
64
}
65
66
public setShouldDisableSecurityWarning(disabled: boolean): Thenable<void> {
67
return this._workspaceState.update(this._should_disable_security_warning_key, disabled);
68
}
69
70
private _getRoot(resource: vscode.Uri): vscode.Uri {
71
if (vscode.workspace.workspaceFolders) {
72
const folderForResource = vscode.workspace.getWorkspaceFolder(resource);
73
if (folderForResource) {
74
return folderForResource.uri;
75
}
76
77
if (vscode.workspace.workspaceFolders.length) {
78
return vscode.workspace.workspaceFolders[0].uri;
79
}
80
}
81
82
return resource;
83
}
84
}
85
86
export class PreviewSecuritySelector {
87
88
public constructor(
89
private readonly _cspArbiter: ContentSecurityPolicyArbiter,
90
private readonly _webviewManager: MarkdownPreviewManager
91
) { }
92
93
public async showSecuritySelectorForResource(resource: vscode.Uri): Promise<void> {
94
interface PreviewSecurityPickItem extends vscode.QuickPickItem {
95
readonly type: 'moreinfo' | 'toggle' | MarkdownPreviewSecurityLevel;
96
}
97
98
function markActiveWhen(when: boolean): string {
99
return when ? '• ' : '';
100
}
101
102
const currentSecurityLevel = this._cspArbiter.getSecurityLevelForResource(resource);
103
const selection = await vscode.window.showQuickPick<PreviewSecurityPickItem>(
104
[
105
{
106
type: MarkdownPreviewSecurityLevel.Strict,
107
label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.Strict) + vscode.l10n.t("Strict"),
108
description: vscode.l10n.t("Only load secure content"),
109
}, {
110
type: MarkdownPreviewSecurityLevel.AllowInsecureLocalContent,
111
label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.AllowInsecureLocalContent) + vscode.l10n.t("Allow insecure local content"),
112
description: vscode.l10n.t("Enable loading content over http served from localhost"),
113
}, {
114
type: MarkdownPreviewSecurityLevel.AllowInsecureContent,
115
label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.AllowInsecureContent) + vscode.l10n.t("Allow insecure content"),
116
description: vscode.l10n.t("Enable loading content over http"),
117
}, {
118
type: MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent,
119
label: markActiveWhen(currentSecurityLevel === MarkdownPreviewSecurityLevel.AllowScriptsAndAllContent) + vscode.l10n.t("Disable"),
120
description: vscode.l10n.t("Allow all content and script execution. Not recommended"),
121
}, {
122
type: 'moreinfo',
123
label: vscode.l10n.t("More Information"),
124
description: ''
125
}, {
126
type: 'toggle',
127
label: this._cspArbiter.shouldDisableSecurityWarnings()
128
? vscode.l10n.t("Enable preview security warnings in this workspace")
129
: vscode.l10n.t("Disable preview security warning in this workspace"),
130
description: vscode.l10n.t("Does not affect the content security level")
131
},
132
], {
133
placeHolder: vscode.l10n.t("Select security settings for Markdown previews in this workspace"),
134
});
135
if (!selection) {
136
return;
137
}
138
139
if (selection.type === 'moreinfo') {
140
vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=854414'));
141
return;
142
}
143
144
if (selection.type === 'toggle') {
145
this._cspArbiter.setShouldDisableSecurityWarning(!this._cspArbiter.shouldDisableSecurityWarnings());
146
this._webviewManager.refresh();
147
return;
148
} else {
149
await this._cspArbiter.setSecurityLevelForResource(resource, selection.type);
150
}
151
this._webviewManager.refresh();
152
}
153
}
154
155