diff --git a/src/ng/compile.js b/src/ng/compile.js index 65200b2fb..2fb653093 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -2971,6 +2971,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // maction[xlink:href] can source SVG. It's not limited to . if (attrNormalizedName === "xlinkHref" || (tag === "form" && attrNormalizedName === "action") || + // links can be stylesheets or imports, which can run script in the current origin + (tag === "link" && attrNormalizedName === "href") || (tag !== "img" && (attrNormalizedName === "src" || attrNormalizedName === "ngSrc"))) { return $sce.RESOURCE_URL; diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 0a6fe4b11..dde7eeb4d 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -10171,6 +10171,7 @@ describe('$compile', function() { "loading resource from url not allowed by $sceDelegate policy. URL: javascript:doTrustedStuff()"); })); + it('should pass through $sce.trustAs() values in action attribute', inject(function($compile, $rootScope, $sce) { /* jshint scripturl:true */ element = $compile('
')($rootScope); @@ -10181,6 +10182,36 @@ describe('$compile', function() { })); }); + describe('link[href]', function() { + it('should reject invalid RESOURCE_URLs', inject(function($compile, $rootScope) { + element = $compile('')($rootScope); + $rootScope.testUrl = "https://evil.example.org/css.css"; + expect(function() { $rootScope.$apply(); }).toThrowMinErr( + "$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " + + "loading resource from url not allowed by $sceDelegate policy. URL: " + + "https://evil.example.org/css.css"); + })); + + it('should accept valid RESOURCE_URLs', inject(function($compile, $rootScope, $sce) { + element = $compile('')($rootScope); + + $rootScope.testUrl = "./css1.css"; + $rootScope.$apply(); + expect(element.attr('href')).toContain('css1.css'); + + $rootScope.testUrl = $sce.trustAsResourceUrl('https://elsewhere.example.org/css2.css'); + $rootScope.$apply(); + expect(element.attr('href')).toContain('https://elsewhere.example.org/css2.css'); + })); + + it('should accept valid constants', inject(function($compile, $rootScope) { + element = $compile('')($rootScope); + + $rootScope.$apply(); + expect(element.attr('href')).toContain('https://elsewhere.example.org/css2.css'); + })); + }); + if (!msie || msie >= 11) { describe('iframe[srcdoc]', function() { it('should NOT set iframe contents for untrusted values', inject(function($compile, $rootScope, $sce) {