diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc index 0b6f3ee29e3e3..7dcda01458612 100644 --- a/content/browser/download/save_file_manager.cc +++ b/content/browser/download/save_file_manager.cc @@ -117,6 +117,13 @@ class SaveFileManager::SimpleURLLoaderHelper int render_frame_routing_id, const GURL& final_url, const network::mojom::URLResponseHead& response_head) { + // POC instrumentation: show that the redirect was followed and the + // post-redirect URL is known here, but quarantine_callback_ was already + // bound in SaveURL() with the pre-redirect URL. + LOG(ERROR) << "[POC] SimpleURLLoaderHelper::OnResponseStarted" + << " initial_url=" << url.spec() + << " final_url=" << final_url.spec() + << " (redirected=" << (url != final_url ? "yes" : "no") << ")"; std::string content_disposition; if (response_head.headers) { content_disposition = @@ -402,6 +409,15 @@ void SaveFileManager::QuarantineItem( SaveFile* save_file = LookupSaveFile(save_item_id); CHECK(save_file); + // POC instrumentation: this `url` was bound at SaveURL():235 BEFORE any + // network request, so for redirected subresources it is the PRE-redirect + // URL. On Windows it is passed to IAttachmentExecute::SetSource() and + // written as HostUrl= in the Zone.Identifier ADS. + LOG(ERROR) << "[POC][BUG] SaveFileManager::QuarantineItem" + << " quarantine_source_url=" << url.spec() + << " referrer_url=" << referrer_url.spec() + << " full_path=" << save_file->FullPath().AsUTF8Unsafe(); + save_file->AnnotateWithSourceInformation( client_guid, url, referrer_url, std::move(remote_quarantine), base::BindOnce(&SaveFileManager::OnQuarantineComplete, this, save_item_id, diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index e5a78b6c5b320..afc279c1e56fe 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -8470,6 +8470,23 @@ void WebContentsImpl::OnDidFinishLoad(RenderFrameHostImpl* render_frame_host, if (!render_frame_host->GetParentOrOuterDocument()) { UMA_HISTOGRAM_COUNTS_1000("Navigation.MainFrame.FrameCount", tree_size); } + + // POC instrumentation: automatically trigger "Save Page As, Webpage + // Complete" when the POC page finishes loading, to avoid needing manual + // Ctrl+S in a headless test environment. This simulates the user gesture + // described in the report; it does NOT bypass any security gate (user + // interaction is required for the real attack). + if (render_frame_host->IsInPrimaryMainFrame() && + validated_url.spec().find("poc.html") != std::string::npos && + !save_package_) { + base::FilePath out_dir(FILE_PATH_LITERAL("/tmp/poc-savepackage")); + LOG(ERROR) << "[POC] auto-triggering SavePage(SAVE_PAGE_TYPE_AS_COMPLETE_" + "HTML) for " + << validated_url.spec() << " -> " << out_dir.AsUTF8Unsafe(); + SavePage(out_dir.Append(FILE_PATH_LITERAL("page.html")), + out_dir.Append(FILE_PATH_LITERAL("page_files")), + content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML); + } } bool WebContentsImpl::IsAllowedToGoToEntryAtOffset(int32_t offset) {