diff --git a/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job.cc b/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job.cc index 704b266b9cf8b..65c80a78793d6 100644 --- a/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job.cc +++ b/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job.cc @@ -837,6 +837,18 @@ void ManifestToWebAppInstallInfoJob::ParseManifestAndPopulateInfo() { GURL inferred_scope = install_info().scope.is_valid() ? install_info().scope : install_info().start_url().GetWithoutFilename(); + + // SECURITY: share_target.action arrives from the renderer with no + // browser-side validation (manifest_manager_host.cc does not check it, and + // ToWebAppShareTarget copies it directly). On ChromeOS this URL is later + // navigated to with a POST body containing user-shared data. A compromised + // renderer could supply a cross-origin action to exfiltrate that data. + // Gate it on IsInScope() exactly like lock_screen and note_taking below. + if (install_info().share_target.has_value() && + !IsInScope(install_info().share_target->action, inferred_scope)) { + install_info().share_target = std::nullopt; + } + if (base::FeatureList::IsEnabled( blink::features::kWebAppManifestLockScreen) && manifest_->lock_screen && manifest_->lock_screen->start_url.is_valid() &&