mirror of
https://github.com/Microsoft/vscode
synced 2024-09-19 10:40:41 +00:00
Fix #83731
This commit is contained in:
parent
e88e032d6a
commit
73d9d76ebd
|
@ -26,6 +26,8 @@ const TRUSTED_DOMAINS_STAT: IStat = {
|
|||
const CONFIG_HELP_TEXT_PRE = `// Links matching one or more entries in the list below can be opened without link protection.
|
||||
// The following examples show what entries can look like:
|
||||
// - "https://microsoft.com": Matches this specific domain using https
|
||||
// - "https://microsoft.com/foo": Matches https://microsoft.com/foo and https://microsoft.com/foo/bar,
|
||||
// but not https://microsoft.com/foobar or https://microsoft.com/bar
|
||||
// - "https://*.microsoft.com": Match all domains ending in "microsoft.com" using https
|
||||
// - "microsoft.com": Match this specific domain using either http or https
|
||||
// - "*.microsoft.com": Match all domains ending in "microsoft.com" using either http or https
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { equalsIgnoreCase } from 'vs/base/common/strings';
|
||||
import { equalsIgnoreCase, startsWith } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
@ -14,7 +14,10 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
|||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { configureOpenerTrustedDomainsHandler, readTrustedDomains } from 'vs/workbench/contrib/url/common/trustedDomains';
|
||||
import {
|
||||
configureOpenerTrustedDomainsHandler,
|
||||
readTrustedDomains
|
||||
} from 'vs/workbench/contrib/url/common/trustedDomains';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export class OpenerValidatorContributions implements IWorkbenchContribution {
|
||||
|
@ -132,10 +135,11 @@ export function isURLDomainTrusted(url: URI, trustedDomains: string[]) {
|
|||
}
|
||||
|
||||
if (url.authority === parsedTrustedDomain.authority) {
|
||||
return true;
|
||||
return pathMatches(url.path, parsedTrustedDomain.path);
|
||||
}
|
||||
|
||||
if (trustedDomains[i].indexOf('*') !== -1) {
|
||||
|
||||
let reversedAuthoritySegments = url.authority.split('.').reverse();
|
||||
const reversedTrustedDomainAuthoritySegments = parsedTrustedDomain.authority.split('.').reverse();
|
||||
|
||||
|
@ -146,11 +150,11 @@ export function isURLDomainTrusted(url: URI, trustedDomains: string[]) {
|
|||
reversedAuthoritySegments = reversedAuthoritySegments.slice(0, reversedTrustedDomainAuthoritySegments.length);
|
||||
}
|
||||
|
||||
if (
|
||||
reversedAuthoritySegments.every((val, i) => {
|
||||
return reversedTrustedDomainAuthoritySegments[i] === '*' || val === reversedTrustedDomainAuthoritySegments[i];
|
||||
})
|
||||
) {
|
||||
const authorityMatches = reversedAuthoritySegments.every((val, i) => {
|
||||
return reversedTrustedDomainAuthoritySegments[i] === '*' || val === reversedTrustedDomainAuthoritySegments[i];
|
||||
});
|
||||
|
||||
if (authorityMatches && pathMatches(url.path, parsedTrustedDomain.path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -158,3 +162,19 @@ export function isURLDomainTrusted(url: URI, trustedDomains: string[]) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
function pathMatches(open: string, rule: string) {
|
||||
if (rule === '/') {
|
||||
return true;
|
||||
}
|
||||
|
||||
const openSegments = open.split('/');
|
||||
const ruleSegments = rule.split('/');
|
||||
for (let i = 0; i < ruleSegments.length; i++) {
|
||||
if (ruleSegments[i] !== openSegments[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,49 +8,67 @@ import * as assert from 'assert';
|
|||
import { isURLDomainTrusted } from 'vs/workbench/contrib/url/common/trustedDomainsValidator';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
function linkProtectedByRules(link: string, rules: string[]) {
|
||||
assert.ok(isURLDomainTrusted(URI.parse(link), rules));
|
||||
function linkAllowedByRules(link: string, rules: string[]) {
|
||||
assert.ok(isURLDomainTrusted(URI.parse(link), rules), `Link\n${link}\n should be protected by rules\n${JSON.stringify(rules)}`);
|
||||
}
|
||||
function linkNotProtectedByRules(link: string, rules: string[]) {
|
||||
assert.ok(!isURLDomainTrusted(URI.parse(link), rules));
|
||||
function linkNotAllowedByRules(link: string, rules: string[]) {
|
||||
assert.ok(!isURLDomainTrusted(URI.parse(link), rules), `Link\n${link}\n should NOT be protected by rules\n${JSON.stringify(rules)}`);
|
||||
}
|
||||
|
||||
suite('Link protection domain matching', () => {
|
||||
test('simple', () => {
|
||||
linkNotProtectedByRules('https://x.org', []);
|
||||
linkNotAllowedByRules('https://x.org', []);
|
||||
|
||||
linkProtectedByRules('https://x.org', ['https://x.org']);
|
||||
linkProtectedByRules('https://x.org/foo', ['https://x.org']);
|
||||
linkAllowedByRules('https://x.org', ['https://x.org']);
|
||||
linkAllowedByRules('https://x.org/foo', ['https://x.org']);
|
||||
|
||||
linkNotProtectedByRules('https://x.org', ['http://x.org']);
|
||||
linkNotProtectedByRules('http://x.org', ['https://x.org']);
|
||||
linkNotAllowedByRules('https://x.org', ['http://x.org']);
|
||||
linkNotAllowedByRules('http://x.org', ['https://x.org']);
|
||||
|
||||
linkNotProtectedByRules('https://www.x.org', ['https://x.org']);
|
||||
linkNotAllowedByRules('https://www.x.org', ['https://x.org']);
|
||||
|
||||
linkProtectedByRules('https://www.x.org', ['https://www.x.org', 'https://y.org']);
|
||||
linkAllowedByRules('https://www.x.org', ['https://www.x.org', 'https://y.org']);
|
||||
});
|
||||
|
||||
test('localhost', () => {
|
||||
linkProtectedByRules('https://127.0.0.1', []);
|
||||
linkProtectedByRules('https://127.0.0.1:3000', []);
|
||||
linkProtectedByRules('https://localhost', []);
|
||||
linkProtectedByRules('https://localhost:3000', []);
|
||||
linkAllowedByRules('https://127.0.0.1', []);
|
||||
linkAllowedByRules('https://127.0.0.1:3000', []);
|
||||
linkAllowedByRules('https://localhost', []);
|
||||
linkAllowedByRules('https://localhost:3000', []);
|
||||
});
|
||||
|
||||
test('* star', () => {
|
||||
linkProtectedByRules('https://a.x.org', ['https://*.x.org']);
|
||||
linkProtectedByRules('https://a.b.x.org', ['https://*.x.org']);
|
||||
linkProtectedByRules('https://a.x.org', ['https://a.x.*']);
|
||||
linkProtectedByRules('https://a.x.org', ['https://a.*.org']);
|
||||
linkProtectedByRules('https://a.x.org', ['https://*.*.org']);
|
||||
linkProtectedByRules('https://a.b.x.org', ['https://*.b.*.org']);
|
||||
linkProtectedByRules('https://a.a.b.x.org', ['https://*.b.*.org']);
|
||||
linkAllowedByRules('https://a.x.org', ['https://*.x.org']);
|
||||
linkAllowedByRules('https://a.b.x.org', ['https://*.x.org']);
|
||||
linkAllowedByRules('https://a.x.org', ['https://a.x.*']);
|
||||
linkAllowedByRules('https://a.x.org', ['https://a.*.org']);
|
||||
linkAllowedByRules('https://a.x.org', ['https://*.*.org']);
|
||||
linkAllowedByRules('https://a.b.x.org', ['https://*.b.*.org']);
|
||||
linkAllowedByRules('https://a.a.b.x.org', ['https://*.b.*.org']);
|
||||
});
|
||||
|
||||
test('no scheme', () => {
|
||||
linkProtectedByRules('https://a.x.org', ['a.x.org']);
|
||||
linkProtectedByRules('https://a.x.org', ['*.x.org']);
|
||||
linkProtectedByRules('https://a.b.x.org', ['*.x.org']);
|
||||
linkProtectedByRules('https://x.org', ['*.x.org']);
|
||||
linkAllowedByRules('https://a.x.org', ['a.x.org']);
|
||||
linkAllowedByRules('https://a.x.org', ['*.x.org']);
|
||||
linkAllowedByRules('https://a.b.x.org', ['*.x.org']);
|
||||
linkAllowedByRules('https://x.org', ['*.x.org']);
|
||||
});
|
||||
|
||||
test('sub paths', () => {
|
||||
linkAllowedByRules('https://x.org/foo', ['https://x.org/foo']);
|
||||
linkAllowedByRules('https://x.org/foo', ['x.org/foo']);
|
||||
linkAllowedByRules('https://x.org/foo', ['*.org/foo']);
|
||||
|
||||
linkNotAllowedByRules('https://x.org/bar', ['https://x.org/foo']);
|
||||
linkNotAllowedByRules('https://x.org/bar', ['x.org/foo']);
|
||||
linkNotAllowedByRules('https://x.org/bar', ['*.org/foo']);
|
||||
|
||||
linkAllowedByRules('https://x.org/foo/bar', ['https://x.org/foo']);
|
||||
linkNotAllowedByRules('https://x.org/foo2', ['https://x.org/foo']);
|
||||
|
||||
linkNotAllowedByRules('https://www.x.org/foo', ['https://x.org/foo']);
|
||||
|
||||
linkNotAllowedByRules('https://a.x.org/bar', ['https://*.x.org/foo']);
|
||||
linkNotAllowedByRules('https://a.b.x.org/bar', ['https://*.x.org/foo']);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue