Skip to content

Commit 383b36f

Browse files
committed
Improve link protection
1 parent e4ea93b commit 383b36f

2 files changed

Lines changed: 39 additions & 24 deletions

File tree

src/vs/platform/product/common/product.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export interface IProductConfiguration {
8787
};
8888
readonly portable?: string;
8989
readonly uiExtensions?: readonly string[];
90+
readonly linkProtectionTrustedDomains?: readonly string[];
9091
}
9192

9293
export interface IExeBasedExtensionTip {

src/vs/workbench/contrib/url/common/url.contribution.ts

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,29 +50,20 @@ Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions).registe
5050
localize('developer', 'Developer')
5151
);
5252

53-
const DEAFULT_TRUSTED_DOMAINS = [
54-
'https://code.visualstudio.com',
55-
'https://go.microsoft.com',
56-
'https://github.com',
57-
'https://marketplace.visualstudio.com',
58-
'https://vscode-auth.github.com'
59-
];
60-
6153
const configureTrustedDomainsHandler = async (
6254
quickInputService: IQuickInputService,
6355
storageService: IStorageService,
56+
linkProtectionTrustedDomains: string[],
6457
domainToConfigure?: string
6558
) => {
66-
let trustedDomains: string[] = DEAFULT_TRUSTED_DOMAINS;
67-
6859
try {
69-
const trustedDomainsSrc = storageService.get('http.trustedDomains', StorageScope.GLOBAL);
60+
const trustedDomainsSrc = storageService.get('http.linkProtectionTrustedDomains', StorageScope.GLOBAL);
7061
if (trustedDomainsSrc) {
71-
trustedDomains = JSON.parse(trustedDomainsSrc);
62+
linkProtectionTrustedDomains = JSON.parse(trustedDomainsSrc);
7263
}
7364
} catch (err) { }
7465

75-
const domainQuickPickItems: IQuickPickItem[] = trustedDomains
66+
const domainQuickPickItems: IQuickPickItem[] = linkProtectionTrustedDomains
7667
.filter(d => d !== '*')
7768
.map(d => {
7869
return {
@@ -88,12 +79,12 @@ const configureTrustedDomainsHandler = async (
8879
type: 'item',
8980
label: localize('openAllLinksWithoutPrompt', 'Open all links without prompt'),
9081
id: '*',
91-
picked: trustedDomains.indexOf('*') !== -1
82+
picked: linkProtectionTrustedDomains.indexOf('*') !== -1
9283
}
9384
];
9485

9586
let domainToConfigureItem: IQuickPickItem | undefined = undefined;
96-
if (domainToConfigure && trustedDomains.indexOf(domainToConfigure) === -1) {
87+
if (domainToConfigure && linkProtectionTrustedDomains.indexOf(domainToConfigure) === -1) {
9788
domainToConfigureItem = {
9889
type: 'item',
9990
label: domainToConfigure,
@@ -116,7 +107,7 @@ const configureTrustedDomainsHandler = async (
116107

117108
if (pickedResult) {
118109
const pickedDomains: string[] = pickedResult.map(r => r.id!);
119-
storageService.store('http.trustedDomains', JSON.stringify(pickedDomains), StorageScope.GLOBAL);
110+
storageService.store('http.linkProtectionTrustedDomains', JSON.stringify(pickedDomains), StorageScope.GLOBAL);
120111

121112
return pickedDomains;
122113
}
@@ -125,16 +116,26 @@ const configureTrustedDomainsHandler = async (
125116
};
126117

127118
const configureTrustedDomainCommand = {
128-
id: 'workbench.action.configureTrustedDomains',
119+
id: 'workbench.action.configureLinkProtectionTrustedDomains',
129120
description: {
130-
description: localize('configureTrustedDomains', 'Configure Trusted Domains'),
121+
description: localize('configureLinkProtectionTrustedDomains', 'Configure Trusted Domains for Link Protection'),
131122
args: [{ name: 'domainToConfigure', schema: { type: 'string' } }]
132123
},
133124
handler: (accessor: ServicesAccessor, domainToConfigure?: string) => {
134125
const quickInputService = accessor.get(IQuickInputService);
135126
const storageService = accessor.get(IStorageService);
136-
137-
return configureTrustedDomainsHandler(quickInputService, storageService, domainToConfigure);
127+
const productService = accessor.get(IProductService);
128+
129+
const trustedDomains = productService.linkProtectionTrustedDomains
130+
? [...productService.linkProtectionTrustedDomains]
131+
: [];
132+
133+
return configureTrustedDomainsHandler(
134+
quickInputService,
135+
storageService,
136+
trustedDomains,
137+
domainToConfigure
138+
);
138139
}
139140
};
140141

@@ -164,17 +165,22 @@ class OpenerValidatorContributions implements IWorkbenchContribution {
164165
return true;
165166
}
166167

167-
let trustedDomains: string[] = DEAFULT_TRUSTED_DOMAINS;
168+
let trustedDomains: string[] = this._productService.linkProtectionTrustedDomains
169+
? [...this._productService.linkProtectionTrustedDomains]
170+
: [];
171+
168172
try {
169-
const trustedDomainsSrc = this._storageService.get('http.trustedDomains', StorageScope.GLOBAL);
173+
const trustedDomainsSrc = this._storageService.get('http.linkProtectionTrustedDomains', StorageScope.GLOBAL);
170174
if (trustedDomainsSrc) {
171175
trustedDomains = JSON.parse(trustedDomainsSrc);
172176
}
173177
} catch (err) { }
174178

175179
const domainToOpen = `${scheme}://${authority}`;
176180

177-
if (isDomainTrusted(domainToOpen, trustedDomains)) {
181+
if (isLocalhostAuthority(authority)) {
182+
return true;
183+
} else if (isDomainTrusted(domainToOpen, trustedDomains)) {
178184
return true;
179185
} else {
180186
const choice = await this._dialogService.show(
@@ -201,7 +207,7 @@ class OpenerValidatorContributions implements IWorkbenchContribution {
201207
}
202208
// Configure Trusted Domains
203209
else if (choice === 2) {
204-
const pickedDomains = await configureTrustedDomainsHandler(this._quickInputService, this._storageService, domainToOpen);
210+
const pickedDomains = await configureTrustedDomainsHandler(this._quickInputService, this._storageService, trustedDomains, domainToOpen);
205211
if (pickedDomains.indexOf(domainToOpen) !== -1) {
206212
return true;
207213
}
@@ -218,6 +224,13 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
218224
LifecyclePhase.Restored
219225
);
220226

227+
const rLocalhost = /^localhost:\d+$/i;
228+
const r127 = /^127.0.0.1:\d+$/;
229+
230+
function isLocalhostAuthority(authority: string) {
231+
return rLocalhost.test(authority) || r127.test(authority);
232+
}
233+
221234
/**
222235
* Check whether a domain like https://www.microsoft.com matches
223236
* the list of trusted domains.
@@ -235,3 +248,4 @@ function isDomainTrusted(domain: string, trustedDomains: string[]) {
235248

236249
return false;
237250
}
251+

0 commit comments

Comments
 (0)