2016-06-23 12:47:54 -04:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
2017-03-02 15:12:46 -05:00
|
|
|
import * as t from '@angular/core/testing/src/testing_internal';
|
2016-05-09 10:46:31 -04:00
|
|
|
|
|
|
|
import {getDOM} from '../../src/dom/dom_adapter';
|
2016-06-24 10:54:11 -04:00
|
|
|
import {sanitizeSrcset, sanitizeUrl} from '../../src/security/url_sanitizer';
|
2016-05-03 21:41:31 -04:00
|
|
|
|
2017-12-16 17:42:55 -05:00
|
|
|
{
|
2016-05-03 21:41:31 -04:00
|
|
|
t.describe('URL sanitizer', () => {
|
2016-05-09 10:46:31 -04:00
|
|
|
let logMsgs: string[];
|
|
|
|
let originalLog: (msg: any) => any;
|
|
|
|
|
|
|
|
t.beforeEach(() => {
|
|
|
|
logMsgs = [];
|
|
|
|
originalLog = getDOM().log; // Monkey patch DOM.log.
|
|
|
|
getDOM().log = (msg) => logMsgs.push(msg);
|
|
|
|
});
|
|
|
|
t.afterEach(() => { getDOM().log = originalLog; });
|
|
|
|
|
|
|
|
t.it('reports unsafe URLs', () => {
|
|
|
|
t.expect(sanitizeUrl('javascript:evil()')).toBe('unsafe:javascript:evil()');
|
|
|
|
t.expect(logMsgs.join('\n')).toMatch(/sanitizing unsafe URL value/);
|
|
|
|
});
|
|
|
|
|
2016-05-03 21:41:31 -04:00
|
|
|
t.describe('valid URLs', () => {
|
|
|
|
const validUrls = [
|
|
|
|
'',
|
|
|
|
'http://abc',
|
|
|
|
'HTTP://abc',
|
|
|
|
'https://abc',
|
|
|
|
'HTTPS://abc',
|
|
|
|
'ftp://abc',
|
|
|
|
'FTP://abc',
|
|
|
|
'mailto:me@example.com',
|
|
|
|
'MAILTO:me@example.com',
|
|
|
|
'tel:123-123-1234',
|
|
|
|
'TEL:123-123-1234',
|
|
|
|
'#anchor',
|
|
|
|
'/page1.md',
|
2016-05-15 05:44:52 -04:00
|
|
|
'http://JavaScript/my.js',
|
|
|
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated.
|
|
|
|
'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
2016-06-24 10:54:11 -04:00
|
|
|
'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
2016-05-03 21:41:31 -04:00
|
|
|
];
|
2016-11-12 08:08:58 -05:00
|
|
|
for (const url of validUrls) {
|
2016-05-03 21:41:31 -04:00
|
|
|
t.it(`valid ${url}`, () => t.expect(sanitizeUrl(url)).toEqual(url));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
t.describe('invalid URLs', () => {
|
|
|
|
const invalidUrls = [
|
|
|
|
'javascript:evil()',
|
|
|
|
'JavaScript:abc',
|
|
|
|
'evilNewProtocol:abc',
|
|
|
|
' \n Java\n Script:abc',
|
|
|
|
'javascript:',
|
|
|
|
'javascript:',
|
|
|
|
'j avascript:',
|
|
|
|
'javascript:',
|
|
|
|
'javascript:',
|
|
|
|
'jav	ascript:alert();',
|
|
|
|
'jav\u0000ascript:alert();',
|
2016-05-15 05:44:52 -04:00
|
|
|
'data:;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
|
|
|
'data:,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
|
|
|
'data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
|
|
|
'data:text/javascript;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
|
|
|
'data:application/x-msdownload;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
2016-05-03 21:41:31 -04:00
|
|
|
];
|
2016-11-12 08:08:58 -05:00
|
|
|
for (const url of invalidUrls) {
|
2016-05-03 21:41:31 -04:00
|
|
|
t.it(`valid ${url}`, () => t.expect(sanitizeUrl(url)).toMatch(/^unsafe:/));
|
|
|
|
}
|
|
|
|
});
|
2016-06-24 10:54:11 -04:00
|
|
|
|
|
|
|
t.describe('valid srcsets', () => {
|
|
|
|
const validSrcsets = [
|
|
|
|
'',
|
|
|
|
'http://angular.io/images/test.png',
|
|
|
|
'http://angular.io/images/test.png, http://angular.io/images/test.png',
|
|
|
|
'http://angular.io/images/test.png, http://angular.io/images/test.png, http://angular.io/images/test.png',
|
|
|
|
'http://angular.io/images/test.png 2x',
|
|
|
|
'http://angular.io/images/test.png 2x, http://angular.io/images/test.png 3x',
|
|
|
|
'http://angular.io/images/test.png 1.5x',
|
|
|
|
'http://angular.io/images/test.png 1.25x',
|
|
|
|
'http://angular.io/images/test.png 200w, http://angular.io/images/test.png 300w',
|
|
|
|
'https://angular.io/images/test.png, http://angular.io/images/test.png',
|
|
|
|
'http://angular.io:80/images/test.png, http://angular.io:8080/images/test.png',
|
|
|
|
'http://www.angular.io:80/images/test.png, http://www.angular.io:8080/images/test.png',
|
|
|
|
'https://angular.io/images/test.png, https://angular.io/images/test.png',
|
|
|
|
'//angular.io/images/test.png, //angular.io/images/test.png',
|
|
|
|
'/images/test.png, /images/test.png',
|
|
|
|
'images/test.png, images/test.png',
|
|
|
|
'http://angular.io/images/test.png?12345, http://angular.io/images/test.png?12345',
|
|
|
|
'http://angular.io/images/test.png?maxage, http://angular.io/images/test.png?maxage',
|
|
|
|
'http://angular.io/images/test.png?maxage=234, http://angular.io/images/test.png?maxage=234',
|
|
|
|
];
|
2016-11-12 08:08:58 -05:00
|
|
|
for (const srcset of validSrcsets) {
|
2016-06-24 10:54:11 -04:00
|
|
|
t.it(`valid ${srcset}`, () => t.expect(sanitizeSrcset(srcset)).toEqual(srcset));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
t.describe('invalid srcsets', () => {
|
|
|
|
const invalidSrcsets = [
|
|
|
|
'ht:tp://angular.io/images/test.png',
|
|
|
|
'http://angular.io/images/test.png, ht:tp://angular.io/images/test.png',
|
|
|
|
];
|
2016-11-12 08:08:58 -05:00
|
|
|
for (const srcset of invalidSrcsets) {
|
2016-06-24 10:54:11 -04:00
|
|
|
t.it(`valid ${srcset}`, () => t.expect(sanitizeSrcset(srcset)).toMatch(/unsafe:/));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-05-03 21:41:31 -04:00
|
|
|
});
|
|
|
|
}
|