diff options
Diffstat (limited to 'test')
| -rwxr-xr-x | test/ng/compileSpec.js | 296 | ||||
| -rw-r--r-- | test/ng/sanitizeUriSpec.js | 230 | ||||
| -rw-r--r-- | test/ngSanitize/sanitizeSpec.js | 159 |
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(' a\ '); + }); + 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	ascript:alert("A");').not.toBeValidUrl(); - expect('jav
ascript:alert("B");').not.toBeValidUrl(); - expect('jav
 ascript:alert("C");').not.toBeValidUrl(); - expect('jav\u0000ascript:alert("D");').not.toBeValidUrl(); - expect('java\u0000\u0000script:alert("D");').not.toBeValidUrl(); - expect('  java\u0000\u0000script:alert("D");').not.toBeValidUrl(); + expect('jav	ascript:alert();').not.toBeValidUrl(); + expect('jav
ascript:alert();').not.toBeValidUrl(); + expect('jav
 ascript:alert();').not.toBeValidUrl(); + expect('jav\u0000ascript:alert();').not.toBeValidUrl(); + expect('java\u0000\u0000script:alert();').not.toBeValidUrl(); + expect('  java\u0000\u0000script:alert();').not.toBeValidUrl(); }); }); + }); - + describe('sanitizeText', function() { + it('should escape text', function() { + expect(sanitizeText('a<div>&</div>c')).toEqual('a<div>&</div>c'); + }); }); }); |
