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 <liu@chromium.org>
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 <qinmin@chromium.org>
Reviewed-by: Lily Chen <chlily@chromium.org>
Commit-Queue: Andrew Liu <liu@chromium.org>
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 mu...@gmail.com
.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