Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
refactor(SanitizeUriProvider): remove usages of whitelist
Browse files Browse the repository at this point in the history
Changes aHrefSanitizationWhitelist to aHrefSanitizationTrustedUri and imgSrcSanitizationWhitelist
to imgSrcSanitizationTrustedUri updating references to use the new symbols.

For the purposes of backward compatibility, the previous symbols are aliased to
the new symbols.
  • Loading branch information
josephperrott authored and petebacondarwin committed Sep 30, 2020
1 parent c953af6 commit 7673810
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 66 deletions.
4 changes: 2 additions & 2 deletions docs/content/guide/migration.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ break.

To fix this you need to ensure that the values used for binding to the affected
`xlink:href` contexts are considered safe URLs, e.g. by whitelisting them in
`$compileProvider`'s `aHrefSanitizationWhitelist` (for `<a>` elements) or
`imgSrcSanitizationWhitelist` (for `<image>` elements).
`$compileProvider`'s `aHrefSanitizationTrustedUri` (for `<a>` elements) or
`imgSrcSanitizationTrustedUri` (for `<image>` elements).

<hr />

Expand Down
32 changes: 17 additions & 15 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@
* By default, `$sce` will throw an error if it detects untrusted HTML content, and will not bind the
* content.
* However, if you include the {@link ngSanitize ngSanitize module}, it will try to sanitize the
* potentially dangerous HTML, e.g. strip non-whitelisted tags and attributes when binding to
* potentially dangerous HTML, e.g. strip non-trusted tags and attributes when binding to
* `innerHTML`.
*
* @example
Expand Down Expand Up @@ -1698,62 +1698,64 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {

/**
* @ngdoc method
* @name $compileProvider#aHrefSanitizationWhitelist
* @name $compileProvider#aHrefSanitizationTrustedUri
* @kind function
*
* @description
* Retrieves or overrides the default regular expression that is used for whitelisting of safe
* Retrieves or overrides the default regular expression that is used for determining trusted safe
* urls during a[href] sanitization.
*
* The sanitization is a security measure aimed at preventing XSS attacks via html links.
*
* Any url about to be assigned to a[href] via data-binding is first normalized and turned into
* an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
* an absolute url. Afterwards, the url is matched against the `aHrefSanitizationTrustedUri`
* regular expression. If a match is found, the original url is written into the dom. Otherwise,
* the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
*
* @param {RegExp=} regexp New regexp to whitelist urls with.
* @param {RegExp=} regexp New regexp to trust urls with.
* @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
* chaining otherwise.
*/
this.aHrefSanitizationWhitelist = function(regexp) {
this.aHrefSanitizationTrustedUri = function(regexp) {
if (isDefined(regexp)) {
$$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
$$sanitizeUriProvider.aHrefSanitizationTrustedUri(regexp);
return this;
} else {
return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
return $$sanitizeUriProvider.aHrefSanitizationTrustedUri();
}
};
this.aHrefSanitizationWhitelist = this.aHrefSanitizationTrustedUri;


/**
* @ngdoc method
* @name $compileProvider#imgSrcSanitizationWhitelist
* @name $compileProvider#imgSrcSanitizationTrustedUri
* @kind function
*
* @description
* Retrieves or overrides the default regular expression that is used for whitelisting of safe
* Retrieves or overrides the default regular expression that is used for determining trusted safe
* urls during img[src] sanitization.
*
* The sanitization is a security measure aimed at prevent XSS attacks via html links.
*
* Any url about to be assigned to img[src] via data-binding is first normalized and turned into
* an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
* an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationTrustedUri`
* regular expression. If a match is found, the original url is written into the dom. Otherwise,
* the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
*
* @param {RegExp=} regexp New regexp to whitelist urls with.
* @param {RegExp=} regexp New regexp to trust urls with.
* @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
* chaining otherwise.
*/
this.imgSrcSanitizationWhitelist = function(regexp) {
this.imgSrcSanitizationTrustedUri = function(regexp) {
if (isDefined(regexp)) {
$$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
$$sanitizeUriProvider.imgSrcSanitizationTrustedUri(regexp);
return this;
} else {
return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
return $$sanitizeUriProvider.imgSrcSanitizationTrustedUri();
}
};
this.imgSrcSanitizationWhitelist = this.imgSrcSanitizationTrustedUri;

/**
* @ngdoc method
Expand Down
31 changes: 16 additions & 15 deletions src/ng/sanitizeUri.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
*/
function $$SanitizeUriProvider() {

var aHrefSanitizationWhitelist = /^\s*(https?|s?ftp|mailto|tel|file):/,
imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
var aHrefSanitizationTrustedUri = /^\s*(https?|s?ftp|mailto|tel|file):/,
imgSrcSanitizationTrustedUri = /^\s*((https?|ftp|file|blob):|data:image\/)/;

/**
* @description
* Retrieves or overrides the default regular expression that is used for whitelisting of safe
* Retrieves or overrides the default regular expression that is used for determining trusted safe
* urls during a[href] sanitization.
*
* The sanitization is a security measure aimed at prevent XSS attacks via HTML anchor links.
Expand All @@ -21,27 +21,27 @@ function $$SanitizeUriProvider() {
* the $sce.URL security context. When interpolation occurs a call is made to `$sce.trustAsUrl(url)`
* which in turn may call `$$sanitizeUri(url, isMedia)` to sanitize the potentially malicious URL.
*
* If the URL matches the `aHrefSanitizationWhitelist` regular expression, it is returned unchanged.
* If the URL matches the `aHrefSanitizationTrustedUri` regular expression, it is returned unchanged.
*
* If there is no match the URL is returned prefixed with `'unsafe:'` to ensure that when it is written
* to the DOM it is inactive and potentially malicious code will not be executed.
*
* @param {RegExp=} regexp New regexp to whitelist urls with.
* @param {RegExp=} regexp New regexp to trust urls with.
* @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
* chaining otherwise.
*/
this.aHrefSanitizationWhitelist = function(regexp) {
this.aHrefSanitizationTrustedUri = function(regexp) {
if (isDefined(regexp)) {
aHrefSanitizationWhitelist = regexp;
aHrefSanitizationTrustedUri = regexp;
return this;
}
return aHrefSanitizationWhitelist;
return aHrefSanitizationTrustedUri;
};


/**
* @description
* Retrieves or overrides the default regular expression that is used for whitelisting of safe
* Retrieves or overrides the default regular expression that is used for determining trusted safe
* urls during img[src] sanitization.
*
* The sanitization is a security measure aimed at prevent XSS attacks via HTML image src links.
Expand All @@ -51,27 +51,28 @@ function $$SanitizeUriProvider() {
* `$sce.trustAsMediaUrl(url)` which in turn may call `$$sanitizeUri(url, isMedia)` to sanitize
* the potentially malicious URL.
*
* If the URL matches the `aImgSanitizationWhitelist` regular expression, it is returned unchanged.
* If the URL matches the `imgSrcSanitizationTrustedUrlList` regular expression, it is returned
* unchanged.
*
* If there is no match the URL is returned prefixed with `'unsafe:'` to ensure that when it is written
* to the DOM it is inactive and potentially malicious code will not be executed.
*
* @param {RegExp=} regexp New regexp to whitelist urls with.
* @param {RegExp=} regexp New regexp to trust urls with.
* @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
* chaining otherwise.
*/
this.imgSrcSanitizationWhitelist = function(regexp) {
this.imgSrcSanitizationTrustedUri = function(regexp) {
if (isDefined(regexp)) {
imgSrcSanitizationWhitelist = regexp;
imgSrcSanitizationTrustedUri = regexp;
return this;
}
return imgSrcSanitizationWhitelist;
return imgSrcSanitizationTrustedUri;
};

this.$get = function() {
return function sanitizeUri(uri, isMediaUrl) {
// if (!uri) return uri;
var regex = isMediaUrl ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
var regex = isMediaUrl ? imgSrcSanitizationTrustedUri : aHrefSanitizationTrustedUri;
var normalizedVal = urlResolve(uri && uri.trim()).href;
if (normalizedVal !== '' && !normalizedVal.match(regex)) {
return 'unsafe:' + normalizedVal;
Expand Down
6 changes: 3 additions & 3 deletions src/ngSanitize/sanitize.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var htmlSanitizeWriter;
* it into the returned string.
*
* The whitelist for URL sanitization of attribute values is configured using the functions
* `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link $compileProvider}.
* `aHrefSanitizationTrustedUri` and `imgSrcSanitizationTrustedUri` of {@link $compileProvider}.
*
* The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
*
Expand Down Expand Up @@ -277,8 +277,8 @@ function $SanitizeProvider() {
* **Note**:
* The new attributes will not be treated as URI attributes, which means their values will not be
* sanitized as URIs using `$compileProvider`'s
* {@link ng.$compileProvider#aHrefSanitizationWhitelist aHrefSanitizationWhitelist} and
* {@link ng.$compileProvider#imgSrcSanitizationWhitelist imgSrcSanitizationWhitelist}.
* {@link ng.$compileProvider#aHrefSanitizationTrustedUri aHrefSanitizationTrustedUri} and
* {@link ng.$compileProvider#imgSrcSanitizationTrustedUri imgSrcSanitizationTrustedUri}.
*
* <div class="alert alert-info">
* This method must be called during the {@link angular.Module#config config} phase. Once the
Expand Down
50 changes: 25 additions & 25 deletions test/ng/compileSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,30 +151,30 @@ describe('$compile', function() {

describe('configuration', function() {

it('should use $$sanitizeUriProvider for reconfiguration of the `aHrefSanitizationWhitelist`', function() {
it('should use $$sanitizeUriProvider for reconfiguration of the `aHrefSanitizationTrustedUri`', function() {
module(function($compileProvider, $$sanitizeUriProvider) {
var newRe = /safe:/, returnVal;

expect($compileProvider.aHrefSanitizationWhitelist()).toBe($$sanitizeUriProvider.aHrefSanitizationWhitelist());
returnVal = $compileProvider.aHrefSanitizationWhitelist(newRe);
expect($compileProvider.aHrefSanitizationTrustedUri()).toBe($$sanitizeUriProvider.aHrefSanitizationTrustedUri());
returnVal = $compileProvider.aHrefSanitizationTrustedUri(newRe);
expect(returnVal).toBe($compileProvider);
expect($$sanitizeUriProvider.aHrefSanitizationWhitelist()).toBe(newRe);
expect($compileProvider.aHrefSanitizationWhitelist()).toBe(newRe);
expect($$sanitizeUriProvider.aHrefSanitizationTrustedUri()).toBe(newRe);
expect($compileProvider.aHrefSanitizationTrustedUri()).toBe(newRe);
});
inject(function() {
// needed to the module definition above is run...
});
});

it('should use $$sanitizeUriProvider for reconfiguration of the `imgSrcSanitizationWhitelist`', function() {
it('should use $$sanitizeUriProvider for reconfiguration of the `imgSrcSanitizationTrustedUri`', function() {
module(function($compileProvider, $$sanitizeUriProvider) {
var newRe = /safe:/, returnVal;

expect($compileProvider.imgSrcSanitizationWhitelist()).toBe($$sanitizeUriProvider.imgSrcSanitizationWhitelist());
returnVal = $compileProvider.imgSrcSanitizationWhitelist(newRe);
expect($compileProvider.imgSrcSanitizationTrustedUri()).toBe($$sanitizeUriProvider.imgSrcSanitizationTrustedUri());
returnVal = $compileProvider.imgSrcSanitizationTrustedUri(newRe);
expect(returnVal).toBe($compileProvider);
expect($$sanitizeUriProvider.imgSrcSanitizationWhitelist()).toBe(newRe);
expect($compileProvider.imgSrcSanitizationWhitelist()).toBe(newRe);
expect($$sanitizeUriProvider.imgSrcSanitizationTrustedUri()).toBe(newRe);
expect($compileProvider.imgSrcSanitizationTrustedUri()).toBe(newRe);
});
inject(function() {
// needed to the module definition above is run...
Expand Down Expand Up @@ -11334,9 +11334,9 @@ describe('$compile', function() {
// IE9 rejects the `video` / `audio` tags with "Error: Not implemented"
if (msie !== 9 || tag === 'img') {
describe(tag + '[src] context requirement', function() {
it('should NOT require trusted values for whitelisted URIs', inject(function($rootScope, $compile) {
it('should NOT require trusted values for trusted URIs', inject(function($rootScope, $compile) {
element = $compile('<' + tag + ' src="{{testUrl}}"></' + tag + '>')($rootScope);
$rootScope.testUrl = 'http://example.com/image.mp4'; // `http` is whitelisted
$rootScope.testUrl = 'http://example.com/image.mp4'; // `http` is trusted
$rootScope.$digest();
expect(element.attr('src')).toEqual('http://example.com/image.mp4');
}));
Expand Down Expand Up @@ -11372,9 +11372,9 @@ describe('$compile', function() {
if (msie !== 9) {
['source', 'track'].forEach(function(tag) {
describe(tag + '[src]', function() {
it('should NOT require trusted values for whitelisted URIs', inject(function($rootScope, $compile) {
it('should NOT require trusted values for trusted URIs', inject(function($rootScope, $compile) {
element = $compile('<video><' + tag + ' src="{{testUrl}}"></' + tag + '></video>')($rootScope);
$rootScope.testUrl = 'http://example.com/image.mp4'; // `http` is whitelisted
$rootScope.testUrl = 'http://example.com/image.mp4'; // `http` is trusted
$rootScope.$digest();
expect(element.find(tag).attr('src')).toEqual('http://example.com/image.mp4');
}));
Expand Down Expand Up @@ -11509,14 +11509,14 @@ describe('$compile', function() {
});
});

it('should NOT require trusted values for whitelisted values', inject(function($rootScope, $compile, $sce) {
it('should NOT require trusted values for trusted URI values', inject(function($rootScope, $compile, $sce) {
element = $compile('<img srcset="{{testUrl}}"></img>')($rootScope);
$rootScope.testUrl = 'http://example.com/image.png'; // `http` is whitelisted
$rootScope.testUrl = 'http://example.com/image.png'; // `http` is trusted
$rootScope.$digest();
expect(element.attr('srcset')).toEqual('http://example.com/image.png');
}));

it('should accept trusted values, if they are also whitelisted', inject(function($rootScope, $compile, $sce) {
it('should accept trusted values, if they are also trusted URIs', inject(function($rootScope, $compile, $sce) {
element = $compile('<img srcset="{{testUrl}}"></img>')($rootScope);
$rootScope.testUrl = $sce.trustAsUrl('http://example.com');
$rootScope.$digest();
Expand Down Expand Up @@ -11602,8 +11602,8 @@ describe('$compile', function() {
});

describe('a[href] sanitization', function() {
it('should NOT require trusted values for whitelisted values', inject(function($rootScope, $compile) {
$rootScope.testUrl = 'http://example.com/image.png'; // `http` is whitelisted
it('should NOT require trusted values for trusted URI values', inject(function($rootScope, $compile) {
$rootScope.testUrl = 'http://example.com/image.png'; // `http` is trusted
element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
$rootScope.$digest();
expect(element.attr('href')).toEqual('http://example.com/image.png');
Expand All @@ -11613,8 +11613,8 @@ describe('$compile', function() {
expect(element.attr('ng-href')).toEqual('http://example.com/image.png');
}));

it('should accept trusted values for non-whitelisted values', inject(function($rootScope, $compile, $sce) {
$rootScope.testUrl = $sce.trustAsUrl('javascript:foo()'); // `javascript` is not whitelisted
it('should accept trusted values for non-trusted URI values', inject(function($rootScope, $compile, $sce) {
$rootScope.testUrl = $sce.trustAsUrl('javascript:foo()'); // `javascript` is not trusted
element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
$rootScope.$digest();
expect(element.attr('href')).toEqual('javascript:foo()');
Expand All @@ -11624,8 +11624,8 @@ describe('$compile', function() {
expect(element.attr('ng-href')).toEqual('javascript:foo()');
}));

it('should sanitize non-whitelisted values', inject(function($rootScope, $compile) {
$rootScope.testUrl = 'javascript:foo()'; // `javascript` is not whitelisted
it('should sanitize non-trusted values', inject(function($rootScope, $compile) {
$rootScope.testUrl = 'javascript:foo()'; // `javascript` is not trusted
element = $compile('<a href="{{testUrl}}"></a>')($rootScope);
$rootScope.$digest();
expect(element.attr('href')).toEqual('unsafe:javascript:foo()');
Expand Down Expand Up @@ -11678,7 +11678,7 @@ describe('$compile', function() {
$provide.value('$$sanitizeUri', $$sanitizeUri);
});
inject(function($compile, $rootScope) {
// This URL would fail the RESOURCE_URL whitelist, but that test shouldn't be run
// This URL would fail the RESOURCE_URL trusted list, but that test shouldn't be run
// because these interpolations will be resolved against the URL context instead
$rootScope.testUrl = 'https://bad.example.org';

Expand All @@ -11700,7 +11700,7 @@ describe('$compile', function() {
$provide.value('$$sanitizeUri', $$sanitizeUri);
});
inject(function($compile, $rootScope) {
// This URL would fail the RESOURCE_URL whitelist, but that test shouldn't be run
// This URL would fail the RESOURCE_URL trusted list, but that test shouldn't be run
// because these interpolations will be resolved against the URL context instead
$rootScope.testUrl = 'https://bad.example.org';

Expand Down
12 changes: 6 additions & 6 deletions test/ng/sanitizeUriSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ describe('sanitizeUri', function() {
expect(sanitizeImg(testUrl)).toBe('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
});

it('should allow reconfiguration of the src whitelist', function() {
it('should allow reconfiguration of the src trusted URIs', function() {
var returnVal;
expect(sanitizeUriProvider.imgSrcSanitizationWhitelist() instanceof RegExp).toBe(true);
returnVal = sanitizeUriProvider.imgSrcSanitizationWhitelist(/javascript:/);
expect(sanitizeUriProvider.imgSrcSanitizationTrustedUri() instanceof RegExp).toBe(true);
returnVal = sanitizeUriProvider.imgSrcSanitizationTrustedUri(/javascript:/);
expect(returnVal).toBe(sanitizeUriProvider);

testUrl = 'javascript:doEvilStuff()';
Expand Down Expand Up @@ -226,10 +226,10 @@ describe('sanitizeUri', function() {
expect(sanitizeHref(testUrl)).toBe('file:///foo/bar.html');
}));

it('should allow reconfiguration of the href whitelist', function() {
it('should allow reconfiguration of the href trusted URIs', function() {
var returnVal;
expect(sanitizeUriProvider.aHrefSanitizationWhitelist() instanceof RegExp).toBe(true);
returnVal = sanitizeUriProvider.aHrefSanitizationWhitelist(/javascript:/);
expect(sanitizeUriProvider.aHrefSanitizationTrustedUri() instanceof RegExp).toBe(true);
returnVal = sanitizeUriProvider.aHrefSanitizationTrustedUri(/javascript:/);
expect(returnVal).toBe(sanitizeUriProvider);

testUrl = 'javascript:doEvilStuff()';
Expand Down

0 comments on commit 7673810

Please sign in to comment.