CVE-2026-2320
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
IN_PROC_BROWSER_TEST_Fcontent/browser/security_exploit_browsertest.cc |
modified | |
ifcontent/browser/web_contents/file_chooser_impl.cc |
modified | |
forcontent/browser/web_contents/file_chooser_impl.cc |
modified | |
TEST_Fcontent/browser/web_contents/file_chooser_impl_unittest.cc |
modified |
Files Changed
content/browser/security_exploit_browsertest.cccontent/browser/web_contents/file_chooser_impl.cccontent/browser/web_contents/file_chooser_impl_browsertest.cccontent/browser/web_contents/file_chooser_impl_unittest.cc
Patch
From b709f9933538dc78cfd681bab3e09a1bc5357b20 Mon Sep 17 00:00:00 2001
From: Ming-Ying Chung <mych@chromium.org>
Date: Wed, 07 Jan 2026 00:14:27 -0800
Subject: [PATCH] [FileChooser] Block `FileChooserParams::Mode::kSave` in content
`FileChooserImpl::OpenFileChooser()` previously allowed `Mode::kSave`,
which permitted the renderer to specify a default_file_name. If the
user accepted the dialog, the renderer would be granted read/write
access to the chosen file. A compromised renderer could exploit this
by prefilling a sensitive filename and tricking the user into granting
access.
`Mode::kSave` was primarily used by the legacy PPAPI and is not used
anymore in [Blink][1]. Instead, the File System Access API handles
save pickers in the browser process, bypassing this
`blink::mojom::FileChooser` interface.
This CL explicitly blocks `Mode::kSave` and reports a bad message in
`FileChooserImpl::OpenFileChooser()` if a renderer attempts to use it.
It also removes the corresponding permission grant logic in
`FileChooserImpl::FileSelected()` and adds a safety check.
Related CL: https://crrev.com/c/6786387
[1]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/forms/file_input_type.cc;l=210-215;drc=56535b80c32d3a618b8fc8cfd7b1afdd3862e1b2
Bug: 435684924
Change-Id: Ic696d0e7f01d1ddda1e5630c6bcb9ba889ce33ed
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7400881
Commit-Queue: Ming-Ying Chung <mych@chromium.org>
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1565463}
---
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index eb0d950..5d81875 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -389,6 +389,30 @@
#endif
}
+// Ensure that we kill the renderer process if it tries to open a file chooser
+// with Mode::kSave, which is not allowed for renderer-initiated choosers.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, FileChooserWithSaveMode) {
+ GURL foo("http://foo.com/simple_page.html");
+ EXPECT_TRUE(NavigateToURL(shell(), foo));
+
+ RenderFrameHost* compromised_renderer =
+ shell()->web_contents()->GetPrimaryMainFrame();
+ blink::mojom::FileChooserParamsPtr params =
+ blink::mojom::FileChooserParams::New();
+ params->mode = blink::mojom::FileChooserParams::Mode::kSave;
+ params->default_file_name = base::FilePath(FILE_PATH_LITERAL("file.txt"));
+
+ mojo::test::BadMessageObserver bad_message_observer;
+ mojo::Remote<blink::mojom::FileChooser> chooser =
+ FileChooserImpl::CreateBoundForTesting(
+ static_cast<RenderFrameHostImpl*>(compromised_renderer));
+ chooser->OpenFileChooser(
+ std::move(params), blink::mojom::FileChooser::OpenFileChooserCallback());
+ chooser.FlushForTesting();
+ EXPECT_EQ("FileChooser: Save mode is not allowed.",
+ bad_message_observer.WaitForBadMessage());
+}
+
// A test for crbug.com/941008.
// Calling OpenFileChooser() and EnumerateChosenDirectory() for a single
// FileChooser instance had a problem.
diff --git a/content/browser/web_contents/file_chooser_impl.cc b/content/browser/web_contents/file_chooser_impl.cc
index 40e2ea6f..45e3a89 100644
--- a/content/browser/web_contents/file_chooser_impl.cc
+++ b/content/browser/web_contents/file_chooser_impl.cc
@@ -171,11 +171,21 @@
return;
}
+ // Do not allow save mode from the renderer process.
+ // Save mode was primarily used by PPAPI and is not used anymore in Blink,
+ // i.e. `blink::FileInputType::OpenPopupView()`.
+ // The File System Access API handles save pickers in the browser process,
+ // bypassing this Mojo interface.
+ // See https://crbug.com/435684924 for context.
+ if (params->mode == blink::mojom::FileChooserParams::Mode::kSave) {
+ mojo::ReportBadMessage("FileChooser: Save mode is not allowed.");
+ listener->FileSelectionCanceled();
+ return;
+ }
+
// Do not allow open dialogs to have renderer-controlled default_file_name.
// See https://crbug.com/433800617 for context.
- if (params->mode != blink::mojom::FileChooserParams::Mode::kSave) {
- params->default_file_name = base::FilePath();
- }
+ params->default_file_name = base::FilePath();
// Don't allow page with open FileChooser to enter BackForwardCache to avoid
// any unexpected behaviour from BackForwardCache.
@@ -214,6 +224,13 @@
const base::FilePath& base_dir,
blink::mojom::FileChooserParams::Mode mode,
std::vector<blink::mojom::FileChooserFileInfoPtr> files) {
+ if (mode == blink::mojom::FileChooserParams::Mode::kSave) {
+ // Save mode should be blocked by OpenFileChooser, but if we get here, e.g.
+ // via test, we must not process it to avoid granting read permissions to
+ // the renderer.
+ return;
+ }
+
listener_impl_ = nullptr;
if (!render_frame_host()) {
std::move(callback_).Run(nullptr);
@@ -224,11 +241,6 @@
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
// Grant the security access requested to the given files.
for (const auto& file : files) {
- if (mode == blink::mojom::FileChooserParams::Mode::kSave) {
- policy->GrantCreateReadWriteFile(pid, file->get_native_file()->file_path);
- continue;
- }
-
if (file->is_file_system()) {
if (!file_system_context) {
file_system_context =
diff --git a/content/browser/web_contents/file_chooser_impl_browsertest.cc b/content/browser/web_contents/file_chooser_impl_browsertest.cc
index d2891cf1..000b003 100644
--- a/content/browser/web_contents/file_chooser_impl_browsertest.cc
+++ b/content/browser/web_contents/file_chooser_impl_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/functional/bind.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_paths.h"
@@ -17,6 +18,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "url/gurl.h"
#include "url/url_constants.h"
@@ -271,4 +273,38 @@
EvalJs(shell(), "document.getElementById('fileinput').files[0].name;"));
}
+// Ensure that FileChooserImpl::FileSelected does not grant permissions if
+// invoked with Mode::kSave, as a defense against compromised renderers.
+// See https://crbug.com/435684924.
+IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest,
+ FileSelectedWithSaveModeDoesNotGrantPermission) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
+
+ auto* rfh = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetPrimaryMainFrame());
+ auto chooser_and_remote = FileChooserImpl::CreateForTesting(rfh);
+ auto* chooser = chooser_and_remote.first;
+
+ base::FilePath test_file;
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &test_file));
+ test_file = test_file.AppendASCII("sensitive_file.txt");
+
+ // Ensure renderer doesn't have access initially.
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ EXPECT_FALSE(policy->CanReadFile(rfh->GetProcess()->GetDeprecatedID(), test_file));
+
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files;
+ files.emplace_back(blink::mojom::FileChooserFileInfo::NewNativeFile(
+ blink::mojom::NativeFileInfo::New(test_file, std::u16string(),
+ std::vector<std::u16string>())));
+
+ // Call FileSelected with kSave.
+ chooser->FileSelected(base::FilePath(),
+ blink::mojom::FileChooserParams::Mode::kSave,
+ std::move(files));
+
+ // Verify renderer STILL doesn't have access.
+ EXPECT_FALSE(policy->CanReadFile(rfh->GetProcess()->GetDeprecatedID(), test_file));
+}
+
} // namespace content
diff --git a/content/browser/web_contents/file_chooser_impl_unittest.cc b/content/browser/web_contents/file_chooser_impl_unittest.cc
index 54d7dea..72e63b9 100644
--- a/content/browser/web_contents/file_chooser_impl_unittest.cc
+++ b/content/browser/web_contents/file_chooser_impl_unittest.cc
@@ -9,6 +9,7 @@
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/test/test_web_contents.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -85,37 +86,24 @@
EXPECT_EQ(captured_params->default_file_name, base::FilePath());
}
-TEST_F(FileChooserImplTest, DefaultFileNamePreservedWhenModeIsSave) {
Regression Test / PoC
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index eb0d950..5d81875 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -389,6 +389,30 @@
#endif
}
+// Ensure that we kill the renderer process if it tries to open a file chooser
+// with Mode::kSave, which is not allowed for renderer-initiated choosers.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, FileChooserWithSaveMode) {
+ GURL foo("http://foo.com/simple_page.html");
+ EXPECT_TRUE(NavigateToURL(shell(), foo));
+
+ RenderFrameHost* compromised_renderer =
+ shell()->web_contents()->GetPrimaryMainFrame();
+ blink::mojom::FileChooserParamsPtr params =
+ blink::mojom::FileChooserParams::New();
+ params->mode = blink::mojom::FileChooserParams::Mode::kSave;
+ params->default_file_name = base::FilePath(FILE_PATH_LITERAL("file.txt"));
+
+ mojo::test::BadMessageObserver bad_message_observer;
+ mojo::Remote<blink::mojom::FileChooser> chooser =
+ FileChooserImpl::CreateBoundForTesting(
+ static_cast<RenderFrameHostImpl*>(compromised_renderer));
+ chooser->OpenFileChooser(
+ std::move(params), blink::mojom::FileChooser::OpenFileChooserCallback());
+ chooser.FlushForTesting();
+ EXPECT_EQ("FileChooser: Save mode is not allowed.",
+ bad_message_observer.WaitForBadMessage());
+}
+
// A test for crbug.com/941008.
// Calling OpenFileChooser() and EnumerateChosenDirectory() for a single
// FileChooser instance had a problem.
diff --git a/content/browser/web_contents/file_chooser_impl_browsertest.cc b/content/browser/web_contents/file_chooser_impl_browsertest.cc
index d2891cf1..000b003 100644
--- a/content/browser/web_contents/file_chooser_impl_browsertest.cc
+++ b/content/browser/web_contents/file_chooser_impl_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/functional/bind.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_paths.h"
@@ -17,6 +18,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "url/gurl.h"
#include "url/url_constants.h"
@@ -271,4 +273,38 @@
EvalJs(shell(), "document.getElementById('fileinput').files[0].name;"));
}
+// Ensure that FileChooserImpl::FileSelected does not grant permissions if
+// invoked with Mode::kSave, as a defense against compromised renderers.
+// See https://crbug.com/435684924.
+IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest,
+ FileSelectedWithSaveModeDoesNotGrantPermission) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
+
+ auto* rfh = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetPrimaryMainFrame());
+ auto chooser_and_remote = FileChooserImpl::CreateForTesting(rfh);
+ auto* chooser = chooser_and_remote.first;
+
+ base::FilePath test_file;
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &test_file));
+ test_file = test_file.AppendASCII("sensitive_file.txt");
+
+ // Ensure renderer doesn't have access initially.
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ EXPECT_FALSE(policy->CanReadFile(rfh->GetProcess()->GetDeprecatedID(), test_file));
+
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files;
+ files.emplace_back(blink::mojom::FileChooserFileInfo::NewNativeFile(
+ blink::mojom::NativeFileInfo::New(test_file, std::u16string(),
+ std::vector<std::u16string>())));
+
+ // Call FileSelected with kSave.
+ chooser->FileSelected(base::FilePath(),
+ blink::mojom::FileChooserParams::Mode::kSave,
+ std::move(files));
+
+ // Verify renderer STILL doesn't have access.
+ EXPECT_FALSE(policy->CanReadFile(rfh->GetProcess()->GetDeprecatedID(), test_file));
+}
+
} // namespace content
diff --git a/content/browser/web_contents/file_chooser_impl_unittest.cc b/content/browser/web_contents/file_chooser_impl_unittest.cc
index 54d7dea..72e63b9 100644
--- a/content/browser/web_contents/file_chooser_impl_unittest.cc
+++ b/content/browser/web_contents/file_chooser_impl_unittest.cc
@@ -9,6 +9,7 @@
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/test/test_web_contents.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -85,37 +86,24 @@
EXPECT_EQ(captured_params->default_file_name, base::FilePath());
}
-TEST_F(FileChooserImplTest, DefaultFileNamePreservedWhenModeIsSave) {
- FileChooserImpl* file_chooser_impl =
- FileChooserImpl::CreateForTesting(
- static_cast<RenderFrameHostImpl*>(main_rfh()))
- .first;
+TEST_F(FileChooserImplTest, SaveModeBlocked) {
+ auto chooser_and_remote = FileChooserImpl::CreateForTesting(
+ static_cast<RenderFrameHostImpl*>(main_rfh()));
+ // We keep the remote to send the message via mojo, which enables
+ // ReportBadMessage to work properly.
+ auto& chooser = chooser_and_remote.second;
auto params = blink::mojom::FileChooserParams::New();
params->mode = blink::mojom::FileChooserParams::Mode::kSave;
- const base::FilePath kInitialFile =
- base::FilePath(FILE_PATH_LITERAL("file.txt"));
- params->default_file_name = kInitialFile;
+ params->default_file_name = base::FilePath(FILE_PATH_LITERAL("file.txt"));
- blink::mojom::FileChooserParamsPtr captured_params;
- EXPECT_CALL(*mock_web_contents_delegate_, RunFileChooser(_, _, _))
- .WillOnce(
- [&](RenderFrameHost* rfh, scoped_refptr<FileSelectListener> listener,
- const blink::mojom::FileChooserParams& passed_params) {
- // Capture the arguments for later inspection.
- captured_params = passed_params.Clone();
+ EXPECT_CALL(*mock_web_contents_delegate_, RunFileChooser(_, _, _)).Times(0);
- // Avoid logging error on destruction in test.
- static_cast<FileChooserImpl::FileSelectListenerImpl*>(
- listener.get())
- ->SetListenerFunctionCalledTrueForTesting();
- });
-
- file_chooser_impl->OpenFileChooser(std::move(params), base::DoNothing());
-
- // Verify the default file name was preserved.
- ASSERT_TRUE(captured_params);
- EXPECT_EQ(captured_params->default_file_name, kInitialFile);
+ mojo::test::BadMessageObserver bad_message_observer;
+ chooser->OpenFileChooser(std::move(params), base::DoNothing());
+ chooser.FlushForTesting();
+ EXPECT_EQ("FileChooser: Save mode is not allowed.",
+ bad_message_observer.WaitForBadMessage());
}
} // namespace content
Original Bug Report
Security: Compromised renderer can read files through file picker dialog with kSave mode + prefilled filename
SUMMARY
A compromised renderer can use a file picker dialog with kSave mode and prefilled filename to read local files. In ideal scenarios, this occurs with minimal user interaction (holding enter) and can be used to read one or multiple files.
This is similar to issue 433800617 that I reported and fixed recently. See that issue for more context on some of the details I mention below.
VULNERABILITY DETAILS
When a user clicks a file-type input, the renderer calls FileChooser::OpenFileChooser() with a FileChooserParams::Mode to open file picker dialogs. In most cases, open file pickers are restricted by the browser from having a prefilled filename to prevent reading files without additional confirmation.
A compromised renderer can read files while bypassing the prefilled filename restrictions. When using Mode::kSave instead of Mode::kOpen, the renderer can set default_file_name which prefills the filename.
When the user clicks the “Save” button, the page gets read access to the file path. No file is created or written at the path, but we can read any current or future file at that path. When targeting a non-existent file, the attacker needs to know/predict the target filename, but this is easily predictable in many cases such as downloads.
There’s two ways an attacker can use this dialog:
- Selecting non-existent file: Even when a file does not yet exist, the renderer gets a file handle when the user clicks “Save”. After selection, when something else creates a file in the same selected location, the renderer can read the file without further user interaction. For example, a file can be created through browser downloads or external processes.
- Selecting existing file: For existing files, Windows will show an overwrite confirmation prompt. If the user accepts, the file is not actually overwritten and the renderer can read the file. This has same impacts as issue 433800617, with the only user flow differences being the overwrite confirmation prompt and the “Save” button instead of “Open” button.
Last selected directory behavior
As mentioned in issue 433800617, the file picker dialog for file-type inputs will show the last_selected_directory which may not be the target folder. If the user needs to select the target folder, this increases user interaction and prevents the happy path from occuring for the first targeted file. However, for any subsequent targeted files in the same folder, the happy path can be used.
This is less of a mitigation here compared to issue 433800617 because this attack asks users to save a file which doesn’t exist, instead of opening an existing file. Even when the user has to manually change folders, the user isn’t aware they are providing read access to any future file at that path.
For example, if an attacker wants to read future files from the downloads folder:
- In the happy path (if it’s the downloads folder): The attacker can easily read one or more future downloads with minimal interaction (holding enter).
- In the sad path (if it’s another folder): The attacker can ask the user to “Save” the file in the Downloads folder, which alllows attacker to read one future download. Any subsequent attempts can use the happy path (hold enter) to read multiple files.
Chained impact: Cross-site downloads
When chained with issue 428189828 to perform cross-site downloads, we can read the cross-site downloads with minimal user interaction (holding enter).
AFAICT, Mode::kSave was used by the PPAPI in the past and isn’t currently used by the renderer through OpenFileChooser().
Chained impact: Arbitrary local file reads
There’s a vulnerability that can be chained to achieve arbitrary local file reads, but I haven’t submitted that report yet. I’ll provide the chained PoC in comments once report is submitted.
Potential impact: File write to potentially bypass Safe Browsing + MOTW
Notably, using Mode::kSave in FileChooserImpl::FileSelected() calls CPSPI::GrantCreateReadWriteFile() which means the renderer could in theory ask the browser to write to the selected file path in the future. However, I have not found a way to do so since AFAICT the renderer needs to make writes through the browser process, and the the only way a renderer can ask the browser process to write files is through the FSA API. But if there’s a way to write to this file, and if those paths don’t use Safe Browsing or set MOTW, this would be a bypass of one or both security features.
If you, reader, know how to write to a file if we have a path from OpenFileChooser(), please comment below. :)
PROPOSED FIX
AFAICT, Mode::kSave was used by the PPAPI in the past and isn’t currently used by the renderer through FileChooser::OpenFileChooser(). Therefore, blocking Mode::kSave in FileChooser::OpenFileChooser() should fix the issue without affecting any other uses of save dialogs that don’t go through the renderer. But I’ll need to verify this once I implement the fix.
VERSION
Chrome version:
- Cross-site credentialed download: 138.0.7204.169 Stable, 140.0.7326.0 Canary
- Show kSave file picker with prefilled filename: Verified with custom build based on
aad34245b04df3c637ce7c51b5a10af879e1ac98(July 3rd)
Operating System: Windows 10
REPRODUCTION CASE
Patch to simulate compromised renderer To simulate a compromised renderer, the patch:
- Updates
third_party/blink/renderer/core/html/html_marquee_element.ccto callNotifyUserActivation()whenmarqueeElem.stop()is called in JS, to bypass user activation checks. - Updates
third_party/blink/renderer/core/html/forms/file_input_type.ccto callDownloadURL()directly and setdefault_file_namein open file picker. See patch for how to use attributes to change behavior.
Setup for PoCs:
- If self-hosting or want to edit using DevTools, optionally configure the target URL in the source code (e.g.
https://myaccount.google.com/personal-info). - If using default target (such as on hosted PoC), navigate to https://aogarantiza.com/set-cookies.php to set cookies on target.
- Apply attached patch and build Chromium.
Scenario 1a: Non-existent file (hold enter) + chained with cross-site download
Using patched browser:
- Navigate to https://alesandroortiz.com/security/chromium/download-theft-input-ksave-cr.html?mode=holdenter
- Press and hold enter.
- For happy path (shows downloads folder): Wait for attack to complete within a couple of seconds.
- For sad path (non-downloads folder case): When prompted again, select downloads folder, then click “Save” button.
Observed: Page can show save dialog with prefilled filename. When user clicks/presses “Save” for non-existent file, page gets file handle for specified path. When page performs cross-site download to the same path, page can read download.
Expected: Page cannot show save dialog with prefilled filename. When user clicks/presses “Save”, page does not get file handle for specified path. When page performs cross-site download to the same path, page cannot read download.
Scenario 1b: Non-existent file (normal dialog interaction) + chained with cross-site download
Using patched browser:
- Navigate to https://alesandroortiz.com/security/chromium/download-theft-input-ksave-cr.html
- Click anywhere. (Note: a compromised renderer can show the dialog without user interaction.)
- For happy path (shows downloads folder): Click “Save” button.
- For sad path (non-downloads folder case): Select downloads folder, then click “Save” button.
- Wait for attack to complete within a couple of seconds.
Observed/Expected: Same as Scenario 1a.
Scenario 2: Existing file (normal dialog interaction)
Note: Ignore PoC’s built-in instructions.
Using patched browser:
- Navigate to https://alesandroortiz.com/security/chromium/download-theft-input-ksave-cr.html
- Click anywhere. (Note: a compromised renderer can show the dialog without user interaction.)
- Click any existing file in the folder.
- Click “Yes” in overwrite confirmation prompt.
Observed: When user clicks “Save”, page can read existing file without further warnings.
Expected: When user clicks “Save”, page cannot read existing file without further warnings.
Credit Information
Reporter credit: Alesandro Ortiz https://AlesandroOrtiz.com
- https://AlesandroOrtiz.com
- https://alesandroortiz.com/security/chromium/download-theft-input-ksave-cr.html
- https://alesandroortiz.com/security/chromium/download-theft-input-ksave-cr.html?mode=holdenter
- https://aogarantiza.com/set-cookies.php
- https://crrev.com/c/6786387
- https://issuetracker.google.com/issues/428189828
- https://issuetracker.google.com/issues/433800617
- https://myaccount.google.com/personal-info
- https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/profiles/profile_impl.cc;l=886;drc=d32f634388f26f8c7bbb98c82fa9718d30636b1e
- https://source.chromium.org/chromium/chromium/src/+/main:content/browser/web_contents/file_chooser_impl.cc;l=227;drc=d32f634388f26f8c7bbb98c82fa9718d30636b1e
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/choosers/file_chooser.mojom;l=137;drc=ebee769e5e2e914e34b4ce20f956863d62bb7c3b
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/choosers/file_chooser.mojom;l=35;drc=ebee769e5e2e914e34b4ce20f956863d62bb7c3b
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/choosers/file_chooser.mojom;l=45;drc=ebee769e5e2e914e34b4ce20f956863d62bb7c3b