Commit 4a8612e3 authored by Dave Tapuska's avatar Dave Tapuska Committed by Commit Bot

CSP handling of 'self' inside sandbox iframe was incorrect.

The correct handling of 'self' depended on the timing of when the
ExecutionContext's sandbox flags were applied. If a CSP policy for 'self'
was applied after the origin was derived to be opaque it would fail.

BUG=973991

Change-Id: Ie6f384b02aa3dea3ce48c3052f06b7bd8fb2d3ea
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1658764
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#670074}
parent 65ce79ab
......@@ -185,10 +185,11 @@ void ContentSecurityPolicy::SetupSelf(const ContentSecurityPolicy& other) {
void ContentSecurityPolicy::ApplyPolicySideEffectsToDelegate() {
DCHECK(delegate_);
const SecurityOrigin* security_origin = delegate_->GetSecurityOrigin();
DCHECK(security_origin);
const SecurityOrigin* self_origin =
delegate_->GetSecurityOrigin()->GetOriginOrPrecursorOriginIfOpaque();
DCHECK(self_origin);
SetupSelf(*security_origin);
SetupSelf(*self_origin);
// Set mixed content checking and sandbox flags, then dump all the parsing
// error messages, then poke at histograms.
......
......@@ -1601,4 +1601,23 @@ TEST_F(ContentSecurityPolicyTest, EmptyCSPIsNoOp) {
csp->HasPolicyFromSource(kContentSecurityPolicyHeaderSourceHTTP));
}
TEST_F(ContentSecurityPolicyTest, OpaqueOriginBeforeBind) {
const KURL url("https://example.test");
// Security Origin of execution context might change when sandbox flags
// are applied. This shouldn't change the application of the 'self'
// determination.
secure_origin = secure_origin->DeriveNewOpaqueOrigin();
execution_context = CreateExecutionContext();
csp->BindToDelegate(execution_context->GetContentSecurityPolicyDelegate());
csp->DidReceiveHeader("default-src 'self';",
kContentSecurityPolicyHeaderTypeEnforce,
kContentSecurityPolicyHeaderSourceMeta);
EXPECT_TRUE(
csp->AllowRequest(mojom::RequestContextType::SUBRESOURCE, url, String(),
IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
SecurityViolationReportingPolicy::kSuppressReporting));
}
} // namespace blink
......@@ -305,6 +305,13 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
// its precursor).
scoped_refptr<SecurityOrigin> DeriveNewOpaqueOrigin() const;
// If this is an opaque origin that was derived from a tuple origin, return
// the origin from which this was derived. Otherwise returns |this|. This
// method may be used for things like CSP 'self' computation which require
// the origin before sandbox flags are applied. It should NOT be used for
// any security checks (such as bindings).
const SecurityOrigin* GetOriginOrPrecursorOriginIfOpaque() const;
// Only used for document.domain setting. The method should probably be moved
// if we need it for something more general.
static String CanonicalizeHost(const String& host, bool* success);
......@@ -341,10 +348,6 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
// used only when trying to send an Origin across an IPC pipe.
base::Optional<base::UnguessableToken> GetNonceForSerialization() const;
// If this is an opaque origin that was derived from a tuple origin, return
// the origin from which this was derived. Otherwise returns |this|.
const SecurityOrigin* GetOriginOrPrecursorOriginIfOpaque() const;
const String protocol_ = g_empty_string;
const String host_ = g_empty_string;
String domain_ = g_empty_string;
......
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="base-uri {{location[scheme]}}://{{domains[]}}:{{ports[http][0]}}/base/">
<title>base-uri works correctly inside a sandboxed iframe.</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
</head>
<body>
<h1>self is derived correctly inside inside a sandboxed iframe.</h1>
<div id='log'></div>
<script>
window.addEventListener('securitypolicyviolation', function(e) {
assert_unreached('No CSP violation report should have been fired.');
});
async_test(function(t) {
var i = document.createElement('iframe');
i.sandbox = 'allow-scripts';
i.style.display = 'none';
i.srcdoc = `
<meta http-equiv="Content-Security-Policy" content="img-src 'self'">
<body>
<script>
var img = document.createElement('img');
img.src = '../support/fail.png';
img.onerror = function() {
top.postMessage('FAIL', '*');
};
img.onload = function() {
top.postMessage('PASS', '*');
};
document.body.appendChild(img);
</sc` + `ript></body>`;
window.addEventListener('message', t.step_func(function(e) {
if (e.source === i.contentWindow) {
assert_equals(e.data, 'PASS');
t.done();
}
}));
document.body.appendChild(i);
}, 'img-src \'self\' works when specified in a meta tag.');
</script>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment