Bug 1770094 r=freddyb,emilio

Differential Revision: https://phabricator.services.mozilla.com/D154518
This commit is contained in:
Tom Schuster 2022-08-15 14:41:10 +00:00
parent 38be891463
commit b7a20e09d8
5 changed files with 56 additions and 21 deletions

View file

@ -792,7 +792,8 @@ nsresult HTMLFormSubmission::GetFromForm(HTMLFormElement* aForm,
// policy - do *not* consult default-src, see: // policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src // http://www.w3.org/TR/CSP2/#directive-default-src
rv = csp->Permits(aForm, nullptr /* nsICSPEventListener */, actionURL, rv = csp->Permits(aForm, nullptr /* nsICSPEventListener */, actionURL,
nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE, true, nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE,
true /* aSpecific */, true /* aSendViolationReports */,
&permitsFormAction); &permitsFormAction);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (!permitsFormAction) { if (!permitsFormAction) {

View file

@ -155,10 +155,10 @@ static void SetBaseURIUsingFirstBaseWithHref(Document* aDocument,
// policy - do *not* consult default-src, see: // policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src // http://www.w3.org/TR/CSP2/#directive-default-src
bool cspPermitsBaseURI = true; bool cspPermitsBaseURI = true;
rv = csp->Permits(child->AsElement(), nullptr /* nsICSPEventListener */, rv = csp->Permits(
newBaseURI, child->AsElement(), nullptr /* nsICSPEventListener */, newBaseURI,
nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true, nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */,
&cspPermitsBaseURI); true /* aSendViolationReports */, &cspPermitsBaseURI);
if (NS_FAILED(rv) || !cspPermitsBaseURI) { if (NS_FAILED(rv) || !cspPermitsBaseURI) {
newBaseURI = nullptr; newBaseURI = nullptr;
} }

View file

@ -307,9 +307,6 @@ interface nsIContentSecurityPolicy : nsISerializable
/** /**
* Checks if a specific directive permits loading of a URI. * Checks if a specific directive permits loading of a URI.
* *
* NOTE: Calls to this may trigger violation reports when queried, so the
* return value should not be cached.
*
* @param aTriggeringElement * @param aTriggeringElement
* The element that triggers this CSP check. It can be null. * The element that triggers this CSP check. It can be null.
* @param aURI * @param aURI
@ -323,6 +320,9 @@ interface nsIContentSecurityPolicy : nsISerializable
* "false" allows CSP to fall back to default-src. This function * "false" allows CSP to fall back to default-src. This function
* behaves the same for both values of canUseDefault when querying * behaves the same for both values of canUseDefault when querying
* directives that don't fall-back. * directives that don't fall-back.
* @param aSendViolationReports
* If `true` and the uri is not allowed then trigger violation reports.
* This should be `false` for caching or preloads.
* @return * @return
* Whether or not the provided URI is allowed by CSP under the given * Whether or not the provided URI is allowed by CSP under the given
* directive. (block the pending operation if false). * directive. (block the pending operation if false).
@ -331,7 +331,8 @@ interface nsIContentSecurityPolicy : nsISerializable
in nsICSPEventListener aCSPEventListener, in nsICSPEventListener aCSPEventListener,
in nsIURI aURI, in nsIURI aURI,
in nsIContentSecurityPolicy_CSPDirective aDir, in nsIContentSecurityPolicy_CSPDirective aDir,
in boolean aSpecific); in boolean aSpecific,
in boolean aSendViolationReports);
/** /**
* Delegate method called by the service when sub-elements of the protected * Delegate method called by the service when sub-elements of the protected

View file

@ -1721,7 +1721,8 @@ nsCSPContext::PermitsAncestry(nsILoadInfo* aLoadInfo,
NS_IMETHODIMP NS_IMETHODIMP
nsCSPContext::Permits(Element* aTriggeringElement, nsCSPContext::Permits(Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener, nsIURI* aURI, nsICSPEventListener* aCSPEventListener, nsIURI* aURI,
CSPDirective aDir, bool aSpecific, bool* outPermits) { CSPDirective aDir, bool aSpecific,
bool aSendViolationReports, bool* outPermits) {
// Can't perform check without aURI // Can't perform check without aURI
if (aURI == nullptr) { if (aURI == nullptr) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -1743,14 +1744,14 @@ nsCSPContext::Permits(Element* aTriggeringElement,
permitsInternal(aDir, aTriggeringElement, aCSPEventListener, aURI, permitsInternal(aDir, aTriggeringElement, aCSPEventListener, aURI,
nullptr, // no original (pre-redirect) URI nullptr, // no original (pre-redirect) URI
u""_ns, // no nonce u""_ns, // no nonce
aSpecific, aSpecific, aSendViolationReports,
true, // send violation reports
true, // send blocked URI in violation reports true, // send blocked URI in violation reports
false); // not parser created false); // not parser created
if (CSPCONTEXTLOGENABLED()) { if (CSPCONTEXTLOGENABLED()) {
CSPCONTEXTLOG(("nsCSPContext::Permits, aUri: %s, aDir: %d, isAllowed: %s", CSPCONTEXTLOG(("nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s",
aURI->GetSpecOrDefault().get(), aDir, aURI->GetSpecOrDefault().get(),
CSP_CSPDirectiveToString(aDir),
*outPermits ? "allow" : "deny")); *outPermits ? "allow" : "deny"));
} }

View file

@ -1314,11 +1314,44 @@ void nsHtml5TreeOpExecutor::SetSpeculationBase(const nsAString& aURL) {
// the first one wins // the first one wins
return; return;
} }
auto encoding = mDocument->GetDocumentCharacterSet();
DebugOnly<nsresult> rv = NS_NewURI(getter_AddRefs(mSpeculationBaseURI), aURL,
encoding, mDocument->GetDocumentURI());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to create a URI");
auto encoding = mDocument->GetDocumentCharacterSet();
nsCOMPtr<nsIURI> newBaseURI;
DebugOnly<nsresult> rv = NS_NewURI(getter_AddRefs(newBaseURI), aURL, encoding,
mDocument->GetDocumentURI());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to create a URI");
if (!newBaseURI) {
return;
}
// Check the document's CSP usually delivered via the CSP header.
if (nsCOMPtr<nsIContentSecurityPolicy> csp = mDocument->GetCsp()) {
// base-uri should not fallback to the default-src and preloads should not
// trigger violation reports.
bool cspPermitsBaseURI = true;
nsresult rv = csp->Permits(
nullptr, nullptr, newBaseURI,
nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */,
false /* aSendViolationReports */, &cspPermitsBaseURI);
if (NS_FAILED(rv) || !cspPermitsBaseURI) {
return;
}
}
// Also check the CSP discovered from the <meta> tag during speculative
// parsing.
if (nsCOMPtr<nsIContentSecurityPolicy> csp = mDocument->GetPreloadCsp()) {
bool cspPermitsBaseURI = true;
nsresult rv = csp->Permits(
nullptr, nullptr, newBaseURI,
nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */,
false /* aSendViolationReports */, &cspPermitsBaseURI);
if (NS_FAILED(rv) || !cspPermitsBaseURI) {
return;
}
}
mSpeculationBaseURI = newBaseURI;
mDocument->Preloads().SetSpeculationBase(mSpeculationBaseURI); mDocument->Preloads().SetSpeculationBase(mSpeculationBaseURI);
} }
@ -1338,8 +1371,7 @@ void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
NS_ENSURE_SUCCESS_VOID(rv); NS_ENSURE_SUCCESS_VOID(rv);
} }
// please note that meta CSPs and CSPs delivered through a header need // Please note that multiple meta CSPs need to be joined together.
// to be joined together.
rv = preloadCsp->AppendPolicy( rv = preloadCsp->AppendPolicy(
aCSP, aCSP,
false, // csp via meta tag can not be report only false, // csp via meta tag can not be report only