Commit ca6496df authored by arthursonzogni's avatar arthursonzogni Committed by Commit Bot

Test and fix about:srcdoc inheritance.

Make about:srcdoc to inherit CSP from its parent.

Bug: 1001982
Change-Id: I5e750a8d821e6a8e8cc81e6c8a0feeb7583de020
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1789541Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarCamille Lamy <clamy@chromium.org>
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#698438}
parent b7a13cd1
...@@ -2542,4 +2542,114 @@ IN_PROC_BROWSER_TEST_P(NavigationBaseBrowserTest, ...@@ -2542,4 +2542,114 @@ IN_PROC_BROWSER_TEST_P(NavigationBaseBrowserTest,
// been invalidated. At some point, |url_b| should be displayed, not |url_c|. // been invalidated. At some point, |url_b| should be displayed, not |url_c|.
} }
// Regression test for https://crbug.com/1001283
// 1) Load main document with CSP: script-src 'none'
// 2) Open an about:srcdoc iframe. It inherits the CSP.
// 3) The iframe navigates elsewhere.
// 4) The iframe navigates back to about:srcdoc.
// Check Javascript is never allowed.
IN_PROC_BROWSER_TEST_P(NavigationBaseBrowserTest,
SrcDocCSPInheritedAfterSameSiteHistoryNavigation) {
using Response = net::test_server::ControllableHttpResponse;
Response main_document_response(embedded_test_server(), "/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a = embedded_test_server()->GetURL("a.com", "/main_document");
GURL url_b = embedded_test_server()->GetURL("a.com", "/title1.html");
auto console_delegate_1 = std::make_unique<ConsoleObserverDelegate>(
shell()->web_contents(), "Refused to execute inline script *");
shell()->web_contents()->SetDelegate(console_delegate_1.get());
// 1) Load main document with CSP: script-src 'none'
// 2) Open an about:srcdoc iframe. It inherits the CSP from its parent.
shell()->LoadURL(url_a);
main_document_response.WaitForRequest();
main_document_response.Send(
"HTTP/1.1 200 OK\n"
"content-type: text/html; charset=UTF-8\n"
"Content-Security-Policy: script-src 'none'\n"
"\n"
"<iframe name='theiframe' srcdoc='"
" <script>"
" console.error(\"CSP failure\");"
" </script>"
"'>"
"</iframe>");
main_document_response.Done();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// Check Javascript was blocked the first time.
console_delegate_1->Wait();
// 3) The iframe navigates elsewhere.
shell()->LoadURLForFrame(url_b, "theiframe",
ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
auto console_delegate_2 = std::make_unique<ConsoleObserverDelegate>(
shell()->web_contents(), "Refused to execute inline script *");
shell()->web_contents()->SetDelegate(console_delegate_2.get());
// 4) The iframe navigates back to about:srcdoc.
shell()->web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// Check Javascript was blocked the second time.
console_delegate_2->Wait();
}
IN_PROC_BROWSER_TEST_P(NavigationBaseBrowserTest,
SrcDocCSPInheritedAfterCrossSiteHistoryNavigation) {
using Response = net::test_server::ControllableHttpResponse;
Response main_document_response(embedded_test_server(), "/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a = embedded_test_server()->GetURL("a.com", "/main_document");
GURL url_b = embedded_test_server()->GetURL("b.com", "/title1.html");
auto console_delegate_1 = std::make_unique<ConsoleObserverDelegate>(
shell()->web_contents(), "Refused to execute inline script *");
shell()->web_contents()->SetDelegate(console_delegate_1.get());
// 1) Load main document with CSP: script-src 'none'
// 2) Open an about:srcdoc iframe. It inherits the CSP from its parent.
shell()->LoadURL(url_a);
main_document_response.WaitForRequest();
main_document_response.Send(
"HTTP/1.1 200 OK\n"
"content-type: text/html; charset=UTF-8\n"
"Content-Security-Policy: script-src 'none'\n"
"\n"
"<iframe name='theiframe' srcdoc='"
" <script>"
" console.error(\"CSP failure\");"
" </script>"
"'>"
"</iframe>");
main_document_response.Done();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// Check Javascript was blocked the first time.
console_delegate_1->Wait();
// 3) The iframe navigates elsewhere.
shell()->LoadURLForFrame(url_b, "theiframe",
ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
auto console_delegate_2 = std::make_unique<ConsoleObserverDelegate>(
shell()->web_contents(), "Refused to execute inline script *");
shell()->web_contents()->SetDelegate(console_delegate_2.get());
// 4) The iframe navigates back to about:srcdoc.
shell()->web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// Check Javascript was blocked the second time.
console_delegate_2->Wait();
}
} // namespace content } // namespace content
...@@ -735,7 +735,10 @@ class Document::SecurityContextInit : public FeaturePolicyParserDelegate { ...@@ -735,7 +735,10 @@ class Document::SecurityContextInit : public FeaturePolicyParserDelegate {
// We should inherit the navigation initiator CSP if the document is loaded // We should inherit the navigation initiator CSP if the document is loaded
// using a local-scheme url. // using a local-scheme url.
if (last_origin_document_csp && //
// Note: about:srcdoc inherits CSP from its parent, not from its initiator.
// In this case, the initializer.GetContentSecurityPolicy() is used.
if (last_origin_document_csp && !url.IsAboutSrcdocURL() &&
(url.IsEmpty() || url.ProtocolIsAbout() || url.ProtocolIsData() || (url.IsEmpty() || url.ProtocolIsAbout() || url.ProtocolIsData() ||
url.ProtocolIs("blob") || url.ProtocolIs("filesystem"))) { url.ProtocolIs("blob") || url.ProtocolIs("filesystem"))) {
csp_->CopyStateFrom(last_origin_document_csp); csp_->CopyStateFrom(last_origin_document_csp);
......
...@@ -213,7 +213,16 @@ DocumentLoader::DocumentLoader( ...@@ -213,7 +213,16 @@ DocumentLoader::DocumentLoader(
!params_->is_static_data && WillLoadUrlAsEmpty(url_); !params_->is_static_data && WillLoadUrlAsEmpty(url_);
loading_srcdoc_ = url_.IsAboutSrcdocURL(); loading_srcdoc_ = url_.IsAboutSrcdocURL();
if (!loading_url_as_empty_document_) { if (loading_srcdoc_) {
// about:srcdoc always inherits CSP from its parent.
ContentSecurityPolicy* parent_csp = frame_->Tree()
.Parent()
->GetSecurityContext()
->GetContentSecurityPolicy();
content_security_policy_ = MakeGarbageCollected<ContentSecurityPolicy>();
content_security_policy_->CopyStateFrom(parent_csp);
content_security_policy_->CopyPluginTypesFrom(parent_csp);
} else if (!loading_url_as_empty_document_) {
content_security_policy_ = content_security_policy_ =
CreateCSP(params_->response.ToResourceResponse(), origin_policy_); CreateCSP(params_->response.ToResourceResponse(), origin_policy_);
if (!content_security_policy_) { if (!content_security_policy_) {
......
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