aboutsummaryrefslogtreecommitdiffstats
path: root/test/ng/sanitizeUriSpec.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/ng/sanitizeUriSpec.js')
-rw-r--r--test/ng/sanitizeUriSpec.js230
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