diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index d30036c85c2f..16fb9fa9754f 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -172,11 +172,31 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { nsCOMPtr csp = aLoadInfo->GetCsp(); if (csp) { + // Generally aOriginalURI denotes the URI before a redirect and hence + // will always be a nullptr here. Only exception are frame navigations + // which we want to treat as a redirect for the purpose of CSP reporting + // and in particular the `blocked-uri` in the CSP report where we want + // to report the prePath information. + nsCOMPtr originalURI = nullptr; + ExtContentPolicyType extType = + nsContentUtils::InternalContentPolicyTypeToExternal(contentType); + if (extType == ExtContentPolicy::TYPE_SUBDOCUMENT && + !aLoadInfo->GetOriginalFrameSrcLoad() && + mozilla::StaticPrefs:: + security_csp_truncate_blocked_uri_for_frame_navigations()) { + nsAutoCString prePathStr; + nsresult rv = aContentLocation->GetPrePath(prePathStr); + NS_ENSURE_SUCCESS(rv, rv); + rv = NS_NewURI(getter_AddRefs(originalURI), prePathStr); + NS_ENSURE_SUCCESS(rv, rv); + } + // obtain the enforcement decision - rv = csp->ShouldLoad(contentType, cspEventListener, aContentLocation, - nullptr, // no redirect, aOriginal URL is null. - !isPreload && aLoadInfo->GetSendCSPViolationEvents(), - cspNonce, parserCreatedScript, aDecision); + rv = csp->ShouldLoad( + contentType, cspEventListener, aContentLocation, + originalURI, // no redirect, unless it's a frame navigation. + !isPreload && aLoadInfo->GetSendCSPViolationEvents(), cspNonce, + parserCreatedScript, aDecision); if (NS_CP_REJECTED(*aDecision)) { NS_SetRequestBlockingReason( diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index bea641a838d6..8c58252a8dc4 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -9475,6 +9475,11 @@ value: 40 mirror: always +- name: security.csp.truncate_blocked_uri_for_frame_navigations + type: bool + value: true + mirror: always + # Allows loading ui resources in CheckLoadURIFlags # TODO Bug 1654488: Remove pref in CheckLoadURIFlags # which allows all UI resources to load diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js index 223f0650e943..f5df8e61d2f5 100644 --- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js @@ -25,6 +25,12 @@ Services.prefs.setIntPref( 4096 ); +// Do not trunacate the blocked-uri in CSP reports for frame navigations. +Services.prefs.setBoolPref( + "security.csp.truncate_blocked_uri_for_frame_navigations", + false +); + // ExtensionContent.jsm needs to know when it's running from xpcshell, // to use the right timeout for content scripts executed at document_idle. ExtensionTestUtils.mockAppInfo(); @@ -830,6 +836,8 @@ function computeBaseURLs(tests, expectedSources, forbiddenSources = {}) { function* iterSources(test, sources) { for (let [source, attrs] of Object.entries(sources)) { + // if a source defines attributes (e.g. liveSrc in PAGE_SOURCES etc.) then all + // attributes in the source must be matched by the test (see const TEST). if (Object.keys(attrs).every(attr => attrs[attr] === test[attr])) { yield `${BASE_URL}/${test.src}?source=${source}`; } @@ -1082,6 +1090,9 @@ const TESTS = [ }, // TODO: element, which requires a frameset document. { + // the blocked-uri for frame-navigations is the pre-path URI. For the + // purpose of this test we do not strip the blocked-uri by setting the + // preference 'truncate_blocked_uri_for_frame_navigations' element: ["iframe", {}], src: "iframe.html", },