Skip to content

Commit

Permalink
Allow * in trustedDomains. Fix #79943
Browse files Browse the repository at this point in the history
  • Loading branch information
octref committed Aug 28, 2019
1 parent cc3770e commit 623c783
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 15 deletions.
59 changes: 44 additions & 15 deletions src/vs/workbench/contrib/url/common/url.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import { Action } from 'vs/base/common/actions';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import {
IWorkbenchContribution,
IWorkbenchContributionsRegistry,
Extensions as WorkbenchExtensions
} from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IProductService } from 'vs/platform/product/common/product';
Expand Down Expand Up @@ -130,12 +134,7 @@ const configureTrustedDomainCommand = {
? [...productService.linkProtectionTrustedDomains]
: [];

return configureTrustedDomainsHandler(
quickInputService,
storageService,
trustedDomains,
domainToConfigure
);
return configureTrustedDomainsHandler(quickInputService, storageService, trustedDomains, domainToConfigure);
}
};

Expand Down Expand Up @@ -178,9 +177,7 @@ class OpenerValidatorContributions implements IWorkbenchContribution {

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

if (isLocalhostAuthority(authority)) {
return true;
} else if (isDomainTrusted(domainToOpen, trustedDomains)) {
if (isURLDomainTrusted(resource, trustedDomains)) {
return true;
} else {
const choice = await this._dialogService.show(
Expand All @@ -207,7 +204,12 @@ class OpenerValidatorContributions implements IWorkbenchContribution {
}
// Configure Trusted Domains
else if (choice === 2) {
const pickedDomains = await configureTrustedDomainsHandler(this._quickInputService, this._storageService, trustedDomains, domainToOpen);
const pickedDomains = await configureTrustedDomainsHandler(
this._quickInputService,
this._storageService,
trustedDomains,
domainToOpen
);
if (pickedDomains.indexOf(domainToOpen) !== -1) {
return true;
}
Expand All @@ -224,8 +226,8 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
LifecyclePhase.Restored
);

const rLocalhost = /^localhost:\d+$/i;
const r127 = /^127.0.0.1:\d+$/;
const rLocalhost = /^localhost(:\d+)?$/i;
const r127 = /^127.0.0.1(:\d+)?$/;

function isLocalhostAuthority(authority: string) {
return rLocalhost.test(authority) || r127.test(authority);
Expand All @@ -234,8 +236,18 @@ function isLocalhostAuthority(authority: string) {
/**
* Check whether a domain like https://www.microsoft.com matches
* the list of trusted domains.
*
* - Schemes must match
* - There's no subdomain matching. For example https://microsoft.com doesn't match https://www.microsoft.com
* - Star matches all. For example https://*.microsoft.com matches https://www.microsoft.com
*/
function isDomainTrusted(domain: string, trustedDomains: string[]) {
export function isURLDomainTrusted(url: URI, trustedDomains: string[]) {
if (isLocalhostAuthority(url.authority)) {
return true;
}

const domain = `${url.scheme}://${url.authority}`;

for (let i = 0; i < trustedDomains.length; i++) {
if (trustedDomains[i] === '*') {
return true;
Expand All @@ -244,8 +256,25 @@ function isDomainTrusted(domain: string, trustedDomains: string[]) {
if (trustedDomains[i] === domain) {
return true;
}

if (trustedDomains[i].indexOf('*') !== -1) {
const parsedTrustedDomain = URI.parse(trustedDomains[i]);
if (url.scheme === parsedTrustedDomain.scheme) {
const authoritySegments = url.authority.split('.');
const trustedDomainAuthoritySegments = parsedTrustedDomain.authority.split('.');

if (authoritySegments.length === trustedDomainAuthoritySegments.length) {
if (
authoritySegments.every(
(val, i) => trustedDomainAuthoritySegments[i] === '*' || val === trustedDomainAuthoritySegments[i]
)
) {
return true;
}
}
}
}
}

return false;
}

42 changes: 42 additions & 0 deletions src/vs/workbench/test/contrib/linkProtection.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';

import { isURLDomainTrusted } from 'vs/workbench/contrib/url/common/url.contribution';
import { URI } from 'vs/base/common/uri';

suite('Link protection domain matching', () => {

test('simple', () => {
assert.ok(!isURLDomainTrusted(URI.parse('https://x.org'), []));
assert.ok(isURLDomainTrusted(URI.parse('https://x.org'), ['https://x.org']));
assert.ok(isURLDomainTrusted(URI.parse('https://x.org/foo'), ['https://x.org']));

assert.ok(!isURLDomainTrusted(URI.parse('https://x.org'), ['http://x.org']));
assert.ok(!isURLDomainTrusted(URI.parse('http://x.org'), ['https://x.org']));

assert.ok(!isURLDomainTrusted(URI.parse('https://www.x.org'), ['https://x.org']));

assert.ok(isURLDomainTrusted(URI.parse('https://www.x.org'), ['https://www.x.org', 'https://y.org']));
});

test('localhost', () => {
assert.ok(isURLDomainTrusted(URI.parse('https://127.0.0.1'), []));
assert.ok(isURLDomainTrusted(URI.parse('https://127.0.0.1:3000'), []));
assert.ok(isURLDomainTrusted(URI.parse('https://localhost'), []));
assert.ok(isURLDomainTrusted(URI.parse('https://localhost:3000'), []));
});

test('* star', () => {
assert.ok(isURLDomainTrusted(URI.parse('https://a.x.org'), ['https://*.x.org']));
assert.ok(isURLDomainTrusted(URI.parse('https://a.x.org'), ['https://a.x.*']));
assert.ok(isURLDomainTrusted(URI.parse('https://a.x.org'), ['https://a.*.org']));
assert.ok(isURLDomainTrusted(URI.parse('https://a.x.org'), ['https://*.*.org']));

assert.ok(!isURLDomainTrusted(URI.parse('https://a.b.c.org'), ['https://*.*.org']));
assert.ok(isURLDomainTrusted(URI.parse('https://a.b.c.org'), ['https://*.*.*.org']));
});
});

0 comments on commit 623c783

Please sign in to comment.