aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/ng/compileSpec.js296
-rw-r--r--test/ng/sanitizeUriSpec.js230
-rw-r--r--test/ngSanitize/sanitizeSpec.js159
3 files changed, 394 insertions, 291 deletions
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 80788b02..6de96f65 100755
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -3834,6 +3834,7 @@ describe('$compile', function() {
describe('img[src] sanitization', function() {
+
it('should NOT require trusted values for img src', inject(function($rootScope, $compile, $sce) {
element = $compile('<img src="{{testUrl}}"></img>')($rootScope);
$rootScope.testUrl = 'http://example.com/image.png';
@@ -3845,127 +3846,6 @@ describe('$compile', function() {
expect(element.attr('src')).toEqual('http://example.com/image2.png');
}));
- it('should sanitize javascript: urls', inject(function($compile, $rootScope) {
- element = $compile('<img src="{{testUrl}}"></a>')($rootScope);
- $rootScope.testUrl = "javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('unsafe:javascript:doEvilStuff()');
- }));
-
- it('should sanitize non-image data: urls', inject(function($compile, $rootScope) {
- element = $compile('<img src="{{testUrl}}"></a>')($rootScope);
- $rootScope.testUrl = "data:application/javascript;charset=US-ASCII,alert('evil!');";
- $rootScope.$apply();
- expect(element.attr('src')).toBe("unsafe:data:application/javascript;charset=US-ASCII,alert('evil!');");
- $rootScope.testUrl = "data:,foo";
- $rootScope.$apply();
- expect(element.attr('src')).toBe("unsafe:data:,foo");
- }));
-
-
- it('should not sanitize data: URIs for images', inject(function($compile, $rootScope) {
- element = $compile('<img src="{{dataUri}}"></img>')($rootScope);
-
- // image data uri
- // ref: http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
- $rootScope.dataUri = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
- }));
-
-
- // Fails on IE <= 10 with "TypeError: Access is denied" when trying to set img[src]
- if (!msie || msie > 10) {
- it('should sanitize mailto: urls', inject(function($compile, $rootScope) {
- element = $compile('<img src="{{testUrl}}"></a>')($rootScope);
- $rootScope.testUrl = "mailto:foo@bar.com";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('unsafe:mailto:foo@bar.com');
- }));
- }
-
- it('should sanitize obfuscated javascript: urls', inject(function($compile, $rootScope) {
- element = $compile('<img src="{{testUrl}}"></img>')($rootScope);
-
- // case-sensitive
- $rootScope.testUrl = "JaVaScRiPt:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].src).toBe('unsafe:javascript:doEvilStuff()');
-
- // tab in protocol
- $rootScope.testUrl = "java\u0009script:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].src).toMatch(/(http:\/\/|unsafe:javascript:doEvilStuff\(\))/);
-
- // space before
- $rootScope.testUrl = " javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].src).toBe('unsafe:javascript:doEvilStuff()');
-
- // ws chars before
- $rootScope.testUrl = " \u000e javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].src).toMatch(/(http:\/\/|unsafe:javascript:doEvilStuff\(\))/);
-
- // post-fixed with proper url
- $rootScope.testUrl = "javascript:doEvilStuff(); http://make.me/look/good";
- $rootScope.$apply();
- expect(element[0].src).toBeOneOf(
- 'unsafe:javascript:doEvilStuff(); http://make.me/look/good',
- 'unsafe:javascript:doEvilStuff();%20http://make.me/look/good'
- );
- }));
-
- it('should sanitize ng-src bindings as well', inject(function($compile, $rootScope) {
- element = $compile('<img ng-src="{{testUrl}}"></img>')($rootScope);
- $rootScope.testUrl = "javascript:doEvilStuff()";
- $rootScope.$apply();
-
- expect(element[0].src).toBe('unsafe:javascript:doEvilStuff()');
- }));
-
-
- it('should not sanitize valid urls', inject(function($compile, $rootScope) {
- element = $compile('<img src="{{testUrl}}"></img>')($rootScope);
-
- $rootScope.testUrl = "foo/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('foo/bar');
-
- $rootScope.testUrl = "/foo/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('/foo/bar');
-
- $rootScope.testUrl = "../foo/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('../foo/bar');
-
- $rootScope.testUrl = "#foo";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('#foo');
-
- $rootScope.testUrl = "http://foo.com/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('http://foo.com/bar');
-
- $rootScope.testUrl = " http://foo.com/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe(' http://foo.com/bar');
-
- $rootScope.testUrl = "https://foo.com/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('https://foo.com/bar');
-
- $rootScope.testUrl = "ftp://foo.com/bar";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('ftp://foo.com/bar');
-
- $rootScope.testUrl = "file:///foo/bar.html";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('file:///foo/bar.html');
- }));
-
-
it('should not sanitize attributes other than src', inject(function($compile, $rootScope) {
element = $compile('<img title="{{testUrl}}"></img>')($rootScope);
$rootScope.testUrl = "javascript:doEvilStuff()";
@@ -3974,141 +3854,42 @@ describe('$compile', function() {
expect(element.attr('title')).toBe('javascript:doEvilStuff()');
}));
+ it('should use $$sanitizeUriProvider for reconfiguration of the src whitelist', function() {
+ module(function($compileProvider, $$sanitizeUriProvider) {
+ var newRe = /javascript:/,
+ returnVal;
+ expect($compileProvider.imgSrcSanitizationWhitelist()).toBe($$sanitizeUriProvider.imgSrcSanitizationWhitelist());
- it('should allow reconfiguration of the src whitelist', function() {
- module(function($compileProvider) {
- expect($compileProvider.imgSrcSanitizationWhitelist() instanceof RegExp).toBe(true);
- var returnVal = $compileProvider.imgSrcSanitizationWhitelist(/javascript:/);
+ returnVal = $compileProvider.imgSrcSanitizationWhitelist(newRe);
expect(returnVal).toBe($compileProvider);
+ expect($$sanitizeUriProvider.imgSrcSanitizationWhitelist()).toBe(newRe);
+ expect($compileProvider.imgSrcSanitizationWhitelist()).toBe(newRe);
});
+ inject(function() {
+ // needed to the module definition above is run...
+ });
+ });
+ it('should use $$sanitizeUri', function() {
+ var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
+ module(function($provide) {
+ $provide.value('$$sanitizeUri', $$sanitizeUri);
+ });
inject(function($compile, $rootScope) {
element = $compile('<img src="{{testUrl}}"></img>')($rootScope);
+ $rootScope.testUrl = "someUrl";
- // Fails on IE <= 11 with "TypeError: Object doesn't support this property or method" when
- // trying to set img[src]
- if (!msie || msie > 11) {
- $rootScope.testUrl = "javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element.attr('src')).toBe('javascript:doEvilStuff()');
- }
-
- $rootScope.testUrl = "http://recon/figured";
+ $$sanitizeUri.andReturn('someSanitizedUrl');
$rootScope.$apply();
- expect(element.attr('src')).toBe('unsafe:http://recon/figured');
+ expect(element.attr('src')).toBe('someSanitizedUrl');
+ expect($$sanitizeUri).toHaveBeenCalledWith($rootScope.testUrl, true);
});
});
-
});
describe('a[href] sanitization', function() {
- it('should sanitize javascript: urls', inject(function($compile, $rootScope) {
- element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
- $rootScope.testUrl = "javascript:doEvilStuff()";
- $rootScope.$apply();
-
- expect(element.attr('href')).toBe('unsafe:javascript:doEvilStuff()');
- }));
-
-
- it('should sanitize data: urls', inject(function($compile, $rootScope) {
- element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
- $rootScope.testUrl = "data:evilPayload";
- $rootScope.$apply();
-
- expect(element.attr('href')).toBe('unsafe:data:evilPayload');
- }));
-
-
- it('should sanitize obfuscated javascript: urls', inject(function($compile, $rootScope) {
- element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
-
- // case-sensitive
- $rootScope.testUrl = "JaVaScRiPt:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].href).toBe('unsafe:javascript:doEvilStuff()');
-
- // tab in protocol
- $rootScope.testUrl = "java\u0009script:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].href).toMatch(/(http:\/\/|unsafe:javascript:doEvilStuff\(\))/);
-
- // space before
- $rootScope.testUrl = " javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].href).toBe('unsafe:javascript:doEvilStuff()');
-
- // ws chars before
- $rootScope.testUrl = " \u000e javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element[0].href).toMatch(/(http:\/\/|unsafe:javascript:doEvilStuff\(\))/);
-
- // post-fixed with proper url
- $rootScope.testUrl = "javascript:doEvilStuff(); http://make.me/look/good";
- $rootScope.$apply();
- expect(element[0].href).toBeOneOf(
- 'unsafe:javascript:doEvilStuff(); http://make.me/look/good',
- 'unsafe:javascript:doEvilStuff();%20http://make.me/look/good'
- );
- }));
-
-
- it('should sanitize ngHref bindings as well', inject(function($compile, $rootScope) {
- element = $compile('<a ng-href="{{testUrl}}"></a>')($rootScope);
- $rootScope.testUrl = "javascript:doEvilStuff()";
- $rootScope.$apply();
-
- expect(element[0].href).toBe('unsafe:javascript:doEvilStuff()');
- }));
-
-
- it('should not sanitize valid urls', inject(function($compile, $rootScope) {
- element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
-
- $rootScope.testUrl = "foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('foo/bar');
-
- $rootScope.testUrl = "/foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('/foo/bar');
-
- $rootScope.testUrl = "../foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('../foo/bar');
-
- $rootScope.testUrl = "#foo";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('#foo');
-
- $rootScope.testUrl = "http://foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('http://foo/bar');
-
- $rootScope.testUrl = " http://foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe(' http://foo/bar');
-
- $rootScope.testUrl = "https://foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('https://foo/bar');
-
- $rootScope.testUrl = "ftp://foo/bar";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('ftp://foo/bar');
-
- $rootScope.testUrl = "mailto:foo@bar.com";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('mailto:foo@bar.com');
-
- $rootScope.testUrl = "file:///foo/bar.html";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('file:///foo/bar.html');
- }));
-
-
it('should not sanitize href on elements other than anchor', inject(function($compile, $rootScope) {
element = $compile('<div href="{{testUrl}}"></div>')($rootScope);
$rootScope.testUrl = "javascript:doEvilStuff()";
@@ -4117,7 +3898,6 @@ describe('$compile', function() {
expect(element.attr('href')).toBe('javascript:doEvilStuff()');
}));
-
it('should not sanitize attributes other than href', inject(function($compile, $rootScope) {
element = $compile('<a title="{{testUrl}}"></a>')($rootScope);
$rootScope.testUrl = "javascript:doEvilStuff()";
@@ -4126,26 +3906,38 @@ describe('$compile', function() {
expect(element.attr('title')).toBe('javascript:doEvilStuff()');
}));
+ it('should use $$sanitizeUriProvider for reconfiguration of the href whitelist', function() {
+ module(function($compileProvider, $$sanitizeUriProvider) {
+ var newRe = /javascript:/,
+ returnVal;
+ expect($compileProvider.aHrefSanitizationWhitelist()).toBe($$sanitizeUriProvider.aHrefSanitizationWhitelist());
- it('should allow reconfiguration of the href whitelist', function() {
- module(function($compileProvider) {
- expect($compileProvider.aHrefSanitizationWhitelist() instanceof RegExp).toBe(true);
- var returnVal = $compileProvider.aHrefSanitizationWhitelist(/javascript:/);
+ returnVal = $compileProvider.aHrefSanitizationWhitelist(newRe);
expect(returnVal).toBe($compileProvider);
+ expect($$sanitizeUriProvider.aHrefSanitizationWhitelist()).toBe(newRe);
+ expect($compileProvider.aHrefSanitizationWhitelist()).toBe(newRe);
+ });
+ inject(function() {
+ // needed to the module definition above is run...
});
+ });
+ it('should use $$sanitizeUri', function() {
+ var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
+ module(function($provide) {
+ $provide.value('$$sanitizeUri', $$sanitizeUri);
+ });
inject(function($compile, $rootScope) {
element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
+ $rootScope.testUrl = "someUrl";
- $rootScope.testUrl = "javascript:doEvilStuff()";
- $rootScope.$apply();
- expect(element.attr('href')).toBe('javascript:doEvilStuff()');
-
- $rootScope.testUrl = "http://recon/figured";
+ $$sanitizeUri.andReturn('someSanitizedUrl');
$rootScope.$apply();
- expect(element.attr('href')).toBe('unsafe:http://recon/figured');
+ expect(element.attr('href')).toBe('someSanitizedUrl');
+ expect($$sanitizeUri).toHaveBeenCalledWith($rootScope.testUrl, false);
});
});
+
});
describe('interpolation on HTML DOM event handler attributes onclick, onXYZ, formaction', function() {
diff --git a/test/ng/sanitizeUriSpec.js b/test/ng/sanitizeUriSpec.js
new file mode 100644
index 00000000..b9f6a0e2
--- /dev/null
+++ b/test/ng/sanitizeUriSpec.js
@@ -0,0 +1,230 @@
+'use strict';
+
+describe('sanitizeUri', function() {
+ var sanitizeHref, sanitizeImg, sanitizeUriProvider, testUrl;
+ beforeEach(function() {
+ module(function(_$$sanitizeUriProvider_) {
+ sanitizeUriProvider = _$$sanitizeUriProvider_;
+ });
+ inject(function($$sanitizeUri) {
+ sanitizeHref = function(uri) {
+ return $$sanitizeUri(uri, false);
+ };
+ sanitizeImg = function(uri) {
+ return $$sanitizeUri(uri, true);
+ }
+ });
+ });
+
+ function isEvilInCurrentBrowser(uri) {
+ var a = document.createElement('a');
+ a.setAttribute('href', uri);
+ return a.href.substring(0, 4) !== 'http';
+ }
+
+ describe('img[src] sanitization', function() {
+
+ it('should sanitize javascript: urls', function() {
+ testUrl = "javascript:doEvilStuff()";
+ expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+ });
+
+ it('should sanitize non-image data: urls', function() {
+ testUrl = "data:application/javascript;charset=US-ASCII,alert('evil!');";
+ expect(sanitizeImg(testUrl)).toBe("unsafe:data:application/javascript;charset=US-ASCII,alert('evil!');");
+
+ testUrl = "data:,foo";
+ expect(sanitizeImg(testUrl)).toBe("unsafe:data:,foo");
+ });
+
+ it('should not sanitize data: URIs for images', function() {
+ // image data uri
+ // ref: http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
+ testUrl = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
+ expect(sanitizeImg(testUrl)).toBe('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
+ });
+
+ it('should sanitize mailto: urls', function() {
+ testUrl = "mailto:foo@bar.com";
+ expect(sanitizeImg(testUrl)).toBe('unsafe:mailto:foo@bar.com');
+ });
+
+ it('should sanitize obfuscated javascript: urls', function() {
+ // case-sensitive
+ testUrl = "JaVaScRiPt:doEvilStuff()";
+ expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+
+ // tab in protocol
+ testUrl = "java\u0009script:doEvilStuff()";
+ if (isEvilInCurrentBrowser(testUrl)) {
+ expect(sanitizeImg(testUrl)).toEqual('unsafe:javascript:doEvilStuff()');
+ }
+
+ // space before
+ testUrl = " javascript:doEvilStuff()";
+ expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+
+ // ws chars before
+ testUrl = " \u000e javascript:doEvilStuff()";
+ if (isEvilInCurrentBrowser(testUrl)) {
+ expect(sanitizeImg(testUrl)).toEqual('unsafe:javascript:doEvilStuff()');
+ }
+
+ // post-fixed with proper url
+ testUrl = "javascript:doEvilStuff(); http://make.me/look/good";
+ expect(sanitizeImg(testUrl)).toBeOneOf(
+ 'unsafe:javascript:doEvilStuff(); http://make.me/look/good',
+ 'unsafe:javascript:doEvilStuff();%20http://make.me/look/good'
+ );
+ });
+
+ it('should sanitize ng-src bindings as well', function() {
+ testUrl = "javascript:doEvilStuff()";
+ expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+ });
+
+
+ it('should not sanitize valid urls', function() {
+ testUrl = "foo/bar";
+ expect(sanitizeImg(testUrl)).toBe('foo/bar');
+
+ testUrl = "/foo/bar";
+ expect(sanitizeImg(testUrl)).toBe('/foo/bar');
+
+ testUrl = "../foo/bar";
+ expect(sanitizeImg(testUrl)).toBe('../foo/bar');
+
+ testUrl = "#foo";
+ expect(sanitizeImg(testUrl)).toBe('#foo');
+
+ testUrl = "http://foo.com/bar";
+ expect(sanitizeImg(testUrl)).toBe('http://foo.com/bar');
+
+ testUrl = " http://foo.com/bar";
+ expect(sanitizeImg(testUrl)).toBe(' http://foo.com/bar');
+
+ testUrl = "https://foo.com/bar";
+ expect(sanitizeImg(testUrl)).toBe('https://foo.com/bar');
+
+ testUrl = "ftp://foo.com/bar";
+ expect(sanitizeImg(testUrl)).toBe('ftp://foo.com/bar');
+
+ testUrl = "file:///foo/bar.html";
+ expect(sanitizeImg(testUrl)).toBe('file:///foo/bar.html');
+ });
+
+
+ it('should allow reconfiguration of the src whitelist', function() {
+ var returnVal;
+ expect(sanitizeUriProvider.imgSrcSanitizationWhitelist() instanceof RegExp).toBe(true);
+ returnVal = sanitizeUriProvider.imgSrcSanitizationWhitelist(/javascript:/);
+ expect(returnVal).toBe(sanitizeUriProvider);
+
+ testUrl = "javascript:doEvilStuff()";
+ expect(sanitizeImg(testUrl)).toBe('javascript:doEvilStuff()');
+
+ testUrl = "http://recon/figured";
+ expect(sanitizeImg(testUrl)).toBe('unsafe:http://recon/figured');
+ });
+
+ });
+
+
+ describe('a[href] sanitization', function() {
+
+ it('should sanitize javascript: urls', inject(function() {
+ testUrl = "javascript:doEvilStuff()";
+ expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+ }));
+
+
+ it('should sanitize data: urls', inject(function() {
+ testUrl = "data:evilPayload";
+ expect(sanitizeHref(testUrl)).toBe('unsafe:data:evilPayload');
+ }));
+
+
+ it('should sanitize obfuscated javascript: urls', inject(function() {
+ // case-sensitive
+ testUrl = "JaVaScRiPt:doEvilStuff()";
+ expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+
+ // tab in protocol
+ testUrl = "java\u0009script:doEvilStuff()";
+ if (isEvilInCurrentBrowser(testUrl)) {
+ expect(sanitizeHref(testUrl)).toEqual('unsafe:javascript:doEvilStuff()');
+ }
+
+ // space before
+ testUrl = " javascript:doEvilStuff()";
+ expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+
+ // ws chars before
+ testUrl = " \u000e javascript:doEvilStuff()";
+ if (isEvilInCurrentBrowser(testUrl)) {
+ expect(sanitizeHref(testUrl)).toEqual('unsafe:javascript:doEvilStuff()');
+ }
+
+ // post-fixed with proper url
+ testUrl = "javascript:doEvilStuff(); http://make.me/look/good";
+ expect(sanitizeHref(testUrl)).toBeOneOf(
+ 'unsafe:javascript:doEvilStuff(); http://make.me/look/good',
+ 'unsafe:javascript:doEvilStuff();%20http://make.me/look/good'
+ );
+ }));
+
+
+ it('should sanitize ngHref bindings as well', inject(function() {
+ testUrl = "javascript:doEvilStuff()";
+ expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
+ }));
+
+
+ it('should not sanitize valid urls', inject(function() {
+ testUrl = "foo/bar";
+ expect(sanitizeHref(testUrl)).toBe('foo/bar');
+
+ testUrl = "/foo/bar";
+ expect(sanitizeHref(testUrl)).toBe('/foo/bar');
+
+ testUrl = "../foo/bar";
+ expect(sanitizeHref(testUrl)).toBe('../foo/bar');
+
+ testUrl = "#foo";
+ expect(sanitizeHref(testUrl)).toBe('#foo');
+
+ testUrl = "http://foo/bar";
+ expect(sanitizeHref(testUrl)).toBe('http://foo/bar');
+
+ testUrl = " http://foo/bar";
+ expect(sanitizeHref(testUrl)).toBe(' http://foo/bar');
+
+ testUrl = "https://foo/bar";
+ expect(sanitizeHref(testUrl)).toBe('https://foo/bar');
+
+ testUrl = "ftp://foo/bar";
+ expect(sanitizeHref(testUrl)).toBe('ftp://foo/bar');
+
+ testUrl = "mailto:foo@bar.com";
+ expect(sanitizeHref(testUrl)).toBe('mailto:foo@bar.com');
+
+ testUrl = "file:///foo/bar.html";
+ expect(sanitizeHref(testUrl)).toBe('file:///foo/bar.html');
+ }));
+
+ it('should allow reconfiguration of the href whitelist', function() {
+ var returnVal;
+ expect(sanitizeUriProvider.aHrefSanitizationWhitelist() instanceof RegExp).toBe(true);
+ returnVal = sanitizeUriProvider.aHrefSanitizationWhitelist(/javascript:/);
+ expect(returnVal).toBe(sanitizeUriProvider);
+
+ testUrl = "javascript:doEvilStuff()";
+ expect(sanitizeHref(testUrl)).toBe('javascript:doEvilStuff()');
+
+ testUrl = "http://recon/figured";
+ expect(sanitizeHref(testUrl)).toBe('unsafe:http://recon/figured');
+ });
+
+ });
+
+}); \ No newline at end of file
diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js
index 3d586830..1958ec0f 100644
--- a/test/ngSanitize/sanitizeSpec.js
+++ b/test/ngSanitize/sanitizeSpec.js
@@ -5,12 +5,15 @@ describe('HTML', function() {
var expectHTML;
beforeEach(module('ngSanitize'));
-
- beforeEach(inject(function($sanitize) {
+ beforeEach(function() {
expectHTML = function(html){
- return expect($sanitize(html));
+ var sanitize;
+ inject(function($sanitize) {
+ sanitize = $sanitize;
+ });
+ return expect(sanitize(html));
};
- }));
+ });
describe('htmlParser', function() {
if (angular.isUndefined(window.htmlParser)) return;
@@ -183,13 +186,22 @@ describe('HTML', function() {
toEqual('');
});
+ it('should keep spaces as prefix/postfix', function() {
+ expectHTML(' a ').toEqual(' a ');
+ });
+
+ it('should allow multiline strings', function() {
+ expectHTML('\na\n').toEqual('&#10;a\&#10;');
+ });
+
describe('htmlSanitizerWriter', function() {
if (angular.isUndefined(window.htmlSanitizeWriter)) return;
- var writer, html;
+ var writer, html, uriValidator;
beforeEach(function() {
html = '';
- writer = htmlSanitizeWriter({push:function(text){html+=text;}});
+ uriValidator = jasmine.createSpy('uriValidator');
+ writer = htmlSanitizeWriter({push:function(text){html+=text;}}, uriValidator);
});
it('should write basic HTML', function() {
@@ -258,41 +270,106 @@ describe('HTML', function() {
});
});
- describe('isUri', function() {
+ describe('uri validation', function() {
+ it('should call the uri validator', function() {
+ writer.start('a', {href:'someUrl'}, false);
+ expect(uriValidator).toHaveBeenCalledWith('someUrl', false);
+ uriValidator.reset();
+ writer.start('img', {src:'someImgUrl'}, false);
+ expect(uriValidator).toHaveBeenCalledWith('someImgUrl', true);
+ uriValidator.reset();
+ writer.start('someTag', {src:'someNonUrl'}, false);
+ expect(uriValidator).not.toHaveBeenCalled();
+ });
- function isUri(value) {
- return value.match(URI_REGEXP);
- }
+ it('should drop non valid uri attributes', function() {
+ uriValidator.andReturn(false);
+ writer.start('a', {href:'someUrl'}, false);
+ expect(html).toEqual('<a>');
- it('should be URI', function() {
- expect(isUri('http://abc')).toBeTruthy();
- expect(isUri('HTTP://abc')).toBeTruthy();
- expect(isUri('https://abc')).toBeTruthy();
- expect(isUri('HTTPS://abc')).toBeTruthy();
- expect(isUri('ftp://abc')).toBeTruthy();
- expect(isUri('FTP://abc')).toBeTruthy();
- expect(isUri('mailto:me@example.com')).toBeTruthy();
- expect(isUri('MAILTO:me@example.com')).toBeTruthy();
- expect(isUri('tel:123-123-1234')).toBeTruthy();
- expect(isUri('TEL:123-123-1234')).toBeTruthy();
- expect(isUri('#anchor')).toBeTruthy();
+ html = '';
+ uriValidator.andReturn(true);
+ writer.start('a', {href:'someUrl'}, false);
+ expect(html).toEqual('<a href="someUrl">');
});
+ });
+ });
- it('should not be URI', function() {
- expect(isUri('')).toBeFalsy();
- expect(isUri('javascript:alert')).toBeFalsy();
+ describe('uri checking', function() {
+ beforeEach(function() {
+ this.addMatchers({
+ toBeValidUrl: function() {
+ var sanitize;
+ inject(function($sanitize) {
+ sanitize = $sanitize;
+ });
+ var input = '<a href="'+this.actual+'"></a>';
+ return sanitize(input) === input;
+ },
+ toBeValidImageSrc: function() {
+ var sanitize;
+ inject(function($sanitize) {
+ sanitize = $sanitize;
+ });
+ var input = '<img src="'+this.actual+'"/>';
+ return sanitize(input) === input;
+ }
});
});
- describe('javascript URL attribute', function() {
- beforeEach(function() {
- this.addMatchers({
- toBeValidUrl: function() {
- return URI_REGEXP.exec(this.actual);
- }
- });
+ it('should use $$sanitizeUri for links', function() {
+ var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
+ module(function($provide) {
+ $provide.value('$$sanitizeUri', $$sanitizeUri);
});
+ inject(function() {
+ $$sanitizeUri.andReturn('someUri');
+ expectHTML('<a href="someUri"></a>').toEqual('<a href="someUri"></a>');
+ expect($$sanitizeUri).toHaveBeenCalledWith('someUri', false);
+
+ $$sanitizeUri.andReturn('unsafe:someUri');
+ expectHTML('<a href="someUri"></a>').toEqual('<a></a>');
+ });
+ });
+
+ it('should use $$sanitizeUri for links', function() {
+ var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
+ module(function($provide) {
+ $provide.value('$$sanitizeUri', $$sanitizeUri);
+ });
+ inject(function() {
+ $$sanitizeUri.andReturn('someUri');
+
+ expectHTML('<img src="someUri"/>').toEqual('<img src="someUri"/>');
+ expect($$sanitizeUri).toHaveBeenCalledWith('someUri', true);
+
+ $$sanitizeUri.andReturn('unsafe:someUri');
+ expectHTML('<img src="someUri"/>').toEqual('<img/>');
+ });
+ });
+
+ it('should be URI', function() {
+ expect('').toBeValidUrl();
+ expect('http://abc').toBeValidUrl();
+ expect('HTTP://abc').toBeValidUrl();
+ expect('https://abc').toBeValidUrl();
+ expect('HTTPS://abc').toBeValidUrl();
+ expect('ftp://abc').toBeValidUrl();
+ expect('FTP://abc').toBeValidUrl();
+ expect('mailto:me@example.com').toBeValidUrl();
+ expect('MAILTO:me@example.com').toBeValidUrl();
+ expect('tel:123-123-1234').toBeValidUrl();
+ expect('TEL:123-123-1234').toBeValidUrl();
+ expect('#anchor').toBeValidUrl();
+ expect('/page1.md').toBeValidUrl();
+ });
+
+ it('should not be URI', function() {
+ expect('javascript:alert').not.toBeValidUrl();
+ });
+
+ describe('javascript URLs', function() {
it('should ignore javascript:', function() {
expect('JavaScript:abc').not.toBeValidUrl();
expect(' \n Java\n Script:abc').not.toBeValidUrl();
@@ -318,15 +395,19 @@ describe('HTML', function() {
});
it('should ignore hex encoded whitespace javascript:', function() {
- expect('jav&#x09;ascript:alert("A");').not.toBeValidUrl();
- expect('jav&#x0A;ascript:alert("B");').not.toBeValidUrl();
- expect('jav&#x0A ascript:alert("C");').not.toBeValidUrl();
- expect('jav\u0000ascript:alert("D");').not.toBeValidUrl();
- expect('java\u0000\u0000script:alert("D");').not.toBeValidUrl();
- expect(' &#14; java\u0000\u0000script:alert("D");').not.toBeValidUrl();
+ expect('jav&#x09;ascript:alert();').not.toBeValidUrl();
+ expect('jav&#x0A;ascript:alert();').not.toBeValidUrl();
+ expect('jav&#x0A ascript:alert();').not.toBeValidUrl();
+ expect('jav\u0000ascript:alert();').not.toBeValidUrl();
+ expect('java\u0000\u0000script:alert();').not.toBeValidUrl();
+ expect(' &#14; java\u0000\u0000script:alert();').not.toBeValidUrl();
});
});
+ });
-
+ describe('sanitizeText', function() {
+ it('should escape text', function() {
+ expect(sanitizeText('a<div>&</div>c')).toEqual('a&lt;div&gt;&amp;&lt;/div&gt;c');
+ });
});
});