author | Narcis Beleuzu <nbeleuzu@mozilla.com> |
Mon, 25 May 2020 13:52:24 +0300 | |
changeset 531873 | 90b6e0e32402202184bd54e196262d4d99c6f1e8 |
parent 531872 | 9b5d151a83b7d94170f1d094f4a1959bad9d8c91 |
child 531874 | 5e78c6238e348639fdbd0bd47eb2151aadd66bee |
push id | 37447 |
push user | nbeleuzu@mozilla.com |
push date | Mon, 25 May 2020 15:42:48 +0000 |
treeherder | mozilla-central@e7641c1071ea [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1638826 |
milestone | 78.0a1 |
backs out | 2b4796470c0b1a73a943c4d882a492bea5383882 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -1622,24 +1622,16 @@ NS_IMETHODIMP nsCSPContext::Permits(Element* aTriggeringElement, nsICSPEventListener* aCSPEventListener, nsIURI* aURI, CSPDirective aDir, bool aSpecific, bool* outPermits) { // Can't perform check without aURI if (aURI == nullptr) { return NS_ERROR_FAILURE; } - // CSP_SubjectToCSP allow lists some internal schemes but also some - // specific content types. Using TYPE_OTHER as a default which will - // still allow list all allow listed schemes. - if (!CSP_SubjectToCSP(aURI, nsIContentPolicy::TYPE_OTHER)) { - *outPermits = true; - return NS_OK; - } - *outPermits = permitsInternal(aDir, aTriggeringElement, aCSPEventListener, aURI, nullptr, // no original (pre-redirect) URI EmptyString(), // no nonce false, // not a preload. aSpecific, true, // send violation reports true, // send blocked URI in violation reports
--- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -26,16 +26,86 @@ using namespace mozilla; static LazyLogModule gCspPRLog("CSP"); CSPService::CSPService() = default; CSPService::~CSPService() = default; NS_IMPL_ISUPPORTS(CSPService, nsIContentPolicy, nsIChannelEventSink) +// Helper function to identify protocols and content types not subject to CSP. +bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { + nsContentPolicyType contentType = + nsContentUtils::InternalContentPolicyTypeToExternal(aContentType); + + // These content types are not subject to CSP content policy checks: + // TYPE_CSP_REPORT -- csp can't block csp reports + // TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl) + // TYPE_DOCUMENT -- used for frame-ancestors + if (contentType == nsIContentPolicy::TYPE_CSP_REPORT || + contentType == nsIContentPolicy::TYPE_REFRESH || + contentType == nsIContentPolicy::TYPE_DOCUMENT) { + return false; + } + + // The three protocols: data:, blob: and filesystem: share the same + // protocol flag (URI_IS_LOCAL_RESOURCE) with other protocols, + // but those three protocols get special attention in CSP and + // are subject to CSP, hence we have to make sure those + // protocols are subject to CSP, see: + // http://www.w3.org/TR/CSP2/#source-list-guid-matching + if (aURI->SchemeIs("data") || aURI->SchemeIs("blob") || + aURI->SchemeIs("filesystem")) { + return true; + } + + // Finally we have to whitelist "about:" which does not fall into + // the category underneath and also "javascript:" which is not + // subject to CSP content loading rules. + if (aURI->SchemeIs("about") || aURI->SchemeIs("javascript")) { + return false; + } + + // Please note that it should be possible for websites to + // whitelist their own protocol handlers with respect to CSP, + // hence we use protocol flags to accomplish that, but we also + // want resource:, chrome: and moz-icon to be subject to CSP + // (which also use URI_IS_LOCAL_RESOURCE). + // Exception to the rule are images, styles, and localization + // DTDs using a scheme of resource: or chrome: + bool isImgOrStyleOrDTD = contentType == nsIContentPolicy::TYPE_IMAGE || + contentType == nsIContentPolicy::TYPE_STYLESHEET || + contentType == nsIContentPolicy::TYPE_DTD; + if (aURI->SchemeIs("resource")) { + nsAutoCString uriSpec; + aURI->GetSpec(uriSpec); + // Exempt pdf.js from being subject to a page's CSP. + if (StringBeginsWith(uriSpec, NS_LITERAL_CSTRING("resource://pdf.js/"))) { + return false; + } + if (!isImgOrStyleOrDTD) { + return true; + } + } + if (aURI->SchemeIs("chrome") && !isImgOrStyleOrDTD) { + return true; + } + if (aURI->SchemeIs("moz-icon")) { + return true; + } + bool match; + nsresult rv = NS_URIChainHasFlags( + aURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &match); + if (NS_SUCCEEDED(rv) && match) { + return false; + } + // all other protocols are subject To CSP. + return true; +} + /* static */ nsresult CSPService::ConsultCSP(nsIURI* aContentLocation, nsILoadInfo* aLoadInfo, const nsACString& aMimeTypeGuess, int16_t* aDecision) { if (!aContentLocation) { return NS_ERROR_FAILURE; } @@ -55,19 +125,19 @@ NS_IMPL_ISUPPORTS(CSPService, nsIContent // default decision, CSP can revise it if there's a policy to enforce *aDecision = nsIContentPolicy::ACCEPT; // No need to continue processing if CSP is disabled or if the protocol // or type is *not* subject to CSP. // Please note, the correct way to opt-out of CSP using a custom // protocolHandler is to set one of the nsIProtocolHandler flags - // that are whitelistet in CSP_SubjectToCSP() + // that are whitelistet in subjectToCSP() if (!StaticPrefs::security_csp_enable() || - !CSP_SubjectToCSP(aContentLocation, contentType)) { + !subjectToCSP(aContentLocation, contentType)) { return NS_OK; } nsAutoString cspNonce; rv = aLoadInfo->GetCspNonce(cspNonce); NS_ENSURE_SUCCESS(rv, rv); // 1) Apply speculate CSP for preloads @@ -236,20 +306,20 @@ nsresult CSPService::ConsultCSPForRedire return NS_OK; } } // No need to continue processing if CSP is disabled or if the protocol // is *not* subject to CSP. // Please note, the correct way to opt-out of CSP using a custom // protocolHandler is to set one of the nsIProtocolHandler flags - // that are whitelistet in CSP_SubjectToCSP() + // that are whitelistet in subjectToCSP() nsContentPolicyType policyType = aLoadInfo->InternalContentPolicyType(); if (!StaticPrefs::security_csp_enable() || - !CSP_SubjectToCSP(aNewURI, policyType)) { + !subjectToCSP(aNewURI, policyType)) { return NS_OK; } nsCOMPtr<nsICSPEventListener> cspEventListener; nsresult rv = aLoadInfo->GetCspEventListener(getter_AddRefs(cspEventListener)); MOZ_ALWAYS_SUCCEEDS(rv);
--- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp @@ -455,85 +455,16 @@ bool permitsScheme(const nsAString& aEnf // the error back to the page. return ( (aUpgradeInsecure && !aReportOnly) && ((scheme.EqualsASCII("http") && aEnforcementScheme.EqualsASCII("https")) || (scheme.EqualsASCII("ws") && aEnforcementScheme.EqualsASCII("wss")))); } -bool CSP_SubjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) { - nsContentPolicyType contentType = - nsContentUtils::InternalContentPolicyTypeToExternal(aContentType); - - // These content types are not subject to CSP content policy checks: - // TYPE_CSP_REPORT -- csp can't block csp reports - // TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl) - // TYPE_DOCUMENT -- used for frame-ancestors - if (contentType == nsIContentPolicy::TYPE_CSP_REPORT || - contentType == nsIContentPolicy::TYPE_REFRESH || - contentType == nsIContentPolicy::TYPE_DOCUMENT) { - return false; - } - - // The three protocols: data:, blob: and filesystem: share the same - // protocol flag (URI_IS_LOCAL_RESOURCE) with other protocols, - // but those three protocols get special attention in CSP and - // are subject to CSP, hence we have to make sure those - // protocols are subject to CSP, see: - // http://www.w3.org/TR/CSP2/#source-list-guid-matching - if (aURI->SchemeIs("data") || aURI->SchemeIs("blob") || - aURI->SchemeIs("filesystem")) { - return true; - } - - // Finally we have to whitelist "about:" which does not fall into - // the category underneath and also "javascript:" which is not - // subject to CSP content loading rules. - if (aURI->SchemeIs("about") || aURI->SchemeIs("javascript")) { - return false; - } - - // Please note that it should be possible for websites to - // whitelist their own protocol handlers with respect to CSP, - // hence we use protocol flags to accomplish that, but we also - // want resource:, chrome: and moz-icon to be subject to CSP - // (which also use URI_IS_LOCAL_RESOURCE). - // Exception to the rule are images, styles, and localization - // DTDs using a scheme of resource: or chrome: - bool isImgOrStyleOrDTD = contentType == nsIContentPolicy::TYPE_IMAGE || - contentType == nsIContentPolicy::TYPE_STYLESHEET || - contentType == nsIContentPolicy::TYPE_DTD; - if (aURI->SchemeIs("resource")) { - nsAutoCString uriSpec; - aURI->GetSpec(uriSpec); - // Exempt pdf.js from being subject to a page's CSP. - if (StringBeginsWith(uriSpec, NS_LITERAL_CSTRING("resource://pdf.js/"))) { - return false; - } - if (!isImgOrStyleOrDTD) { - return true; - } - } - if (aURI->SchemeIs("chrome") && !isImgOrStyleOrDTD) { - return true; - } - if (aURI->SchemeIs("moz-icon")) { - return true; - } - bool match; - nsresult rv = NS_URIChainHasFlags( - aURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &match); - if (NS_SUCCEEDED(rv) && match) { - return false; - } - // all other protocols are subject To CSP. - return true; -} - /* * A helper function for appending a CSP header to an existing CSP * policy. * * @param aCsp the CSP policy * @param aHeaderValue the header * @param aReportOnly is this a report-only header? */
--- a/dom/security/nsCSPUtils.h +++ b/dom/security/nsCSPUtils.h @@ -183,19 +183,16 @@ inline CSPKeyword CSP_UTF16KeywordToEnum if (lowerKey.Equals(gCSPUTF16Keywords[i])) { return static_cast<CSPKeyword>(i); } } NS_ASSERTION(false, "Can not convert unknown Keyword to Enum"); return CSP_LAST_KEYWORD_VALUE; } -// Helper function to identify protocols and content types not subject to CSP. -bool CSP_SubjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType); - nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp, const nsAString& aHeaderValue, bool aReportOnly); /* =============== Helpers ================== */ class nsCSPHostSrc;
--- a/dom/security/test/csp/file_pdfjs_not_subject_to_csp.html +++ b/dom/security/test/csp/file_pdfjs_not_subject_to_csp.html @@ -1,11 +1,11 @@ <html> <head> - <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-allowPDF'; base-uri 'self'"> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-allowPDF'"> </head> <body> <iframe id="pdfFrame"></iframe> <br/> <button id="pdfButton">click to load pdf</button> <script nonce="allowPDF"> async function loadPDFIntoIframe() { let response = await fetch("dummy.pdf");