camo: include subdomains of whitelisted domains in whitelist

This commit is contained in:
Calvin Montgomery 2017-07-08 20:46:19 -07:00
parent 07179d6c83
commit 637bcad816
5 changed files with 53 additions and 4 deletions

View File

@ -2,7 +2,7 @@
"author": "Calvin Montgomery",
"name": "CyTube",
"description": "Online media synchronizer and chat",
"version": "3.39.4",
"version": "3.39.5",
"repository": {
"url": "http://github.com/calzoneman/sync"
},

View File

@ -6,9 +6,9 @@ import { CamoConfig } from './configuration/camoconfig';
const LOGGER = require('@calzoneman/jsli')('camo');
function isWhitelisted(camoConfig: CamoConfig, url: string): boolean {
const whitelistedDomains = camoConfig.getWhitelistedDomains();
const whitelistedDomains = camoConfig.getWhitelistedDomainsRegexp();
const parsed = urlparse.parse(url);
return whitelistedDomains.includes(parsed.hostname);
return whitelistedDomains.test('.' + parsed.hostname);
}
export function camoify(camoConfig: CamoConfig, url: string): string {

View File

@ -1,3 +1,5 @@
const SPECIALCHARS = /([\\\.\?\+\*\$\^\|\(\)\[\]\{\}])/g;
class CamoConfig {
constructor(config = { camo: { enabled: false } }) {
this.config = config.camo;
@ -30,6 +32,17 @@ class CamoConfig {
return this.config['whitelisted-domains'] || [];
}
getWhitelistedDomainsRegexp() {
const domains = this.getWhitelistedDomains()
.map(d => '\\.' + d.replace(SPECIALCHARS, '\\$1') + '$');
if (domains.length === 0) {
// If no whitelist, match nothing
return new RegExp('$^');
}
return new RegExp(domains.join('|'), 'i');
}
getEncoding() {
return this.config.encoding || 'url';
}

View File

@ -7,7 +7,7 @@ describe('Camo', () => {
camo: {
server: 'http://localhost:8081',
key: '9LKC7708ZHOVRCTLOLE3G2YJ0U1T8F96',
'whitelisted-domains': ['def.xyz'],
'whitelisted-domains': ['def.xyz', 'tii.kzz.qqq'],
encoding: 'hex'
}
});
@ -36,6 +36,28 @@ describe('Camo', () => {
const result = Camo.camoify(config, 'http://def.xyz/image.jpeg');
assert.strictEqual(result, 'https://def.xyz/image.jpeg');
});
it('bypasses camo for whitelisted domains subdomains', () => {
const result = Camo.camoify(config, 'http://abc.def.xyz/image.jpeg');
assert.strictEqual(result, 'https://abc.def.xyz/image.jpeg');
});
it('does not bypass camo for a non-subdomain match', () => {
const result = Camo.camoify(config, 'http://abcdef.xyz/image.jpeg');
assert.strictEqual(result, 'http://localhost:8081/19f53f65e8081a064cff54fbd665e8bb08612aa6/687474703a2f2f6162636465662e78797a2f696d6167652e6a706567');
});
it('does not bypass camo when no whitelist is configured', () => {
const config = new CamoConfig({
camo: {
server: 'http://localhost:8081',
key: '9LKC7708ZHOVRCTLOLE3G2YJ0U1T8F96',
encoding: 'hex'
}
});
const result = Camo.camoify(config, 'http://abcdef.xyz/image.jpeg');
assert.strictEqual(result, 'http://localhost:8081/19f53f65e8081a064cff54fbd665e8bb08612aa6/687474703a2f2f6162636465662e78797a2f696d6167652e6a706567');
});
});
describe('#transformImgTags', () => {

View File

@ -39,4 +39,18 @@ describe('CamoConfig', () => {
assert.deepStrictEqual(new CamoConfig().getEncoding(), 'url');
});
});
describe('#getWhitelistedDomainsRegexp', () => {
it('generates a regex based on the whitelisted domains', () => {
const config = new CamoConfig({
camo: {
server: 'localhost:8081',
'whitelisted-domains': ['abc.xyz', 'tii.kzz.qqq']
}
});
const re = config.getWhitelistedDomainsRegexp();
assert.deepStrictEqual(re, /\.abc\.xyz$|\.tii\.kzz\.qqq$/i);
});
});
});