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", "author": "Calvin Montgomery",
"name": "CyTube", "name": "CyTube",
"description": "Online media synchronizer and chat", "description": "Online media synchronizer and chat",
"version": "3.39.4", "version": "3.39.5",
"repository": { "repository": {
"url": "http://github.com/calzoneman/sync" "url": "http://github.com/calzoneman/sync"
}, },

View file

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

View file

@ -1,3 +1,5 @@
const SPECIALCHARS = /([\\\.\?\+\*\$\^\|\(\)\[\]\{\}])/g;
class CamoConfig { class CamoConfig {
constructor(config = { camo: { enabled: false } }) { constructor(config = { camo: { enabled: false } }) {
this.config = config.camo; this.config = config.camo;
@ -30,6 +32,17 @@ class CamoConfig {
return this.config['whitelisted-domains'] || []; 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() { getEncoding() {
return this.config.encoding || 'url'; return this.config.encoding || 'url';
} }

View file

@ -7,7 +7,7 @@ describe('Camo', () => {
camo: { camo: {
server: 'http://localhost:8081', server: 'http://localhost:8081',
key: '9LKC7708ZHOVRCTLOLE3G2YJ0U1T8F96', key: '9LKC7708ZHOVRCTLOLE3G2YJ0U1T8F96',
'whitelisted-domains': ['def.xyz'], 'whitelisted-domains': ['def.xyz', 'tii.kzz.qqq'],
encoding: 'hex' encoding: 'hex'
} }
}); });
@ -36,6 +36,28 @@ describe('Camo', () => {
const result = Camo.camoify(config, 'http://def.xyz/image.jpeg'); const result = Camo.camoify(config, 'http://def.xyz/image.jpeg');
assert.strictEqual(result, 'https://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', () => { describe('#transformImgTags', () => {

View file

@ -39,4 +39,18 @@ describe('CamoConfig', () => {
assert.deepStrictEqual(new CamoConfig().getEncoding(), 'url'); 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);
});
});
}); });