diff --git a/caps/include/nsNullPrincipal.h b/caps/include/nsNullPrincipal.h index 10b83f3cfa0c..7e7b1c68bb58 100644 --- a/caps/include/nsNullPrincipal.h +++ b/caps/include/nsNullPrincipal.h @@ -16,6 +16,7 @@ #include "nsJSPrincipals.h" #include "nsCOMPtr.h" #include "nsPrincipal.h" +#include "nsIContentSecurityPolicy.h" class nsIURI; @@ -53,6 +54,7 @@ public: virtual ~nsNullPrincipal(); nsCOMPtr mURI; + nsCOMPtr mCSP; }; #endif // nsNullPrincipal_h__ diff --git a/caps/src/nsNullPrincipal.cpp b/caps/src/nsNullPrincipal.cpp index 9ff9730bc8df..639e064051fe 100644 --- a/caps/src/nsNullPrincipal.cpp +++ b/caps/src/nsNullPrincipal.cpp @@ -149,8 +149,11 @@ nsNullPrincipal::GetHashValue(uint32_t *aResult) NS_IMETHODIMP nsNullPrincipal::GetSecurityPolicy(void** aSecurityPolicy) { - // We don't actually do security policy caching. And it's not like anyone - // can set a security policy for us anyway. + // Leftover from old security model, a "security policy" is a set of + // rules for property access that can override the SOP. Policies are + // associated with origins and since nsNullPinricipals never get the + // same origin twice, it's not possible to specify a "security + // policy" for it. Hence, we do not cache the security policy. *aSecurityPolicy = nullptr; return NS_OK; } @@ -158,8 +161,11 @@ nsNullPrincipal::GetSecurityPolicy(void** aSecurityPolicy) NS_IMETHODIMP nsNullPrincipal::SetSecurityPolicy(void* aSecurityPolicy) { - // We don't actually do security policy caching. And it's not like anyone - // can set a security policy for us anyway. + // Leftover from old security model, a "security policy" is a set of + // rules for property access that can override the SOP. Policies are + // associated with origins and since nsNullPinricipals never get the + // same origin twice, it's not possible to specify a "security + // policy" for it. Hence, we do not cache the security policy. return NS_OK; } @@ -172,16 +178,20 @@ nsNullPrincipal::GetURI(nsIURI** aURI) NS_IMETHODIMP nsNullPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) { - // CSP on a null principal makes no sense - *aCsp = nullptr; + NS_IF_ADDREF(*aCsp = mCSP); return NS_OK; } NS_IMETHODIMP nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) { - // CSP on a null principal makes no sense - return NS_ERROR_NOT_AVAILABLE; + // If CSP was already set, it should not be destroyed! Instead, it should + // get set anew when a new principal is created. + if (mCSP) + return NS_ERROR_ALREADY_INITIALIZED; + + mCSP = aCsp; + return NS_OK; } NS_IMETHODIMP diff --git a/content/base/src/contentSecurityPolicy.js b/content/base/src/contentSecurityPolicy.js index f5be9abe93c7..03e7236a61d2 100644 --- a/content/base/src/contentSecurityPolicy.js +++ b/content/base/src/contentSecurityPolicy.js @@ -51,9 +51,9 @@ function ContentSecurityPolicy() { this._request = ""; this._requestOrigin = ""; - this._requestPrincipal = ""; + this._weakRequestPrincipal = { get : function() { return null; } }; this._referrer = ""; - this._docRequest = null; + this._weakDocRequest = { get : function() { return null; } }; CSPdebug("CSP object initialized, no policies to enforce yet"); this._cache = { }; @@ -296,7 +296,7 @@ ContentSecurityPolicy.prototype = { return; // Save the docRequest for fetching a policy-uri - this._docRequest = aChannel; + this._weakDocRequest = Cu.getWeakReference(aChannel); // save the document URI (minus ) and referrer for reporting let uri = aChannel.URI.cloneIgnoringRef(); @@ -307,8 +307,9 @@ ContentSecurityPolicy.prototype = { this._requestOrigin = uri; //store a reference to the principal, that can later be used in shouldLoad - this._requestPrincipal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager).getChannelPrincipal(aChannel); + this._weakRequestPrincipal = Cu.getWeakReference(Cc["@mozilla.org/scriptsecuritymanager;1"] + .getService(Ci.nsIScriptSecurityManager) + .getChannelPrincipal(aChannel)); if (aChannel.referrer) { let referrer = aChannel.referrer.cloneIgnoringRef(); @@ -358,13 +359,13 @@ ContentSecurityPolicy.prototype = { newpolicy = CSPRep.fromStringSpecCompliant(aPolicy, selfURI, aReportOnly, - this._docRequest, + this._weakDocRequest.get(), this); } else { newpolicy = CSPRep.fromString(aPolicy, selfURI, aReportOnly, - this._docRequest, + this._weakDocRequest.get(), this); } @@ -481,8 +482,8 @@ ContentSecurityPolicy.prototype = { // we need to set an nsIChannelEventSink on the channel object // so we can tell it to not follow redirects when posting the reports chan.notificationCallbacks = new CSPReportRedirectSink(policy); - if (this._docRequest) { - chan.loadGroup = this._docRequest.loadGroup; + if (this._weakDocRequest.get()) { + chan.loadGroup = this._weakDocRequest.get().loadGroup; } chan.QueryInterface(Ci.nsIUploadChannel) @@ -501,7 +502,7 @@ ContentSecurityPolicy.prototype = { .getService(Ci.nsIContentPolicy); if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_CSP_REPORT, chan.URI, this._requestOrigin, - null, null, null, this._requestPrincipal) + null, null, null, this._weakRequestPrincipal.get()) != Ci.nsIContentPolicy.ACCEPT) { continue; // skip unauthorized URIs } diff --git a/content/base/test/csp/file_bug886164.html b/content/base/test/csp/file_bug886164.html new file mode 100644 index 000000000000..e47c2bc5da5a --- /dev/null +++ b/content/base/test/csp/file_bug886164.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/content/base/test/csp/file_bug886164.html^headers^ b/content/base/test/csp/file_bug886164.html^headers^ new file mode 100644 index 000000000000..4c6fa3c26a77 --- /dev/null +++ b/content/base/test/csp/file_bug886164.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'self' diff --git a/content/base/test/csp/file_bug886164_2.html b/content/base/test/csp/file_bug886164_2.html new file mode 100644 index 000000000000..f08826f698ff --- /dev/null +++ b/content/base/test/csp/file_bug886164_2.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/content/base/test/csp/file_bug886164_2.html^headers^ b/content/base/test/csp/file_bug886164_2.html^headers^ new file mode 100644 index 000000000000..4c6fa3c26a77 --- /dev/null +++ b/content/base/test/csp/file_bug886164_2.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'self' diff --git a/content/base/test/csp/file_bug886164_3.html b/content/base/test/csp/file_bug886164_3.html new file mode 100644 index 000000000000..7cefd6569c86 --- /dev/null +++ b/content/base/test/csp/file_bug886164_3.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/content/base/test/csp/file_bug886164_3.html^headers^ b/content/base/test/csp/file_bug886164_3.html^headers^ new file mode 100644 index 000000000000..6581fd425ed9 --- /dev/null +++ b/content/base/test/csp/file_bug886164_3.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'none' diff --git a/content/base/test/csp/file_bug886164_4.html b/content/base/test/csp/file_bug886164_4.html new file mode 100644 index 000000000000..146c6ba01fcd --- /dev/null +++ b/content/base/test/csp/file_bug886164_4.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/content/base/test/csp/file_bug886164_4.html^headers^ b/content/base/test/csp/file_bug886164_4.html^headers^ new file mode 100644 index 000000000000..6581fd425ed9 --- /dev/null +++ b/content/base/test/csp/file_bug886164_4.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'none' diff --git a/content/base/test/csp/file_bug886164_5.html b/content/base/test/csp/file_bug886164_5.html new file mode 100644 index 000000000000..1d9bd022c173 --- /dev/null +++ b/content/base/test/csp/file_bug886164_5.html @@ -0,0 +1,26 @@ + + + + + + + I am sandboxed but with only inline "allow-scripts" + + + + + + + + + + + diff --git a/content/base/test/csp/file_bug886164_5.html^headers^ b/content/base/test/csp/file_bug886164_5.html^headers^ new file mode 100644 index 000000000000..3abc19055220 --- /dev/null +++ b/content/base/test/csp/file_bug886164_5.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'none' 'unsafe-inline'; diff --git a/content/base/test/csp/file_bug886164_6.html b/content/base/test/csp/file_bug886164_6.html new file mode 100644 index 000000000000..211a2aa06694 --- /dev/null +++ b/content/base/test/csp/file_bug886164_6.html @@ -0,0 +1,35 @@ + + + + + + + + + + I am sandboxed but with "allow-scripts" + + + +
+ First name: + Last name: + +
+ + click me + + diff --git a/content/base/test/csp/file_bug886164_6.html^headers^ b/content/base/test/csp/file_bug886164_6.html^headers^ new file mode 100644 index 000000000000..6f9fc3f25de2 --- /dev/null +++ b/content/base/test/csp/file_bug886164_6.html^headers^ @@ -0,0 +1 @@ +Content-Security-Policy: default-src 'self' 'unsafe-inline'; diff --git a/content/base/test/csp/mochitest.ini b/content/base/test/csp/mochitest.ini index 42b7767a1b7a..fc9dcc91222e 100644 --- a/content/base/test/csp/mochitest.ini +++ b/content/base/test/csp/mochitest.ini @@ -68,6 +68,18 @@ support-files = file_bug836922_npolicies.html^headers^ file_bug836922_npolicies_ro_violation.sjs file_bug836922_npolicies_violation.sjs + file_bug886164.html + file_bug886164.html^headers^ + file_bug886164_2.html + file_bug886164_2.html^headers^ + file_bug886164_3.html + file_bug886164_3.html^headers^ + file_bug886164_4.html + file_bug886164_4.html^headers^ + file_bug886164_5.html + file_bug886164_5.html^headers^ + file_bug886164_6.html + file_bug886164_6.html^headers^ file_csp_bug768029.html file_csp_bug768029.sjs file_csp_bug773891.html @@ -101,6 +113,7 @@ support-files = [test_CSP_inlinestyle.html] [test_bothCSPheaders.html] [test_bug836922_npolicies.html] +[test_bug886164.html] [test_csp_redirects.html] [test_CSP_bug910139.html] [test_CSP_bug909029.html] diff --git a/content/base/test/csp/test_bug886164.html b/content/base/test/csp/test_bug886164.html new file mode 100644 index 000000000000..3cdea4ca1e9e --- /dev/null +++ b/content/base/test/csp/test_bug886164.html @@ -0,0 +1,183 @@ + + + + + Bug 886164 - Enforce CSP in sandboxed iframe + + + + +

+ + + + + + + + + + + + diff --git a/testing/mochitest/b2g.json b/testing/mochitest/b2g.json index d2762dbdf28b..90eeee181578 100644 --- a/testing/mochitest/b2g.json +++ b/testing/mochitest/b2g.json @@ -209,6 +209,7 @@ "content/base/test/csp/test_CSP_frameancestors.html":"observer not working", "content/base/test/csp/test_CSP.html":"observer not working", "content/base/test/csp/test_bug836922_npolicies.html":"observer not working", + "content/base/test/csp/test_bug886164.html":"observer not working", "content/base/test/csp/test_CSP_bug916446.html":"observer not working", "content/base/test/csp/test_CSP_bug909029.html":"observer not working", "content/base/test/csp/test_policyuri_regression_from_multipolicy.html":"observer not working",