зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1731778
- Implement COEP: credentialless r=smaug,necko-reviewers,kershaw
Spec: https://html.spec.whatwg.org/multipage/#coep:coep-credentialless Credentialless is a new cross-origin embedder policy which allows us to not enforcing CORP when loading cross-origin resources while providing SharedArrayBuffer. There are two main things involved here: 1. Fetching cross-origin no-CORS resources omits credentials - This is done by applying `LOAD_ANONYMOUS` flag to the request 2. Other requests sent with credentials require the server's explicit permission through the CORS protocol or the CORS header - This is done by expanding `ProcessCrossOriginResourcePolicyHeader` function to apply the necessary checks. Differential Revision: https://phabricator.services.mozilla.com/D147802
This commit is contained in:
Родитель
20e4c096c5
Коммит
6acee53f6c
|
@ -1513,6 +1513,10 @@ nsresult nsContentSecurityManager::CheckChannel(nsIChannel* aChannel) {
|
|||
AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
|
||||
}
|
||||
|
||||
if (!CrossOriginEmbedderPolicyAllowsCredentials(aChannel)) {
|
||||
AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
|
||||
}
|
||||
|
||||
nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
|
||||
|
||||
// CORS mode is handled by nsCORSListenerProxy
|
||||
|
@ -1562,6 +1566,54 @@ nsresult nsContentSecurityManager::CheckChannel(nsIChannel* aChannel) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#ref-for-cross-origin-embedder-policy-allows-credentials
|
||||
bool nsContentSecurityManager::CrossOriginEmbedderPolicyAllowsCredentials(
|
||||
nsIChannel* aChannel) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
|
||||
// 1. If request’s mode is not "no-cors", then return true.
|
||||
//
|
||||
// `no-cors` check applies to document navigation such that if it is
|
||||
// an document navigation, this check should return true to allow
|
||||
// credentials.
|
||||
if (loadInfo->GetExternalContentPolicyType() ==
|
||||
ExtContentPolicy::TYPE_DOCUMENT ||
|
||||
loadInfo->GetExternalContentPolicyType() ==
|
||||
ExtContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (loadInfo->GetSecurityMode() !=
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL &&
|
||||
loadInfo->GetSecurityMode() !=
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If request’s client’s policy container’s embedder policy’s value is not
|
||||
// "credentialless", then return true.
|
||||
if (loadInfo->GetLoadingEmbedderPolicy() !=
|
||||
nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If request’s origin is same origin with request’s current URL’s origin and
|
||||
// request does not have a redirect-tainted origin, then return true.
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
nsCOMPtr<nsIPrincipal> resourcePrincipal;
|
||||
ssm->GetChannelURIPrincipal(aChannel, getter_AddRefs(resourcePrincipal));
|
||||
|
||||
bool sameOrigin = resourcePrincipal->Equals(loadInfo->TriggeringPrincipal());
|
||||
nsAutoCString serializedOrigin;
|
||||
GetSerializedOrigin(loadInfo->TriggeringPrincipal(), resourcePrincipal,
|
||||
serializedOrigin, loadInfo);
|
||||
if (sameOrigin && !serializedOrigin.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#serializing-a-request-origin
|
||||
void nsContentSecurityManager::GetSerializedOrigin(
|
||||
nsIPrincipal* aOrigin, nsIPrincipal* aResourceOrigin,
|
||||
|
|
|
@ -81,6 +81,7 @@ class nsContentSecurityManager : public nsIContentSecurityManager,
|
|||
static nsresult CheckAllowLoadInSystemPrivilegedContext(nsIChannel* aChannel);
|
||||
static nsresult CheckAllowLoadInPrivilegedAboutContext(nsIChannel* aChannel);
|
||||
static nsresult CheckChannelHasProtocolSecurityFlag(nsIChannel* aChannel);
|
||||
static bool CrossOriginEmbedderPolicyAllowsCredentials(nsIChannel* aChannel);
|
||||
|
||||
virtual ~nsContentSecurityManager() = default;
|
||||
};
|
||||
|
|
|
@ -916,7 +916,8 @@ struct CrossOriginEmbedderPolicyValidator {
|
|||
|
||||
static bool IsLegalValue(const IntegralType e) {
|
||||
return AreIntegralValuesEqual(e, nsILoadInfo::EMBEDDER_POLICY_NULL) ||
|
||||
AreIntegralValuesEqual(e, nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP);
|
||||
AreIntegralValuesEqual(e, nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) ||
|
||||
AreIntegralValuesEqual(e, nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -1517,6 +1517,13 @@
|
|||
value: true
|
||||
mirror: always
|
||||
|
||||
# This pref makes `credentialless` a valid value for
|
||||
# Cross-Origin-Embedder-Policy header
|
||||
- name: browser.tabs.remote.coep.credentialless
|
||||
type: RelaxedAtomicBool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# When this pref is enabled top level loads with a mismatched
|
||||
# Cross-Origin-Opener-Policy header will be loaded in a separate process.
|
||||
- name: browser.tabs.remote.useCrossOriginOpenerPolicy
|
||||
|
|
|
@ -1380,6 +1380,7 @@ interface nsILoadInfo : nsISupports
|
|||
cenum CrossOriginEmbedderPolicy : 8 {
|
||||
EMBEDDER_POLICY_NULL = 0,
|
||||
EMBEDDER_POLICY_REQUIRE_CORP = 1,
|
||||
EMBEDDER_POLICY_CREDENTIALLESS = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -2626,9 +2626,14 @@ NS_GetCrossOriginEmbedderPolicyFromHeader(const nsACString& aHeader) {
|
|||
return nsILoadInfo::EMBEDDER_POLICY_NULL;
|
||||
}
|
||||
|
||||
return embedderPolicy.EqualsLiteral("require-corp")
|
||||
? nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP
|
||||
: nsILoadInfo::EMBEDDER_POLICY_NULL;
|
||||
if (embedderPolicy.EqualsLiteral("require-corp")) {
|
||||
return nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP;
|
||||
} else if (embedderPolicy.EqualsLiteral("credentialless") &&
|
||||
StaticPrefs::browser_tabs_remote_coep_credentialless()) {
|
||||
return nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS;
|
||||
}
|
||||
|
||||
return nsILoadInfo::EMBEDDER_POLICY_NULL;
|
||||
}
|
||||
|
||||
/** Given the first (disposition) token from a Content-Disposition header,
|
||||
|
|
|
@ -2401,12 +2401,13 @@ nsresult HttpBaseChannel::ProcessCrossOriginEmbedderPolicyHeader() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// https://mikewest.github.io/corpp/#abstract-opdef-process-navigation-response
|
||||
// https://html.spec.whatwg.org/multipage/origin.html#coep
|
||||
if (mLoadInfo->GetExternalContentPolicyType() ==
|
||||
ExtContentPolicy::TYPE_SUBDOCUMENT &&
|
||||
mLoadInfo->GetLoadingEmbedderPolicy() !=
|
||||
nsILoadInfo::EMBEDDER_POLICY_NULL &&
|
||||
resultPolicy != nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) {
|
||||
resultPolicy != nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP &&
|
||||
resultPolicy != nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS) {
|
||||
return NS_ERROR_DOM_COEP_FAILED;
|
||||
}
|
||||
|
||||
|
@ -2458,13 +2459,29 @@ nsresult HttpBaseChannel::ProcessCrossOriginResourcePolicyHeader() {
|
|||
content);
|
||||
|
||||
if (StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
|
||||
// COEP 3.2.1.6 If policy is null, and embedder policy is "require-corp",
|
||||
// set policy to "same-origin".
|
||||
// Note that we treat invalid value as "cross-origin", which spec
|
||||
// indicates. We might want to make that stricter.
|
||||
if (content.IsEmpty() && mLoadInfo->GetLoadingEmbedderPolicy() ==
|
||||
nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) {
|
||||
content = "same-origin"_ns;
|
||||
if (content.IsEmpty()) {
|
||||
if (mLoadInfo->GetLoadingEmbedderPolicy() ==
|
||||
nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS &&
|
||||
StaticPrefs::browser_tabs_remote_coep_credentialless()) {
|
||||
bool requestIncludesCredentials = false;
|
||||
nsresult rv = GetCorsIncludeCredentials(&requestIncludesCredentials);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
// COEP: Set policy to `same-origin` if: response’s
|
||||
// request-includes-credentials is true, or forNavigation is true.
|
||||
if (requestIncludesCredentials ||
|
||||
extContentPolicyType == ExtContentPolicyType::TYPE_SUBDOCUMENT) {
|
||||
content = "same-origin"_ns;
|
||||
}
|
||||
} else if (mLoadInfo->GetLoadingEmbedderPolicy() ==
|
||||
nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) {
|
||||
// COEP 3.2.1.6 If policy is null, and embedder policy is
|
||||
// "require-corp", set policy to "same-origin". Note that we treat
|
||||
// invalid value as "cross-origin", which spec indicates. We might want
|
||||
// to make that stricter.
|
||||
content = "same-origin"_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5726,7 +5743,8 @@ NS_IMETHODIMP HttpBaseChannel::ComputeCrossOriginOpenerPolicy(
|
|||
nsILoadInfo::CrossOriginEmbedderPolicy coep =
|
||||
nsILoadInfo::EMBEDDER_POLICY_NULL;
|
||||
if (NS_SUCCEEDED(GetResponseEmbedderPolicy(&coep)) &&
|
||||
coep == nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) {
|
||||
(coep == nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP ||
|
||||
coep == nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS)) {
|
||||
policy =
|
||||
nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1698587
|
||||
prefs: [browser.tabs.remote.useCrossOriginEmbedderPolicy:true, browser.tabs.remote.coep.credentialless:true]
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[reporting-navigation.https.window.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1652926
|
|
@ -0,0 +1,2 @@
|
|||
[reporting-subresource-corp.https.window.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1652926
|
|
@ -0,0 +1,2 @@
|
|||
[service-worker-coep-credentialless-proxy.https.window.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1613912
|
|
@ -0,0 +1,2 @@
|
|||
[service-worker-coep-none-proxy.https.window.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1613912
|
Загрузка…
Ссылка в новой задаче