Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in WebAppInstalls
DescriptionInsufficient validation of untrusted input in WebAppInstalls
ComponentWebAppInstalls
Bug ClassLogic Error
Tracker514020982
Fix commit83acaeae804d (chromium/src) +49/-5
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
for
chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job.cc
modified
TEST_F
chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
modified

Files Changed

  • chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
  • chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job.cc
  • chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
From 83acaeae804d4ad86a71a6e5e786cdd51c327951 Mon Sep 17 00:00:00 2001
From: Edman Anjos <[email protected]>
Date: Mon, 01 Jun 2026 10:56:39 -0700
Subject: [PATCH] Ignore unframed display override in install job when the flag is disabled

Fixed: 514020982
Test: testing/xvfb.py tools/autotest.py -C out_/Default chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
Change-Id: I86539fe197f2ffb7d9e4fb991190b88ad73ab90a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7867923
Reviewed-by: Eshwar Stalin <[email protected]>
Commit-Queue: Edman Anjos <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1639520}
---

diff --git a/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
index 4fbb5184..5fb9b5c 100644
--- a/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
@@ -3,10 +3,13 @@
 // found in the LICENSE file.
 
 #include <memory>
+#include <optional>
 #include <string_view>
 #include <vector>
 
+#include "base/auto_reset.h"
 #include "base/check_deref.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
@@ -32,6 +35,7 @@
 #include "components/webapps/isolated_web_apps/types/update_channel.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/safe_url_pattern.h"
 #include "third_party/liburlpattern/part.h"
 
@@ -100,6 +104,7 @@
  public:
   ManifestUpdateTest()
       : IsolatedWebAppTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
+    scoped_feature_list_.InitAndEnableFeature(blink::features::kUnframedIwa);
   }
   ~ManifestUpdateTest() override = default;
 
@@ -162,6 +167,7 @@
     ASSERT_THAT(TestIwa(), HasVersion("2.0.0"));
   }
 
+  base::test::ScopedFeatureList scoped_feature_list_;
   FakeIwaRuntimeDataProvider data_provider_;
   std::optional<base::AutoReset<ChromeIwaRuntimeDataProvider*>> resetter_;
 };
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 1e64842..5744abc0 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
@@ -813,10 +813,15 @@
     install_info().display_mode = manifest_->display;
   }
   for (const auto& override_item : manifest_->display_override) {
-    install_info().display_override.push_back(
-        override_item.display() == DisplayMode::kUnframed
-            ? DisplayOverride::CreateUnframed(override_item.url_patterns())
-            : DisplayOverride::Create(override_item.display()));
+    if (override_item.display() == DisplayMode::kUnframed) {
+      if (base::FeatureList::IsEnabled(blink::features::kUnframedIwa)) {
+        install_info().display_override.push_back(
+            DisplayOverride::CreateUnframed(override_item.url_patterns()));
+      }
+    } else {
+      install_info().display_override.push_back(
+          DisplayOverride::Create(override_item.display()));
+    }
   }
 
   const std::vector<blink::Manifest::ImageResource>& icons =
diff --git a/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc b/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
index b0c0cce..fef5eb6 100644
--- a/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
+++ b/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/feature_list.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
@@ -167,7 +168,8 @@
 TEST_F(ManifestToWebAppInstallInfoJobTest, BasicFieldsPopulated) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures({blink::features::kFileHandlingIcons,
-                                 blink::features::kWebAppManifestLockScreen},
+                                 blink::features::kWebAppManifestLockScreen,
+                                 blink::features::kUnframedIwa},
                                 /*disabled_features=*/{});
 
   SetupBasicPageState();
@@ -2213,6 +2215,37 @@
   EXPECT_EQ(default_icon_url, icons[0].url);
 }
 
+TEST_F(ManifestToWebAppInstallInfoJobTest,
+       AcceptsUnframedDisplayOverrideWhenTheFeatureIsEnabled) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(blink::features::kUnframedIwa);
+
+  ASSERT_TRUE(base::FeatureList::IsEnabled(blink::features::kUnframedIwa));
+
+  SetupBasicPageState();
+  blink::mojom::ManifestPtr& manifest = GetPageManifest();
+  manifest->display_override.push_back(
+      blink::Manifest::DisplayOverride::CreateUnframed({FooUrlPattern()}));
+
+  auto web_app_info = GetWebAppInstallInfoFromJob(*manifest);
+  EXPECT_THAT(
+      web_app_info->display_override,
+      testing::ElementsAre(DisplayOverride::CreateUnframed({FooUrlPattern()})));
+}
+
+TEST_F(ManifestToWebAppInstallInfoJobTest,
+       IgnoresUnframedDisplayOverrideWhenTheFeatureIsDisabled) {
+  ASSERT_FALSE(base::FeatureList::IsEnabled(blink::features::kUnframedIwa));
+
+  SetupBasicPageState();
+  blink::mojom::ManifestPtr& manifest = GetPageManifest();
+  manifest->display_override.push_back(
+      blink::Manifest::DisplayOverride::CreateUnframed());
+
+  auto web_app_info = GetWebAppInstallInfoFromJob(*manifest);
+  EXPECT_THAT(web_app_info->display_override, testing::IsEmpty());
+}
+
 }  // namespace
 
 }  // namespace web_app
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
index 4fbb5184..5fb9b5c 100644
--- a/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/manifest_update_unittest.cc
@@ -3,10 +3,13 @@
 // found in the LICENSE file.
 
 #include <memory>
+#include <optional>
 #include <string_view>
 #include <vector>
 
+#include "base/auto_reset.h"
 #include "base/check_deref.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
@@ -32,6 +35,7 @@
 #include "components/webapps/isolated_web_apps/types/update_channel.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/safe_url_pattern.h"
 #include "third_party/liburlpattern/part.h"
 
@@ -100,6 +104,7 @@
  public:
   ManifestUpdateTest()
       : IsolatedWebAppTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
+    scoped_feature_list_.InitAndEnableFeature(blink::features::kUnframedIwa);
   }
   ~ManifestUpdateTest() override = default;
 
@@ -162,6 +167,7 @@
     ASSERT_THAT(TestIwa(), HasVersion("2.0.0"));
   }
 
+  base::test::ScopedFeatureList scoped_feature_list_;
   FakeIwaRuntimeDataProvider data_provider_;
   std::optional<base::AutoReset<ChromeIwaRuntimeDataProvider*>> resetter_;
 };
diff --git a/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc b/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
index b0c0cce..fef5eb6 100644
--- a/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
+++ b/chrome/browser/web_applications/jobs/manifest_to_web_app_install_info_job_unittest.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/feature_list.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
@@ -167,7 +168,8 @@
 TEST_F(ManifestToWebAppInstallInfoJobTest, BasicFieldsPopulated) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures({blink::features::kFileHandlingIcons,
-                                 blink::features::kWebAppManifestLockScreen},
+                                 blink::features::kWebAppManifestLockScreen,
+                                 blink::features::kUnframedIwa},
                                 /*disabled_features=*/{});
 
   SetupBasicPageState();
@@ -2213,6 +2215,37 @@
   EXPECT_EQ(default_icon_url, icons[0].url);
 }
 
+TEST_F(ManifestToWebAppInstallInfoJobTest,
+       AcceptsUnframedDisplayOverrideWhenTheFeatureIsEnabled) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(blink::features::kUnframedIwa);
+
+  ASSERT_TRUE(base::FeatureList::IsEnabled(blink::features::kUnframedIwa));
+
+  SetupBasicPageState();
+  blink::mojom::ManifestPtr& manifest = GetPageManifest();
+  manifest->display_override.push_back(
+      blink::Manifest::DisplayOverride::CreateUnframed({FooUrlPattern()}));
+
+  auto web_app_info = GetWebAppInstallInfoFromJob(*manifest);
+  EXPECT_THAT(
+      web_app_info->display_override,
+      testing::ElementsAre(DisplayOverride::CreateUnframed({FooUrlPattern()})));
+}
+
+TEST_F(ManifestToWebAppInstallInfoJobTest,
+       IgnoresUnframedDisplayOverrideWhenTheFeatureIsDisabled) {
+  ASSERT_FALSE(base::FeatureList::IsEnabled(blink::features::kUnframedIwa));
+
+  SetupBasicPageState();
+  blink::mojom::ManifestPtr& manifest = GetPageManifest();
+  manifest->display_override.push_back(
+      blink::Manifest::DisplayOverride::CreateUnframed());
+
+  auto web_app_info = GetWebAppInstallInfoFromJob(*manifest);
+  EXPECT_THAT(web_app_info->display_override, testing::IsEmpty());
+}
+
 }  // namespace
 
 }  // namespace web_app
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.