diff options
Diffstat (limited to 'test/ng/sanitizeUriSpec.js')
| -rw-r--r-- | test/ng/sanitizeUriSpec.js | 230 |
1 files changed, 230 insertions, 0 deletions
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 |
