Firefox · DOM
CVE-2026-6774
Logic Error in DOM
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
CreateFromCSPdom/security/OffThreadCSPContext.cpp |
modified | |
WorkerCSPContextdom/security/OffThreadCSPContext.h |
modified | |
OffThreadCSPContextdom/security/OffThreadCSPContext.h |
modified | |
ifdom/workers/WorkerLoadInfo.cpp |
modified | |
ifdom/worklet/WorkletImpl.cpp |
modified |
Files Changed
dom/security/OffThreadCSPContext.cppdom/security/OffThreadCSPContext.hdom/security/moz.builddom/security/trusted-types/TrustedTypePolicyFactory.cppdom/workers/RuntimeService.cppdom/workers/WorkerCSPContext.cppdom/workers/WorkerCSPContext.hdom/workers/WorkerLoadInfo.cppdom/workers/WorkerLoadInfo.hdom/workers/WorkerPrivate.cppdom/workers/WorkerPrivate.hdom/workers/moz.builddom/workers/remoteworkers/RemoteWorkerChild.cppdom/worklet/WorkletImpl.cppdom/worklet/WorkletImpl.hdom/worklet/WorkletThread.cpp
Patch
diff --git a/dom/workers/WorkerCSPContext.cpp b/dom/security/OffThreadCSPContext.cpp
similarity index 79%
rename from dom/workers/WorkerCSPContext.cpp
rename to dom/security/OffThreadCSPContext.cpp
index cefbac2c1bc..a06a1a86e73 100644
--- a/dom/workers/WorkerCSPContext.cpp
+++ b/dom/security/OffThreadCSPContext.cpp
@@ -2,11 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "WorkerCSPContext.h"
+#include "OffThreadCSPContext.h"
+#include "MainThreadUtils.h"
#include "mozilla/StaticPrefs_dom.h"
-#include "mozilla/dom/WorkerCommon.h"
-#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/nsCSPParser.h"
#include "mozilla/dom/nsCSPUtils.h"
#include "mozilla/ipc/BackgroundUtils.h"
@@ -15,24 +14,24 @@
namespace mozilla::dom {
/* static */
-Result<UniquePtr<WorkerCSPContext>, nsresult> WorkerCSPContext::CreateFromCSP(
- nsIContentSecurityPolicy* aCSP) {
- AssertIsOnMainThread();
+Result<UniquePtr<OffThreadCSPContext>, nsresult>
+OffThreadCSPContext::CreateFromCSP(nsIContentSecurityPolicy* aCSP) {
+ MOZ_ASSERT(NS_IsMainThread());
mozilla::ipc::CSPInfo cspInfo;
nsresult rv = CSPToCSPInfo(aCSP, &cspInfo);
if (NS_FAILED(rv)) {
return Err(rv);
}
- return MakeUnique<WorkerCSPContext>(std::move(cspInfo));
+ return MakeUnique<OffThreadCSPContext>(std::move(cspInfo));
}
-const nsTArray<UniquePtr<const nsCSPPolicy>>& WorkerCSPContext::Policies() {
+const nsTArray<UniquePtr<const nsCSPPolicy>>& OffThreadCSPContext::Policies() {
EnsureIPCPoliciesRead();
return mPolicies;
}
-bool WorkerCSPContext::IsEvalAllowed(bool& aReportViolation) {
+bool OffThreadCSPContext::IsEvalAllowed(bool& aReportViolation) {
MOZ_ASSERT(!aReportViolation);
bool trustedTypesRequired =
@@ -54,7 +53,7 @@ bool WorkerCSPContext::IsEvalAllowed(bool& aReportViolation) {
return true;
}
-bool WorkerCSPContext::IsWasmEvalAllowed(bool& aReportViolation) {
+bool OffThreadCSPContext::IsWasmEvalAllowed(bool& aReportViolation) {
MOZ_ASSERT(!aReportViolation);
for (const UniquePtr<const nsCSPPolicy>& policy : Policies()) {
// Either 'unsafe-eval' or 'wasm-unsafe-eval' can allow this
@@ -71,8 +70,8 @@ bool WorkerCSPContext::IsWasmEvalAllowed(bool& aReportViolation) {
return true;
}
-void WorkerCSPContext::EnsureIPCPoliciesRead() {
- MOZ_DIAGNOSTIC_ASSERT(!!GetCurrentThreadWorkerPrivate());
+void OffThreadCSPContext::EnsureIPCPoliciesRead() {
+ MOZ_ASSERT(!NS_IsMainThread());
if (!mPolicies.IsEmpty() || mCSPInfo.policyInfos().IsEmpty()) {
return;
diff --git a/dom/workers/WorkerCSPContext.h b/dom/security/OffThreadCSPContext.h
similarity index 68%
rename from dom/workers/WorkerCSPContext.h
rename to dom/security/OffThreadCSPContext.h
index f33d497feee..5f73b14b23e 100644
--- a/dom/workers/WorkerCSPContext.h
+++ b/dom/security/OffThreadCSPContext.h
@@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef mozilla_dom_workers_WorkerCSPContext_h_
-#define mozilla_dom_workers_WorkerCSPContext_h_
+#ifndef mozilla_dom_OffThreadCSPContext_h_
+#define mozilla_dom_OffThreadCSPContext_h_
#include "mozilla/Result.h"
#include "mozilla/UniquePtr.h"
@@ -15,12 +15,13 @@ class nsIContentSecurityPolicy;
namespace mozilla::dom {
-// A minimal version of nsCSPContext that can run on Worker threads.
-class WorkerCSPContext final {
+// A minimal version of nsCSPContext that can run on worker and worklet threads.
+class OffThreadCSPContext final {
public:
- explicit WorkerCSPContext(mozilla::ipc::CSPInfo&& aInfo) : mCSPInfo(aInfo) {}
+ explicit OffThreadCSPContext(mozilla::ipc::CSPInfo&& aInfo)
+ : mCSPInfo(aInfo) {}
- static Result<UniquePtr<WorkerCSPContext>, nsresult> CreateFromCSP(
+ static Result<UniquePtr<OffThreadCSPContext>, nsresult> CreateFromCSP(
nsIContentSecurityPolicy* aCSP);
const mozilla::ipc::CSPInfo& CSPInfo() const { return mCSPInfo; }
@@ -35,15 +36,14 @@ class WorkerCSPContext final {
// Thread boundaries require us to not only store a CSP object, but also a
// serialized version of the CSP. Reason being: Serializing a CSP to a CSPInfo
// needs to happen on the main thread, but storing the CSPInfo needs to happen
- // on the worker thread. We move the CSPInfo into the Client within
- // ScriptExecutorRunnable::PreRun().
+ // on the worker/worklet thread.
mozilla::ipc::CSPInfo mCSPInfo;
- // This is created lazily by parsing the policies in CSPInfo on the worker
- // thread.
+ // This is created lazily by parsing the policies in CSPInfo on the
+ // worker/worklet thread.
nsTArray<UniquePtr<const nsCSPPolicy>> mPolicies;
};
} // namespace mozilla::dom
-#endif // mozilla_dom_workers_WorkerCSPContext_h_
+#endif // mozilla_dom_OffThreadCSPContext_h_
diff --git a/dom/security/moz.build b/dom/security/moz.build
index 147a4dacf3e..f865c75a2a9 100644
--- a/dom/security/moz.build
+++ b/dom/security/moz.build
@@ -29,6 +29,7 @@ EXPORTS.mozilla.dom += [
"nsHTTPSOnlyStreamListener.h",
"nsHTTPSOnlyUtils.h",
"nsMixedContentBlocker.h",
+ "OffThreadCSPContext.h",
"PolicyContainer.h",
"PolicyTokenizer.h",
"ReferrerInfo.h",
@@ -64,6 +65,7 @@ UNIFIED_SOURCES += [
"nsHTTPSOnlyStreamListener.cpp",
"nsHTTPSOnlyUtils.cpp",
"nsMixedContentBlocker.cpp",
+ "OffThreadCSPContext.cpp",
"PolicyContainer.cpp",
"PolicyTokenizer.cpp",
"ReferrerInfo.cpp",
diff --git a/dom/security/trusted-types/TrustedTypePolicyFactory.cpp b/dom/security/trusted-types/TrustedTypePolicyFactory.cpp
index 656a56126f2..ab5ed351972 100644
--- a/dom/security/trusted-types/TrustedTypePolicyFactory.cpp
+++ b/dom/security/trusted-types/TrustedTypePolicyFactory.cpp
@@ -157,7 +157,7 @@ auto TrustedTypePolicyFactory::ShouldTrustedTypePolicyCreationBeBlockedByCSP(
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
}
- if (WorkerCSPContext* ctx = workerPrivate->GetCSPContext()) {
+ if (OffThreadCSPContext* ctx = workerPrivate->GetCSPContext()) {
for (const UniquePtr<const nsCSPPolicy>& policy : ctx->Policies()) {
if (shouldBlock(policy.get())) {
result = PolicyCreation::Blocked;
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
index 477490a0849..2d7ef850680 100644
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -555,12 +555,12 @@ MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION bool ContentSecurityPolicyAllows(
return true;
}
- if (WorkerCSPContext* ctx = worker->GetCSPContext()) {
+ if (OffThreadCSPContext* ctx = worker->GetCSPContext()) {
evalOK = ctx->IsEvalAllowed(reportViolation);
}
violationType = nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL;
} else {
- if (WorkerCSPContext* ctx = worker->GetCSPContext()) {
+ if (OffThreadCSPContext* ctx = worker->GetCSPContext()) {
evalOK = ctx->IsWasmEvalAllowed(reportViolation);
}
diff --git a/dom/workers/WorkerLoadInfo.cpp b/dom/workers/WorkerLoadInfo.cpp
index 9a10f3654e5..5d2542e984e 100644
--- a/dom/workers/WorkerLoadInfo.cpp
+++ b/dom/workers/WorkerLoadInfo.cpp
@@ -113,8 +113,8 @@ nsresult WorkerLoadInfo::SetPrincipalsAndCSPOnMainThread(
mCSP = aCsp;
if (mCSP) {
- Result<UniquePtr<WorkerCSPContext>, nsresult> ctx =
- WorkerCSPContext::CreateFromCSP(aCsp);
+ Result<UniquePtr<OffThreadCSPContext>, nsresult> ctx =
+ OffThreadCSPContext::CreateFromCSP(aCsp);
if (NS_WARN_IF(ctx.isErr())) {
return ctx.unwrapErr();
}
diff --git a/dom/workers/WorkerLoadInfo.h b/dom/workers/WorkerLoadInfo.h
index a52a8cb1663..63b0645991d 100644
--- a/dom/workers/WorkerLoadInfo.h
+++ b/dom/workers/WorkerLoadInfo.h
@@ -12,8 +12,8 @@
#include "mozilla/StorageAccess.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/ChannelInfo.h"
+#include "mozilla/dom/OffThreadCSPContext.h"
#include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
-#include "mozilla/dom/WorkerCSPContext.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/net/NeckoChannelParams.h"
#include "nsIInterfaceRequestor.h"
@@ -70,7 +70,7 @@ struct WorkerLoadInfoData {
nsCOMPtr<nsIScriptContext> mScriptContext;
nsCOMPtr<nsPIDOMWindowInner> mWindow;
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
- UniquePtr<WorkerCSPContext> mCSPContext;
+ UniquePtr<OffThreadCSPContext> mCSPContext;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsILoadGroup> mLoadGroup;
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index 5e961bdc5b0..115cbc60454 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1409,7 +1409,7 @@ nsresult WorkerPrivate::SetCsp(nsIContentSecurityPolicy* aCSP) {
aCSP->EnsureEventTarget(mMainThreadEventTarget);
mLoadInfo.mCSP = aCSP;
- auto ctx = WorkerCSPContext::CreateFromCSP(aCSP);
+ auto ctx = OffThreadCSPContext::CreateFromCSP(aCSP);
if (NS_WARN_IF(ctx.isErr())) {
return ctx.unwrapErr();
}
@@ -1477,7 +1477,7 @@ nsresult WorkerPrivate::SetCSPFromHeaderValues(
mLoadInfo.mCSP = csp;
- auto ctx = WorkerCSPContext::CreateFromCSP(csp);
+ auto ctx = OffThreadCSPContext::CreateFromCSP(csp);
if (NS_WARN_IF(ctx.isErr())) {
return ctx.unwrapErr();
}
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index 62216aa3362..3110d859825 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -961,7 +961,7 @@ class WorkerPrivate final
return mLoadInfo.mCSPContext->CSPInfo();
}
- WorkerCSPContext* GetCSPContext() const {
+ OffThreadCSPContext* GetCSPContext() const {
return mLoadInfo.mCSPContext.get();
}
diff --git a/dom/workers/moz.build b/dom/workers/moz.build
index 2f2948a7294..c7818826d18 100644
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -17,7 +17,6 @@ EXPORTS.mozilla.dom += [
"Worker.h",
"WorkerChannelInfo.h",
"WorkerCommon.h",
- "WorkerCSPContext.h",
"WorkerDebugger.h",
"WorkerDebuggerManager.h",
"WorkerDocumentListener.h",
@@ -61,7 +60,6 @@ UNIFIED_SOURCES += [
"ScriptLoader.cpp",
"Worker.cpp",
"WorkerChannelInfo.cpp",
- "WorkerCSPContext.cpp",
"WorkerCSPEventListener.cpp",
"WorkerDebugger.cpp",
"WorkerDebuggerManager.cpp",
diff --git a/dom/workers/remoteworkers/RemoteWorkerChild.cpp b/dom/workers/remoteworkers/RemoteWorkerChild.cpp
index 006b2ec52c6..992a0227616 100644
--- a/dom/workers/remoteworkers/RemoteWorkerChild.cpp
+++ b/dom/workers/remoteworkers/RemoteWorkerChild.cpp
@@ -21,6 +21,7 @@
#include "mozilla/dom/FetchEventOpProxyChild.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/dom/MessagePort.h"
+#include "mozilla/dom/OffThreadCSPContext.h"
#include "mozilla/dom/PolicyContainer.h"
#include "mozilla/dom/RemoteWorkerTypes.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
@@ -30,7 +31,6 @@
#include "mozilla/dom/ServiceWorkerShutdownState.h"
#include "mozilla/dom/ServiceWorkerUtils.h"
#include "mozilla/dom/SharedWorkerOp.h"
-#include "mozilla/dom/WorkerCSPContext.h"
#include "mozilla/dom/WorkerError.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
@@ -305,8 +305,8 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(
clientInfo.ref().GetPolicyContainerArgs();
if (policyContainerArgs.isSome() && policyContainerArgs->csp().isSome()) {
info.mCSP = CSPInfoToCSP(*policyContainerArgs->csp(), nullptr);
- mozilla::Result<UniquePtr<WorkerCSPContext>, nsresult> ctx =
- WorkerCSPContext::CreateFromCSP(info.mCSP);
+ mozilla::Result<UniquePtr<OffThreadCSPContext>, nsresult> ctx =
+ OffThreadCSPContext::CreateFromCSP(info.mCSP);
if (ctx.isErr()) {
return ctx.unwrapErr();
}
diff --git a/dom/worklet/WorkletImpl.cpp b/dom/worklet/WorkletImpl.cpp
index 47f030f3705..ebe030548a2 100644
--- a/dom/worklet/WorkletImpl.cpp
+++ b/dom/worklet/WorkletImpl.cpp
@@ -12,6 +12,7 @@
#include "mozilla/NullPrincipal.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/Document.h"
+#include "mozilla/dom/PolicyContainer.h"
#include "mozilla/dom/RegisterWorkletBindings.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/WorkletBinding.h"
@@ -60,11 +61,17 @@ WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal)
mShouldResistFingerprinting = aWindow->AsGlobal()->ShouldResistFingerprinting(
RFPTarget::IsAlwaysEnabledForPrecompute);
- RefPtr<dom::Document> doc = nsGlobalWindowInner::Cast(aWindow)->GetDocument();
- if (doc) {
+ if (RefPtr<dom::Document> doc =
+ nsGlobalWindowInner::Cast(aWindow)->GetDocument()) {
mIsPrivateBrowsing = doc->IsInPrivateBrowsing();
mOverriddenFingerprintingSettings =
doc->GetOverriddenFingerprintingSettings();
+
+ if (auto* policy = PolicyContainer::Cast(doc->GetPolicyContainer())) {
+ ipc::PolicyContainerArgs policyContainer;
+ PolicyContainer::ToArgs(policy, policyContainer);
+ mPolicyContainer = Some(std::move(policyContainer));
+ }
}
}
@@ -114,6 +121,16 @@ dom::WorkletGlobalScope* WorkletImpl::GetGlobalScope() {
return mGlobalScope;
}
+dom::OffThreadCSPContext* WorkletImpl::GetCSPContext() {
+ dom::WorkletThread::AssertIsOnWorkletThread();
+
+ if (!mCSPContext && mPolicyContainer && mPolicyContainer->csp().isSome()) {
+ ipc::CSPInfo cspInfo(mPolicyContainer->csp().ref());
+ mCSPContext = MakeUnique<dom::OffThreadCSPContext>(std::move(cspInfo));
+ }
+ return mCSPContext.get();
+}
+
void WorkletImpl::NotifyWorkletFinished() {
MOZ_ASSERT(NS_IsMainThread());
@@ -127,6 +144,7 @@ void WorkletImpl::NotifyWorkletFinished() {
[self = RefPtr<WorkletImpl>(this)]() {
self->mFinishedOnExecutionThread = true;
self->mGlobalScope = nullptr;
+ self->mCSPContext = nullptr;
}));
mTerminated = true;
diff --git a/dom/worklet/WorkletImpl.h b/dom/worklet/WorkletImpl.h
index b73217ceb27..dcfc2cba3d8 100644
--- a/dom/worklet/WorkletImpl.h
+++ b/dom/worklet/WorkletImpl.h
@@ -12,6 +12,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/OriginAttributes.h"
#include "mozilla/OriginTrials.h"
+#include "mozilla/dom/OffThreadCSPContext.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsRFPService.h"
@@ -68,6 +69,7 @@ class WorkletImpl {
// Execution thread only.
dom::WorkletGlobalScope* GetGlobalScope();
+ dom::OffThreadCSPContext* GetCSPContext();
// Any thread.
@@ -78,6 +80,9 @@ class WorkletImpl {
}
nsIPrincipal* Principal() const { return mPrincipal; }
const ipc::PrincipalInfo& PrincipalInfo() const { return mPrincipalInfo; }
+ const Maybe<ipc::PolicyContainerArgs>& PolicyContainer() const {
+ return mPolicyContainer;
+ }
const Maybe<nsID>& GetAgentClusterId() const { return mAgentClusterId; }
@@ -109,6 +114,7 @@ class WorkletImpl {
// Modified only in constructor.
ipc::PrincipalInfo mPrincipalInfo;
nsCOMPtr<nsIPrincipal> mPrincipal;
+ Maybe<ipc::PolicyContainerArgs> mPolicyContainer;
const WorkletLoadInfo mWorkletLoadInfo;
@@ -118,6 +124,7 @@ class WorkletImpl {
... (file diff truncated)
Loading diff…
References
On This Page