summaryrefslogtreecommitdiff
path: root/chromium/content/browser/security_exploit_browsertest.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/content/browser/security_exploit_browsertest.cc
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/security_exploit_browsertest.cc')
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc305
1 files changed, 115 insertions, 190 deletions
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index fe9275c119c..baf30825dbd 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -12,7 +12,6 @@
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
@@ -25,7 +24,9 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/file_chooser_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/frame.mojom-test-utils.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_messages.h"
#include "content/common/render_message_filter.mojom.h"
@@ -56,7 +57,6 @@
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/did_commit_navigation_interceptor.h"
#include "content/test/frame_host_interceptor.h"
-#include "content/test/mock_widget_impl.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_security_test_util.h"
@@ -73,7 +73,6 @@
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/url_request/url_request_slow_download_job.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
@@ -89,6 +88,7 @@
#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-test-utils.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
using IPC::IpcSecurityTestUtil;
using ::testing::HasSubstr;
@@ -138,7 +138,7 @@ RenderFrameHostImpl* PrepareToDuplicateHosts(Shell* shell,
// Now, simulate a link click coming from the renderer.
GURL extension_url("http://bar.com/simple_page.html");
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
- wc->GetFrameTree()->root()->navigator()->RequestOpenURL(
+ wc->GetFrameTree()->root()->navigator().RequestOpenURL(
wc->GetFrameTree()->root()->current_frame_host(), extension_url,
GlobalFrameRoutingId() /* initiator_routing_id */,
url::Origin::Create(foo), nullptr, std::string(), Referrer(),
@@ -159,6 +159,15 @@ RenderFrameHostImpl* PrepareToDuplicateHosts(Shell* shell,
return next_rfh;
}
+content::mojom::OpenURLParamsPtr CreateOpenURLParams(const GURL& url) {
+ auto params = mojom::OpenURLParams::New();
+ params->url = url;
+ params->disposition = WindowOpenDisposition::CURRENT_TAB;
+ params->should_replace_current_entry = false;
+ params->user_gesture = true;
+ return params;
+}
+
std::unique_ptr<content::BlobHandle> CreateMemoryBackedBlob(
BrowserContext* browser_context,
const std::string& contents,
@@ -283,10 +292,6 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
// Complete the manual Start() after ContentBrowserTest's own
// initialization, ref. comment on InitializeAndListen() above.
embedded_test_server()->StartAcceptingConnections();
-
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
}
protected:
@@ -313,12 +318,12 @@ void SecurityExploitBrowserTest::TestFileChooserWithPath(
params->default_file_name = path;
mojo::test::BadMessageObserver bad_message_observer;
- mojo::Remote<blink::mojom::FileChooser> factory =
- static_cast<RenderFrameHostImpl*>(compromised_renderer)
- ->BindFileChooserForTesting();
- factory->OpenFileChooser(
+ mojo::Remote<blink::mojom::FileChooser> chooser =
+ FileChooserImpl::CreateBoundForTesting(
+ static_cast<RenderFrameHostImpl*>(compromised_renderer));
+ chooser->OpenFileChooser(
std::move(params), blink::mojom::FileChooser::OpenFileChooserCallback());
- factory.FlushForTesting();
+ chooser.FlushForTesting();
EXPECT_THAT(bad_message_observer.WaitForBadMessage(),
::testing::StartsWith("FileChooser: The default file name"));
}
@@ -371,16 +376,11 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
shell(), embedded_test_server(), &duplicate_routing_id);
EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);
- mojo::PendingRemote<mojom::Widget> widget;
- std::unique_ptr<MockWidgetImpl> widget_impl =
- std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
-
// Since this test executes on the UI thread and hopping threads might cause
// different timing in the test, let's simulate a CreateNewWidget call coming
// from the IO thread. Use the existing window routing id to cause a
// deliberate collision.
pending_rfh->CreateNewWidget(
- std::move(widget),
mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>(),
mojo::PendingAssociatedRemote<blink::mojom::Widget>(), base::DoNothing());
@@ -412,8 +412,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, UnexpectedMethodsSequence) {
shell()->web_contents()->SetDelegate(delegate.get());
mojo::Remote<blink::mojom::FileChooser> chooser =
- static_cast<RenderFrameHostImpl*>(compromised_renderer)
- ->BindFileChooserForTesting();
+ FileChooserImpl::CreateBoundForTesting(
+ static_cast<RenderFrameHostImpl*>(compromised_renderer));
base::RunLoop run_loop1;
base::RunLoop run_loop2;
chooser->OpenFileChooser(blink::mojom::FileChooserParams::New(),
@@ -634,24 +634,18 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &file_path));
ASSERT_TRUE(base::WriteFile(file_path, file_content));
- // Simulate an IPC message asking to POST a file that the renderer shouldn't
- // have access to.
- FrameHostMsg_OpenURL_Params params;
- params.url = target_url;
- params.post_body = new network::ResourceRequestBody;
- params.post_body->AppendFileRange(file_path, 0, file_content.size(),
- base::Time());
- params.disposition = WindowOpenDisposition::CURRENT_TAB;
- params.should_replace_current_entry = true;
- params.user_gesture = true;
-
- FrameHostMsg_OpenURL msg(root->current_frame_host()->routing_id(), params);
- IPC::IpcSecurityTestUtil::PwnMessageReceived(
- root->current_frame_host()->GetProcess()->GetChannel(), msg);
+ // Simulate an OpenURL Mojo method asking to POST a file that the renderer
+ // shouldn't have access to.
+ auto params = CreateOpenURLParams(target_url);
+ params->post_body = new network::ResourceRequestBody;
+ params->post_body->AppendFileRange(file_path, 0, file_content.size(),
+ base::Time());
+ params->should_replace_current_entry = true;
+
+ root->current_frame_host()->OpenURL(std::move(params));
// Verify that the malicious navigation did not commit the navigation to
// |target_url|.
- WaitForLoadStop(shell()->web_contents());
EXPECT_EQ(start_url, root->current_frame_host()->GetLastCommittedURL());
// Verify that the malicious renderer got killed.
@@ -707,6 +701,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PageStateToWrongEntry) {
params->method = "GET";
params->page_state = PageState::CreateFromURL(GURL("data:text/html,foo"));
params->origin = url::Origin::Create(GURL("about:blank"));
+ params->embedding_token = base::UnguessableToken::Create();
mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
isolated_interface_provider;
@@ -873,30 +868,21 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
// Simulate an IPC message where the top frame asks the remote subframe to
// navigate to a file: URL.
- GURL file_url("file:///");
- FrameHostMsg_OpenURL_Params params;
- params.url = file_url;
- params.disposition = WindowOpenDisposition::CURRENT_TAB;
- params.should_replace_current_entry = false;
- params.user_gesture = true;
-
SiteInstance* a_com_instance = root->current_frame_host()->GetSiteInstance();
RenderFrameProxyHost* proxy =
child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
EXPECT_TRUE(proxy);
- {
- FrameHostMsg_OpenURL msg(proxy->GetRoutingID(), params);
- IPC::IpcSecurityTestUtil::PwnMessageReceived(
- proxy->GetProcess()->GetChannel(), msg);
- }
+ TestNavigationObserver observer(shell()->web_contents());
+ proxy->frame_tree_node()->current_frame_host()->OpenURL(
+ CreateOpenURLParams(GURL("file:///")));
+ observer.Wait();
// Verify that the malicious navigation was blocked. Currently, this happens
// by rewriting the target URL to about:blank#blocked.
//
// TODO(alexmos): Consider killing the renderer process in this case, since
// this security check is already enforced in the renderer process.
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(GURL(kBlockedURL),
child->current_frame_host()->GetLastCommittedURL());
@@ -907,82 +893,51 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
proxy = child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
EXPECT_TRUE(proxy);
+ TestNavigationObserver observer_2(shell()->web_contents());
GURL chrome_url(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
- params.url = chrome_url;
- {
- FrameHostMsg_OpenURL msg(proxy->GetRoutingID(), params);
- IPC::IpcSecurityTestUtil::PwnMessageReceived(
- proxy->GetProcess()->GetChannel(), msg);
- }
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ proxy->frame_tree_node()->current_frame_host()->OpenURL(
+ CreateOpenURLParams(chrome_url));
+ observer_2.Wait();
EXPECT_EQ(GURL(kBlockedURL),
child->current_frame_host()->GetLastCommittedURL());
}
-class PostMessageIpcInterceptor : public BrowserMessageFilter {
+class RouteMessageEventInterceptor
+ : public blink::mojom::RemoteFrameHostInterceptorForTesting {
public:
- // Starts listening for IPC messages to |process|, intercepting
- // FrameHostMsg_RouteMessageEvent and storing once it comes.
- explicit PostMessageIpcInterceptor(RenderProcessHost* process)
- : BrowserMessageFilter(FrameMsgStart) {
- process->AddFilter(this);
+ explicit RouteMessageEventInterceptor(
+ RenderFrameProxyHost* render_frame_proxy_host,
+ const base::string16& evil_origin)
+ : render_frame_proxy_host_(render_frame_proxy_host),
+ evil_origin_(evil_origin) {
+ render_frame_proxy_host_->frame_host_receiver_for_testing()
+ .SwapImplForTesting(this);
}
- // Waits for FrameMsg_PostMessage_Params (if it didn't come yet) and returns
- // message payload to the caller.
- void WaitForMessage(int32_t* out_routing_id,
- FrameMsg_PostMessage_Params* out_params) {
- run_loop_.Run();
- *out_routing_id = intercepted_routing_id_;
- *out_params = intercepted_params_;
+ RemoteFrameHost* GetForwardingInterface() override {
+ return render_frame_proxy_host_;
}
- private:
- ~PostMessageIpcInterceptor() override = default;
-
- void OnRouteMessageEvent(const FrameMsg_PostMessage_Params& params) {
- intercepted_params_ = params;
-
- // UaF would have happened without the call below - the call ensures that
- // the data is still valid even once the original message is destroyed.
- intercepted_params_.message->data.EnsureDataIsOwned();
+ void RouteMessageEvent(
+ const base::Optional<base::UnguessableToken>& source_frame_token,
+ const base::string16& source_origin,
+ const base::string16& target_origin,
+ blink::TransferableMessage message) override {
+ // Forward the message to the actual RFPH replacing |source_origin| with the
+ // "evil origin" as especified in SetEvilSourceOriginAndWaitForMessage().
+ GetForwardingInterface()->RouteMessageEvent(
+ std::move(source_frame_token), std::move(evil_origin_),
+ std::move(target_origin), std::move(message));
}
- bool OnMessageReceived(const IPC::Message& message) override {
- // Only intercept one message.
- if (already_intercepted_)
- return false;
-
- // See if we got FrameHostMsg_RouteMessageEvent and if so unpack and store
- // its payload in OnRouteMessageEvent.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PostMessageIpcInterceptor, message)
- IPC_MESSAGE_HANDLER(FrameHostMsg_RouteMessageEvent, OnRouteMessageEvent)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- // If we got FrameHostMsg_RouteMessageEvent, then also store the routing ID
- // and signal to the main test thread that it can stop waiting.
- if (handled) {
- already_intercepted_ = true;
- intercepted_routing_id_ = message.routing_id();
- run_loop_.Quit();
- }
-
- return handled;
- }
-
- bool already_intercepted_ = false;
- int32_t intercepted_routing_id_;
- FrameMsg_PostMessage_Params intercepted_params_;
- base::RunLoop run_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(PostMessageIpcInterceptor);
+ private:
+ RenderFrameProxyHost* render_frame_proxy_host_;
+ base::string16 evil_origin_;
};
-// Test verifying that a compromised renderer can't lie about
-// FrameMsg_PostMessage_Params::source_origin. See also
+// Test verifying that a compromised renderer can't lie about the source_origin
+// passed along with the RouteMessageEvent() mojo message. See also
// https://crbug.com/915721.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PostMessageSourceOrigin) {
// Explicitly isolating a.com helps ensure that this test is applicable on
@@ -1000,91 +955,65 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PostMessageSourceOrigin) {
RenderFrameHost* subframe = web_contents->GetAllFrames()[1];
EXPECT_NE(main_frame->GetProcess(), subframe->GetProcess());
- // Prepare to intercept FrameHostMsg_RouteMessageEvent IPC message that will
- // come from the subframe process.
- RenderProcessHost* subframe_process = subframe->GetProcess();
- auto ipc_interceptor =
- base::MakeRefCounted<PostMessageIpcInterceptor>(subframe_process);
-
- // Post a message from the subframe to the cross-site parent and intercept the
- // associated IPC message.
- EXPECT_TRUE(ExecJs(subframe, "parent.postMessage('blah', '*')"));
- int intercepted_routing_id;
- FrameMsg_PostMessage_Params intercepted_params;
- ipc_interceptor->WaitForMessage(&intercepted_routing_id, &intercepted_params);
-
- // Change the intercepted message to simulate a compromised subframe renderer
- // lying that the |source_origin| of the postMessage is the origin of the
- // parent (not of the subframe).
+ // We need to get ahold of the RenderFrameProxyHost representing the main
+ // frame for the subframe's process, to install the mojo interceptor.
+ FrameTreeNode* main_frame_node =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* subframe_node = main_frame_node->child_at(0);
+ SiteInstance* b_com_instance =
+ subframe_node->current_frame_host()->GetSiteInstance();
+ RenderFrameProxyHost* main_frame_proxy_host =
+ main_frame_node->render_manager()->GetRenderFrameProxyHost(
+ b_com_instance);
+
+ // Prepare to intercept the RouteMessageEvent IPC message that will come
+ // from the subframe process.
url::Origin invalid_origin =
web_contents->GetMainFrame()->GetLastCommittedOrigin();
- FrameMsg_PostMessage_Params evil_params = intercepted_params;
- evil_params.source_origin = base::UTF8ToUTF16(invalid_origin.Serialize());
- FrameHostMsg_RouteMessageEvent evil_msg(intercepted_routing_id, evil_params);
+ base::string16 evil_source_origin =
+ base::UTF8ToUTF16(invalid_origin.Serialize());
+ RouteMessageEventInterceptor mojo_interceptor(main_frame_proxy_host,
+ evil_source_origin);
- // Inject the invalid IPC and verify that the renderer gets terminated.
- RenderProcessHostBadIpcMessageWaiter kill_waiter(subframe_process);
- IpcSecurityTestUtil::PwnMessageReceived(subframe_process->GetChannel(),
- evil_msg);
+ // Post a message from the subframe to the cross-site parent and intercept the
+ // associated IPC message, changing it to simulate a compromised subframe
+ // renderer lying that the |source_origin| of the postMessage is the origin of
+ // the parent (not of the subframe).
+ RenderProcessHostBadIpcMessageWaiter kill_waiter(subframe->GetProcess());
+ EXPECT_TRUE(ExecJs(subframe, "parent.postMessage('blah', '*')"));
EXPECT_EQ(bad_message::RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN,
kill_waiter.Wait());
}
-class OpenUrlIpcInterceptor : public BrowserMessageFilter {
+// Intercepts calls to RenderFramHost's OpenURL mojo method, and
+// store the passed parameter.
+class OpenURLInterceptor : public mojom::FrameHostInterceptorForTesting {
public:
- // Starts listening for IPC messages to |process|, intercepting
- // FrameHostMsg_OpenURL IPC message and storing once it comes.
- explicit OpenUrlIpcInterceptor(RenderProcessHost* process)
- : BrowserMessageFilter(FrameMsgStart) {
- process->AddFilter(this);
- }
-
- // Waits for FrameHostMsg_OpenURL (if it didn't come yet) and returns
- // message payload to the caller.
- void WaitForMessage(int32_t* out_routing_id,
- FrameHostMsg_OpenURL_Params* out_params) {
- run_loop_.Run();
- *out_routing_id = intercepted_routing_id_;
- *out_params = intercepted_params_;
- }
+ explicit OpenURLInterceptor(RenderFrameHostImpl* render_frame_host)
+ : render_frame_host_(render_frame_host),
+ intercepted_params_(mojom::OpenURLParams::New()) {}
- private:
- ~OpenUrlIpcInterceptor() override = default;
+ ~OpenURLInterceptor() override = default;
- void OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
- intercepted_params_ = params;
+ mojom::FrameHost* GetForwardingInterface() override {
+ return render_frame_host_;
}
- bool OnMessageReceived(const IPC::Message& message) override {
- // Only intercept one message.
- if (already_intercepted_)
- return false;
-
- // See if we got FrameHostMsg_RouteMessageEvent and if so unpack and store
- // its payload in OnRouteMessageEvent.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(OpenUrlIpcInterceptor, message)
- IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- // If we got FrameHostMsg_RouteMessageEvent, then also store the routing ID
- // and signal to the main test thread that it can stop waiting.
- if (handled) {
- already_intercepted_ = true;
- intercepted_routing_id_ = message.routing_id();
- run_loop_.Quit();
- }
+ void OpenURL(mojom::OpenURLParamsPtr params) override {
+ intercepted_params_ = std::move(params);
+ }
- return handled;
+ mojom::OpenURLParamsPtr GetInterceptedParams() {
+ return std::move(intercepted_params_);
}
- bool already_intercepted_ = false;
- int32_t intercepted_routing_id_;
- FrameHostMsg_OpenURL_Params intercepted_params_;
- base::RunLoop run_loop_;
+ private:
+ RenderFrameHostImpl* render_frame_host_;
+ mojom::OpenURLParamsPtr intercepted_params_;
- DISALLOW_COPY_AND_ASSIGN(OpenUrlIpcInterceptor);
+ DISALLOW_COPY_AND_ASSIGN(OpenURLInterceptor);
};
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
@@ -1105,28 +1034,24 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
RenderProcessHost* subframe_process = subframe->GetProcess();
EXPECT_NE(main_process->GetID(), subframe_process->GetID());
- // Prepare to intercept FrameHostMsg_OpenURL IPC message that will come from
- // the main frame process.
- auto ipc_interceptor =
- base::MakeRefCounted<OpenUrlIpcInterceptor>(main_process);
+ // Prepare to intercept OpenURL Mojo message that will come from
+ // the main frame.
+ OpenURLInterceptor interceptor(static_cast<RenderFrameHostImpl*>(main_frame));
// Have the main frame request navigation in the "remote" subframe. This will
- // result in FrameHostMsg_OpenURL IPC being sent to the RenderFrameProxyHost.
+ // result in OpenURL Mojo message being sent to the RenderFrameProxyHost.
EXPECT_TRUE(ExecJs(shell()->web_contents()->GetMainFrame(),
"window.frames[0].location = '/title1.html';"));
- int intercepted_routing_id;
- FrameHostMsg_OpenURL_Params intercepted_params;
- ipc_interceptor->WaitForMessage(&intercepted_routing_id, &intercepted_params);
// Change the intercepted message to simulate a compromised subframe renderer
// lying that the |initiator_origin| is the origin of the |subframe|.
- FrameHostMsg_OpenURL_Params evil_params = intercepted_params;
- evil_params.initiator_origin = subframe->GetLastCommittedOrigin();
- FrameHostMsg_OpenURL evil_msg(intercepted_routing_id, evil_params);
+ auto evil_params = interceptor.GetInterceptedParams();
+ evil_params->initiator_origin = subframe->GetLastCommittedOrigin();
// Inject the invalid IPC and verify that the renderer gets terminated.
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);
- IpcSecurityTestUtil::PwnMessageReceived(main_process->GetChannel(), evil_msg);
+ static_cast<RenderFrameHostImpl*>(main_frame)
+ ->OpenURL(std::move(evil_params));
EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait());
}