From 23f3449b1c68248c6a54ca7784a1942ecb05df35 Mon Sep 17 00:00:00 2001 From: James Burke Date: Fri, 29 Jan 2016 13:32:01 -0800 Subject: [PATCH] Bug 1139849 - postMessage to incorrect target domain should print a console security error r=bz --- dom/base/PostMessageEvent.cpp | 22 +++++++++++++++++++++ dom/base/PostMessageEvent.h | 2 ++ dom/base/nsGlobalWindow.cpp | 3 +++ dom/locales/en-US/chrome/dom/dom.properties | 2 ++ 4 files changed, 29 insertions(+) diff --git a/dom/base/PostMessageEvent.cpp b/dom/base/PostMessageEvent.cpp index b33445189c3..50d6fbae758 100644 --- a/dom/base/PostMessageEvent.cpp +++ b/dom/base/PostMessageEvent.cpp @@ -28,6 +28,7 @@ PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource, const nsAString& aCallerOrigin, nsGlobalWindow* aTargetWindow, nsIPrincipal* aProvidedPrincipal, + nsIDocument* aSourceDocument, bool aTrustedCaller) : StructuredCloneHolder(CloningSupported, TransferringSupported, SameProcessSameThread), @@ -35,6 +36,7 @@ PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource, mCallerOrigin(aCallerOrigin), mTargetWindow(aTargetWindow), mProvidedPrincipal(aProvidedPrincipal), + mSourceDocument(aSourceDocument), mTrustedCaller(aTrustedCaller) { MOZ_COUNT_CTOR(PostMessageEvent); @@ -57,6 +59,12 @@ PostMessageEvent::Run() jsapi.Init(); JSContext* cx = jsapi.cx(); + // The document is just used for the principal mismatch error message below. + // Use a stack variable so mSourceDocument is not held onto after this method + // finishes, regardless of the method outcome. + nsCOMPtr sourceDocument; + sourceDocument.swap(mSourceDocument); + // If we bailed before this point we're going to leak mMessage, but // that's probably better than crashing. @@ -92,6 +100,20 @@ PostMessageEvent::Run() // now. Long-term, we want HTML5 to address this so that we can // be compliant while being safer. if (!targetPrin->Equals(mProvidedPrincipal)) { + nsAutoString providedOrigin, targetOrigin; + nsresult rv = nsContentUtils::GetUTFOrigin(targetPrin, targetOrigin); + NS_ENSURE_SUCCESS(rv, rv); + rv = nsContentUtils::GetUTFOrigin(mProvidedPrincipal, providedOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + const char16_t* params[] = { providedOrigin.get(), targetOrigin.get() }; + + nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("DOM Window"), sourceDocument, + nsContentUtils::eDOM_PROPERTIES, + "TargetPrincipalDoesNotMatch", + params, ArrayLength(params)); + return NS_OK; } } diff --git a/dom/base/PostMessageEvent.h b/dom/base/PostMessageEvent.h index 2916a4818a1..54e1a29d6e2 100644 --- a/dom/base/PostMessageEvent.h +++ b/dom/base/PostMessageEvent.h @@ -34,6 +34,7 @@ public: const nsAString& aCallerOrigin, nsGlobalWindow* aTargetWindow, nsIPrincipal* aProvidedPrincipal, + nsIDocument* aSourceDocument, bool aTrustedCaller); private: @@ -43,6 +44,7 @@ private: nsString mCallerOrigin; RefPtr mTargetWindow; nsCOMPtr mProvidedPrincipal; + nsCOMPtr mSourceDocument; bool mTrustedCaller; }; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 97b5db16032..1b9b17e224f 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -7969,6 +7969,9 @@ nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle aMessa origin, this, providedPrincipal, + callerInnerWin + ? callerInnerWin->GetDoc() + : nullptr, nsContentUtils::IsCallerChrome()); JS::Rooted message(aCx, aMessage); diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 34fdb46c0cb..c68d464b7c0 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -190,3 +190,5 @@ InterceptionRejectedResponseWithURL=Failed to load '%1$S'. A ServiceWorker passe InterceptedNonResponseWithURL=Failed to load '%1$S'. A ServiceWorker passed a promise to FetchEvent.respondWith() that resolved with non-Response value '%2$S'. ExecCommandCutCopyDeniedNotInputDriven=document.execCommand('cut'/'copy') was denied because it was not called from inside a short running user-generated event handler. PatternAttributeCompileFailure=Unable to check because the pattern is not a valid regexp: %S +# LOCALIZATION NOTE: Do not translate "postMessage" or DOMWindow. %S values are origins, like https://domain.com:port +TargetPrincipalDoesNotMatch=Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('%S') does not match the recipient window's origin ('%S').