Chrome · Downloads
CVE-2026-5887
Logic Error in Downloads
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
chrome/browser/download/download_target_determiner.ccchrome/browser/download/download_target_determiner_unittest.cc
Patch
From 8c1145d4b23d6a8cf2867b922716153f6ea72d9e Mon Sep 17 00:00:00 2001 From: Andrew Liu <[email protected]> Date: Wed, 04 Mar 2026 12:47:47 -0800 Subject: [PATCH] Filter out multiple "double percent signs" when normalizing download files Bug: 486079015 Change-Id: I7047e2f0a210de1ae17cbb95884f3a6c6a6a6964 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7629495 Reviewed-by: Min Qin <[email protected]> Reviewed-by: Lily Chen <[email protected]> Commit-Queue: Andrew Liu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1594178} --- diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index 760025c..1dd2dbab 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc @@ -599,13 +599,19 @@ // file name first. std::wstring sanitized_name = ui::RemoveEnvVarFromFileName<wchar_t>( virtual_path_.BaseName().value(), L"%"); - // remove leading "." to avoid resorting to potential extension - // bug: 41486690 - while (!sanitized_name.empty() && sanitized_name.back() == L'.') { - sanitized_name.pop_back(); + // Remove trailing "." and whitespace to avoid resorting to potential + // extensions. + // See crbug.com/41486690 and crbug.com/486079015 for more context. + while (!sanitized_name.empty()) { + size_t length = sanitized_name.length(); + while (!sanitized_name.empty() && sanitized_name.back() == L'.') { + sanitized_name.pop_back(); + } + // trim trailing whitespace (space, tab, NBSP) to prevent stale extensions + base::TrimWhitespace(sanitized_name, base::TrimPositions::TRIM_TRAILING, &sanitized_name); + if (length == sanitized_name.length()) + break; } - // trim trailing whitespace (space, tab, NBSP) to prevent stale extensions - base::TrimWhitespace(sanitized_name, base::TrimPositions::TRIM_TRAILING, &sanitized_name); if (sanitized_name.empty()) { sanitized_name = base::UTF8ToWide( l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME)); diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc index dff43fc..890c8305 100644 --- a/chrome/browser/download/download_target_determiner_unittest.cc +++ b/chrome/browser/download/download_target_determiner_unittest.cc @@ -2712,6 +2712,15 @@ FILE_PATH_LITERAL("download"), DownloadItem::TARGET_DISPOSITION_PROMPT, + EXPECT_CRDOWNLOAD}, + {// 6: Multiple env vars need to be filtered out. + SAVE_AS, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.lnk .%% .%%", + "application/octet-stream", FILE_PATH_LITERAL(""), + + FILE_PATH_LITERAL("foo.download"), + DownloadItem::TARGET_DISPOSITION_PROMPT, + EXPECT_CRDOWNLOAD}}; RunTestCasesWithActiveItem(kSaveEnvPathTestCases);
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc
index dff43fc..890c8305 100644
--- a/chrome/browser/download/download_target_determiner_unittest.cc
+++ b/chrome/browser/download/download_target_determiner_unittest.cc
@@ -2712,6 +2712,15 @@
FILE_PATH_LITERAL("download"), DownloadItem::TARGET_DISPOSITION_PROMPT,
+ EXPECT_CRDOWNLOAD},
+ {// 6: Multiple env vars need to be filtered out.
+ SAVE_AS, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.lnk .%% .%%",
+ "application/octet-stream", FILE_PATH_LITERAL(""),
+
+ FILE_PATH_LITERAL("foo.download"),
+ DownloadItem::TARGET_DISPOSITION_PROMPT,
+
EXPECT_CRDOWNLOAD}};
RunTestCasesWithActiveItem(kSaveEnvPathTestCases);
Loading diff…
Original Bug Report
reported by [email protected]
.lnk File Download Bypass Using "Save As" Link (Bypass of #444803530)
Steps to reproduce the problem
- Run poc.py, and then open http://127.0.0.1:8000/
- Right click
download mehyperlink and then chooseSave File As - Choose
Savebutton and .lnk file will be downloaded
Problem Description
This is a bypass of https://issues.chromium.org/issues/444803530, where an attacker uses a double percent sign (%%) to bypass Chrome’s dangerous file protection. Although it has already been fixed, it can still be bypassed by using a double “double percent sign,” such as: file.lnk .%% .%%
Summary
.lnk File Download Bypass Using “Save As” Link (Bypass of #444803530)
Additional Data
Category: Security
Chrome Channel: Not sure
Regression: N/A \
References
On This Page