Bug 725490 - Change XFO sameorigin to check all ancestors for same origin. draft
authorJonathan Kingston <jkt@mozilla.com>
Fri, 03 Nov 2017 15:37:10 +0000
changeset 696833 d4053f69c99fa44d307e47006863ccce8d56a7ad
parent 696686 933f9cd9b3b9030399a11c19cb4e5117b29e2772
child 739942 04c2a011feb86763a6085e462ff95a5d6bab730d
push id88805
push userbmo:jkt@mozilla.com
push dateSat, 11 Nov 2017 22:55:11 +0000
bugs725490
milestone58.0a1
Bug 725490 - Change XFO sameorigin to check all ancestors for same origin. MozReview-Commit-ID: 5fPxGpcdVms
dom/security/FramingChecker.cpp
testing/web-platform/meta/x-frame-options/sameorigin.sub.html.ini
--- a/dom/security/FramingChecker.cpp
+++ b/dom/security/FramingChecker.cpp
@@ -63,17 +63,18 @@ FramingChecker::CheckOneFrameOptionsPoli
   }
 
   // Find the top docshell in our parent chain that doesn't have the system
   // principal and use it for the principal comparison.  Finding the top
   // content-type docshell doesn't work because some chrome documents are
   // loaded in content docshells (see bug 593387).
   nsCOMPtr<nsIDocShellTreeItem> thisDocShellItem(
     do_QueryInterface(static_cast<nsIDocShell*>(aDocShell)));
-  nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem;
+  nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem,
+                                topDocShellItem;
   nsCOMPtr<nsIDocShellTreeItem> curDocShellItem = thisDocShellItem;
   nsCOMPtr<nsIDocument> topDoc;
   nsresult rv;
   nsCOMPtr<nsIScriptSecurityManager> ssm =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
   if (!ssm) {
     MOZ_CRASH();
   }
@@ -120,18 +121,39 @@ FramingChecker::CheckOneFrameOptionsPoli
 
   topDoc = curDocShellItem->GetDocument();
   nsCOMPtr<nsIURI> topUri;
   topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri));
 
   // If the X-Frame-Options value is SAMEORIGIN, then the top frame in the
   // parent chain must be from the same origin as this document.
   if (aPolicy.LowerCaseEqualsLiteral("sameorigin")) {
-    rv = ssm->CheckSameOriginURI(uri, topUri, true);
-    if (NS_FAILED(rv)) {
+
+    bool sameOrigin = true;
+    topDocShellItem = curDocShellItem;
+    curDocShellItem = thisDocShellItem;
+    nsCOMPtr<nsIURI> uri;
+    aHttpChannel->GetURI(getter_AddRefs(uri));
+    nsCOMPtr<nsIURI> topUri;
+
+    do {
+      curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem));
+      topDoc = do_GetInterface(parentDocShellItem);
+      topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri));
+      rv = ssm->CheckSameOriginURI(uri, topUri, true);
+
+      // one of the ancestors is not same origin as this document
+      if (NS_FAILED(rv)) {
+        sameOrigin = false;
+        break;
+      }
+      curDocShellItem = parentDocShellItem;
+    } while (curDocShellItem != topDocShellItem);
+
+    if (!sameOrigin) {
       ReportXFOViolation(curDocShellItem, uri, eSAMEORIGIN);
       return false; /* wasn't same-origin */
     }
   }
 
   // If the X-Frame-Options value is "allow-from [uri]", then the top
   // frame in the parent chain must be from that origin
   if (isAllowFrom) {
--- a/testing/web-platform/meta/x-frame-options/sameorigin.sub.html.ini
+++ b/testing/web-platform/meta/x-frame-options/sameorigin.sub.html.ini
@@ -1,8 +1,5 @@
 [sameorigin.sub.html]
   type: testharness
   [`XFO: SAMEORIGIN` blocks cross-origin framing.]
     expected: FAIL
 
-  [`XFO: SAMEORIGIN` blocks same-origin nested in cross-origin framing.]
-    expected: FAIL
-