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

Commit 1cf728e

Browse files
rjametgkalpak
authored andcommitted
fix($compile) : add base[href] to the list of RESOURCE_URL context attributes
Previously, `base[href]` didn't have an SCE context. This was not ideal, because `base[href]` affects the behavior of all relative URLs across the page. Furthermore, since #15145, `base[href]` also affects which URLs are considered trusted under the 'self' policy for white- or black-listed resource URLs. This commit tightens the security of Angular apps, by adding `base[href]` to the list of RESOURCE_URL context attributes, essentially putting the same constraints on bindings to `base[href]` as on iframe or script sources. Refer to the [`$sce` API docs](https://code.angularjs.org/snapshot/docs/api/ng/service/$sce) for more info on SCE trusted contexts. Closes #15597 BREAKING CHANGE: Previously, `<base href="{{ $ctrl.baseUrl }}" />` would not require `baseUrl` to be trusted as a RESOURCE_URL. Now, `baseUrl` will be sent to `$sce`'s RESOURCE_URL checks. By default, it will break unless `baseUrl` is of the same origin as the application document. Refer to the [`$sce` API docs](https://code.angularjs.org/snapshot/docs/api/ng/service/$sce) for more info on how to trust a value in a RESOURCE_URL context. Also, concatenation in trusted contexts is not allowed, which means that the following won't work: `<base href="/something/{{ $ctrl.partialPath }}" />`. Either construct complex values in a controller (recommended): ```js this.baseUrl = '/something/' + this.partialPath; ``` ```html <base href="{{ $ctrl.baseUrl }}" /> ``` Or use string concatenation in the interpolation expression (not recommended except for the simplest of cases): ```html <base href="{{ '/something/' + $ctrl.partialPath }}" /> ```
1 parent 675f99b commit 1cf728e

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

src/ng/compile.js

+3
Original file line numberDiff line numberDiff line change
@@ -3257,6 +3257,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
32573257
// maction[xlink:href] can source SVG. It's not limited to <maction>.
32583258
} else if (attrNormalizedName === 'xlinkHref' ||
32593259
(tag === 'form' && attrNormalizedName === 'action') ||
3260+
// If relative URLs can go where they are not expected to, then
3261+
// all sorts of trust issues can arise.
3262+
(tag === 'base' && attrNormalizedName === 'href') ||
32603263
// links can be stylesheets or imports, which can run script in the current origin
32613264
(tag === 'link' && attrNormalizedName === 'href')
32623265
) {

src/ng/sce.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ function $SceDelegateProvider() {
544544
* | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
545545
* | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
546546
* | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
547-
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG`, `VIDEO`, `AUDIO`, `SOURCE`, and `TRACK` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
547+
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG`, `VIDEO`, `AUDIO`, `SOURCE`, and `TRACK` (e.g. `IFRAME`, `OBJECT`, etc.), plus some miscellaneous sensitive attributes (BASE HREF, LINK HREF, etc.)<br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
548548
* | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
549549
*
550550
* ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>

test/ng/compileSpec.js

+16
Original file line numberDiff line numberDiff line change
@@ -11169,6 +11169,22 @@ describe('$compile', function() {
1116911169
}));
1117011170
});
1117111171

11172+
describe('base[href]', function() {
11173+
it('should be a RESOURCE_URL context', inject(function($compile, $rootScope, $sce) {
11174+
element = $compile('<base href="{{testUrl}}"/>')($rootScope);
11175+
11176+
$rootScope.testUrl = $sce.trustAsResourceUrl('https://example.com/');
11177+
$rootScope.$apply();
11178+
expect(element.attr('href')).toContain('https://example.com/');
11179+
11180+
$rootScope.testUrl = 'https://not.example.com/';
11181+
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
11182+
'$interpolate', 'interr', 'Can\'t interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked ' +
11183+
'loading resource from url not allowed by $sceDelegate policy. URL: ' +
11184+
'https://not.example.com/');
11185+
}));
11186+
});
11187+
1117211188
describe('form[action]', function() {
1117311189
it('should pass through action attribute for the same domain', inject(function($compile, $rootScope, $sce) {
1117411190
element = $compile('<form action="{{testUrl}}"></form>')($rootScope);

0 commit comments

Comments
 (0)