fix(compile): sanitize srcset attribute

Applies similar sanitization as is applie to img[src] to img[srcset],
while adapting to the different semantics and syntax of srcset.
This commit is contained in:
ltrillaud
2014-09-08 11:03:28 +02:00
committed by Jeff Cross
parent 8199f4dbde
commit ab80cd9066
4 changed files with 135 additions and 8 deletions

View File

@@ -5870,6 +5870,74 @@ describe('$compile', function() {
});
});
describe('img[srcset] sanitization', function() {
it('should NOT require trusted values for img srcset', inject(function($rootScope, $compile, $sce) {
element = $compile('<img srcset="{{testUrl}}"></img>')($rootScope);
$rootScope.testUrl = 'http://example.com/image.png';
$rootScope.$digest();
expect(element.attr('srcset')).toEqual('http://example.com/image.png');
// But it should accept trusted values anyway.
$rootScope.testUrl = $sce.trustAsUrl('http://example.com/image2.png');
$rootScope.$digest();
expect(element.attr('srcset')).toEqual('http://example.com/image2.png');
}));
it('should use $$sanitizeUri', function() {
var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
module(function($provide) {
$provide.value('$$sanitizeUri', $$sanitizeUri);
});
inject(function($compile, $rootScope) {
element = $compile('<img srcset="{{testUrl}}"></img>')($rootScope);
$rootScope.testUrl = "someUrl";
$$sanitizeUri.andReturn('someSanitizedUrl');
$rootScope.$apply();
expect(element.attr('srcset')).toBe('someSanitizedUrl');
expect($$sanitizeUri).toHaveBeenCalledWith($rootScope.testUrl, true);
});
});
it('should sanitize all uris in srcset', inject(function($rootScope, $compile) {
/*jshint scripturl:true*/
element = $compile('<img srcset="{{testUrl}}"></img>')($rootScope);
var testSet = {
'http://example.com/image.png':'http://example.com/image.png',
' http://example.com/image.png':'http://example.com/image.png',
'http://example.com/image.png ':'http://example.com/image.png',
'http://example.com/image.png 128w':'http://example.com/image.png 128w',
'http://example.com/image.png 2x':'http://example.com/image.png 2x',
'http://example.com/image.png 1.5x':'http://example.com/image.png 1.5x',
'http://example.com/image1.png 1x,http://example.com/image2.png 2x':'http://example.com/image1.png 1x,http://example.com/image2.png 2x',
'http://example.com/image1.png 1x ,http://example.com/image2.png 2x':'http://example.com/image1.png 1x ,http://example.com/image2.png 2x',
'http://example.com/image1.png 1x, http://example.com/image2.png 2x':'http://example.com/image1.png 1x,http://example.com/image2.png 2x',
'http://example.com/image1.png 1x , http://example.com/image2.png 2x':'http://example.com/image1.png 1x ,http://example.com/image2.png 2x',
'http://example.com/image1.png 48w,http://example.com/image2.png 64w':'http://example.com/image1.png 48w,http://example.com/image2.png 64w',
//Test regex to make sure doesn't mistake parts of url for width descriptors
'http://example.com/image1.png?w=48w,http://example.com/image2.png 64w':'http://example.com/image1.png?w=48w,http://example.com/image2.png 64w',
'http://example.com/image1.png 1x,http://example.com/image2.png 64w':'http://example.com/image1.png 1x,http://example.com/image2.png 64w',
'http://example.com/image1.png,http://example.com/image2.png':'http://example.com/image1.png ,http://example.com/image2.png',
'http://example.com/image1.png ,http://example.com/image2.png':'http://example.com/image1.png ,http://example.com/image2.png',
'http://example.com/image1.png, http://example.com/image2.png':'http://example.com/image1.png ,http://example.com/image2.png',
'http://example.com/image1.png , http://example.com/image2.png':'http://example.com/image1.png ,http://example.com/image2.png',
'http://example.com/image1.png 1x, http://example.com/image2.png 2x, http://example.com/image3.png 3x':
'http://example.com/image1.png 1x,http://example.com/image2.png 2x,http://example.com/image3.png 3x',
'javascript:doEvilStuff() 2x': 'unsafe:javascript:doEvilStuff() 2x',
'http://example.com/image1.png 1x,javascript:doEvilStuff() 2x':'http://example.com/image1.png 1x,unsafe:javascript:doEvilStuff() 2x',
'http://example.com/image1.jpg?x=a,b 1x,http://example.com/ima,ge2.jpg 2x':'http://example.com/image1.jpg?x=a,b 1x,http://example.com/ima,ge2.jpg 2x',
//Test regex to make sure doesn't mistake parts of url for pixel density descriptors
'http://example.com/image1.jpg?x=a2x,b 1x,http://example.com/ima,ge2.jpg 2x':'http://example.com/image1.jpg?x=a2x,b 1x,http://example.com/ima,ge2.jpg 2x'
};
forEach( testSet, function( ref, url) {
$rootScope.testUrl = url;
$rootScope.$digest();
expect(element.attr('srcset')).toEqual(ref);
});
}));
});
describe('a[href] sanitization', function() {

View File

@@ -8,13 +8,22 @@ describe('ngSrc', function() {
dealoc(element);
});
it('should not result empty string in img src', inject(function($rootScope, $compile) {
$rootScope.image = {};
element = $compile('<img ng-src="{{image.url}}">')($rootScope);
$rootScope.$digest();
expect(element.attr('src')).not.toBe('');
expect(element.attr('src')).toBe(undefined);
}));
describe('img[ng-src]', function() {
it('should not result empty string in img src', inject(function($rootScope, $compile) {
$rootScope.image = {};
element = $compile('<img ng-src="{{image.url}}">')($rootScope);
$rootScope.$digest();
expect(element.attr('src')).not.toBe('');
expect(element.attr('src')).toBe(undefined);
}));
it('should sanitize url', inject(function($rootScope, $compile) {
$rootScope.imageUrl = 'javascript:alert(1);';
element = $compile('<img ng-src="{{imageUrl}}">')($rootScope);
$rootScope.$digest();
expect(element.attr('src')).toBe('unsafe:javascript:alert(1);');
}));
});
describe('iframe[ng-src]', function() {
it('should pass through src attributes for the same domain', inject(function($compile, $rootScope) {

View File

@@ -1,3 +1,4 @@
/*jshint scripturl:true*/
'use strict';
describe('ngSrcset', function() {
@@ -13,4 +14,19 @@ describe('ngSrcset', function() {
$rootScope.$digest();
expect(element.attr('srcset')).toBeUndefined();
}));
it('should sanitize good urls', inject(function($rootScope, $compile) {
$rootScope.imageUrl = 'http://example.com/image1.png 1x, http://example.com/image2.png 2x';
element = $compile('<img ng-srcset="{{imageUrl}}">')($rootScope);
$rootScope.$digest();
expect(element.attr('srcset')).toBe('http://example.com/image1.png 1x,http://example.com/image2.png 2x');
}));
it('should sanitize evil url', inject(function($rootScope, $compile) {
$rootScope.imageUrl = 'http://example.com/image1.png 1x, javascript:doEvilStuff() 2x';
element = $compile('<img ng-srcset="{{imageUrl}}">')($rootScope);
$rootScope.$digest();
expect(element.attr('srcset')).toBe('http://example.com/image1.png 1x,unsafe:javascript:doEvilStuff() 2x');
}));
});