Skip to content

Commit

Permalink
Revert "fixes #385"
Browse files Browse the repository at this point in the history
This reverts commit 84f537a.

fixes #395
  • Loading branch information
joaomoreno committed Oct 16, 2019
1 parent a154e8c commit 107f68b
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 1 deletion.
71 changes: 70 additions & 1 deletion src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,58 @@ function toLanguagePackTags(translations: { id: string }[], languageId: string):
.reduce((r, t) => [...r, ...t], []);
}

/* This list is also maintained by the Marketplace team.
* Remember to reach out to them when adding new domains.
*/
const TrustedSVGSources = [
'api.bintray.com',
'api.travis-ci.com',
'api.travis-ci.org',
'app.fossa.io',
'badge.buildkite.com',
'badge.fury.io',
'badge.waffle.io',
'badgen.net',
'badges.frapsoft.com',
'badges.gitter.im',
'badges.greenkeeper.io',
'cdn.travis-ci.com',
'cdn.travis-ci.org',
'ci.appveyor.com',
'circleci.com',
'cla.opensource.microsoft.com',
'codacy.com',
'codeclimate.com',
'codecov.io',
'coveralls.io',
'david-dm.org',
'deepscan.io',
'dev.azure.com',
'docs.rs',
'flat.badgen.net',
'gemnasium.com',
'githost.io',
'gitlab.com',
'godoc.org',
'goreportcard.com',
'img.shields.io',
'isitmaintained.com',
'marketplace.visualstudio.com',
'nodesecurity.io',
'opencollective.com',
'snyk.io',
'travis-ci.com',
'travis-ci.org',
'visualstudio.com',
'vsmarketplacebadge.apphb.com',
'www.bithound.io',
'www.versioneye.com'
];

function isHostTrusted(host: string): boolean {
return TrustedSVGSources.indexOf(host.toLowerCase()) > -1;
}

function isGitHubRepository(repository: string): boolean {
return /^https:\/\/github\.com\/|^git@github\.com:/.test(repository || '');
}
Expand Down Expand Up @@ -396,9 +448,13 @@ export class MarkdownProcessor extends BaseProcessor {
if (!/^https:$/i.test(srcUrl.protocol)) {
throw new Error(`Images in ${this.name} must come from an HTTPS source: ${src}`);
}

if (/\.svg$/i.test(srcUrl.pathname) && !isHostTrusted(srcUrl.host)) {
throw new Error(`SVGs are restricted in ${this.name}; please use other file image formats, such as PNG: ${src}`);
}
});

$('svg').each(() => {
$('svg').each((_, svg) => {
throw new Error(`SVG tags are not allowed in ${this.name}.`);
});

Expand Down Expand Up @@ -630,6 +686,19 @@ export function validateManifest(manifest: Manifest): Manifest {
throw new Error(`SVGs can't be used as icons: ${manifest.icon}`);
}

(manifest.badges || []).forEach(badge => {
const decodedUrl = decodeURI(badge.url);
const srcUrl = url.parse(decodedUrl);

if (!/^https:$/i.test(srcUrl.protocol)) {
throw new Error(`Badge URLs must come from an HTTPS source: ${badge.url}`);
}

if (/\.svg$/i.test(srcUrl.pathname) && !isHostTrusted(srcUrl.host)) {
throw new Error(`Badge SVGs are restricted. Please use other file image formats, such as PNG: ${badge.url}`);
}
});

Object.keys((manifest.dependencies || {})).forEach(dep => {
if (dep === 'vscode') {
throw new Error(`You should not depend on 'vscode' in your 'dependencies'. Did you mean to add it to 'devDependencies'?`);
Expand Down
57 changes: 57 additions & 0 deletions src/test/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,25 @@ describe('validateManifest', () => {
assert(validateManifest(createManifest({ icon: 'icon.png' })));
assert.throws(() => { validateManifest(createManifest({ icon: 'icon.svg' })); });
});

it('should prevent badges from non HTTPS sources', () => {
assert.throws(() => { validateManifest(createManifest({ badges: [{ url: 'relative.png', href: 'http://badgeurl', description: 'this is a badge' }] })); });
assert.throws(() => { validateManifest(createManifest({ badges: [{ url: 'relative.svg', href: 'http://badgeurl', description: 'this is a badge' }] })); });
assert.throws(() => { validateManifest(createManifest({ badges: [{ url: 'http://badgeurl.png', href: 'http://badgeurl', description: 'this is a badge' }] })); });
});

it('should allow non SVG badges', () => {
assert(validateManifest(createManifest({ badges: [{ url: 'https://host/badge.png', href: 'http://badgeurl', description: 'this is a badge' }] })));
});

it('should allow SVG badges from trusted sources', () => {
assert(validateManifest(createManifest({ badges: [{ url: 'https://gemnasium.com/foo.svg', href: 'http://badgeurl', description: 'this is a badge' }] })));
});

it('should prevent SVG badges from non trusted sources', () => {
assert.throws(() => { assert(validateManifest(createManifest({ badges: [{ url: 'https://github.com/foo.svg', href: 'http://badgeurl', description: 'this is a badge' }] }))); });
assert.throws(() => { assert(validateManifest(createManifest({ badges: [{ url: 'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/410.sv%67', href: 'http://badgeurl', description: 'this is a badge' }] }))); });
});
});

describe('toVsixManifest', () => {
Expand Down Expand Up @@ -1577,6 +1596,44 @@ describe('MarkdownProcessor', () => {
await throws(() => processor.onFile(readme));
});

it('should prevent SVGs from not trusted sources', async () => {
const manifest = { name: 'test', publisher: 'mocha', version: '0.0.1', engines: Object.create(null), repository: 'https://github.com/username/repository' };
const contents = `![title](https://foo/hello.svg)`;
const processor = new ReadmeProcessor(manifest, {});
const readme = { path: 'extension/readme.md', contents };

await throws(() => processor.onFile(readme));
});

it('should allow SVGs from trusted sources', async () => {
const manifest = { name: 'test', publisher: 'mocha', version: '0.0.1', engines: Object.create(null), repository: 'https://github.com/username/repository' };
const contents = `![title](https://badges.gitter.im/hello.svg)`;
const processor = new ReadmeProcessor(manifest, {});
const readme = { path: 'extension/readme.md', contents };

const file = await processor.onFile(readme);
assert(file);
});

it('should prevent SVGs from not trusted sources in img tags', async () => {
const manifest = { name: 'test', publisher: 'mocha', version: '0.0.1', engines: Object.create(null), repository: 'https://github.com/username/repository' };
const contents = `<img src="https://foo/hello.svg" />`;
const processor = new ReadmeProcessor(manifest, {});
const readme = { path: 'extension/readme.md', contents };

await throws(() => processor.onFile(readme));
});

it('should allow SVGs from trusted sources in img tags', async () => {
const manifest = { name: 'test', publisher: 'mocha', version: '0.0.1', engines: Object.create(null), repository: 'https://github.com/username/repository' };
const contents = `<img src="https://badges.gitter.im/hello.svg" />`;
const processor = new ReadmeProcessor(manifest, {});
const readme = { path: 'extension/readme.md', contents };

const file = await processor.onFile(readme);
assert(file);
});

it('should prevent SVG tags', async () => {
const manifest = { name: 'test', publisher: 'mocha', version: '0.0.1', engines: Object.create(null), repository: 'https://github.com/username/repository' };
const contents = `<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path d="M224 387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.93 0 521.287 151.707 491.48 394.785 224 387.814z"/></svg>`;
Expand Down

0 comments on commit 107f68b

Please sign in to comment.