Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactImproper state validation in Installer
DescriptionImproper state validation in Installer
ComponentInstaller
Bug ClassLogic Error
Tracker513495219
Fix commit9f4f461aaf77 (chromium/src) +17/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-09-08

Changed Functions

FunctionChangeNotes
TEST_F
chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
modified

Files Changed

  • chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
  • chrome/utility/safe_browsing/seven_zip_analyzer.cc
  • third_party/lzma_sdk/google/test_data/unsupported_coder_chain.7z
From 9f4f461aaf77809973b4f4e42de7b090ae8deb9b Mon Sep 17 00:00:00 2001
From: thefrog <thefrog@chromium.org>
Date: Fri, 31 Jul 2026 14:41:25 -0700
Subject: [PATCH] Fix 7z unpacking error incorrect reported metadata in download ping

When an unencrypted 7z archive entry failed to unpack,
SevenZipAnalyzer::EntryDone() previously incorrectly marked the archive
result as valid.

As a result, the download ping would incorrectly contain:
 - archive_summary.parser_status = "VALID"
 - download_type = "ARCHIVE"

This change updates SevenZipAnalyzer::EntryDone() so that if an
unencrypted entry fails to unpack, the archive analysis is marked as
failed.

The download ping now contains:
 - archive_summary.parser_status is not set
 - download_type = "INVALID_SEVEN_ZIP"

Reviewed in https://crrev.com/i/9620201.

Fixed: 513495219
Change-Id: I6efa84b5ec9fdfe1ca34fc1aef9de002d1ccf6f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8183009
Auto-Submit: thefrog <thefrog@chromium.org>
Commit-Queue: Yaw Frempong <yawfrempong@google.com>
Commit-Queue: thefrog <thefrog@chromium.org>
Reviewed-by: Yaw Frempong <yawfrempong@google.com>
SLSA-Policy-Verified: SLSA Policy Verification Service <devtools-gerritcodereview-exitgate@google.com>
Cr-Commit-Position: refs/heads/main@{#1672117}
---

diff --git a/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc b/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
index ad9ad97..86a2771 100644
--- a/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
+++ b/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
@@ -235,6 +235,18 @@
   EXPECT_FALSE(results.archived_binary[0].is_archive());
 }
 
+TEST_F(SandboxedSevenZipAnalyzerTest, UnsupportedCoderChainFailsAnalysis) {
+  safe_browsing::ArchiveAnalyzerResults results;
+  RunAnalyzer(
+      dir_test_data_.Append(FILE_PATH_LITERAL("unsupported_coder_chain.7z")),
+      &results);
+  EXPECT_FALSE(results.success);
+  EXPECT_EQ(ArchiveAnalysisResult::kFailedDuringIteration,
+            results.analysis_result);
+  EXPECT_FALSE(results.encryption_info.is_encrypted);
+  EXPECT_EQ(0, results.archived_binary.size());
+}
+
 TEST_F(SandboxedSevenZipAnalyzerTest, NotASevenZip) {
   safe_browsing::ArchiveAnalyzerResults results;
   RunAnalyzer(dir_test_data_.Append(FILE_PATH_LITERAL("not_a_seven_zip.7z")),
diff --git a/chrome/utility/safe_browsing/seven_zip_analyzer.cc b/chrome/utility/safe_browsing/seven_zip_analyzer.cc
index 259392e28..766668f 100644
--- a/chrome/utility/safe_browsing/seven_zip_analyzer.cc
+++ b/chrome/utility/safe_browsing/seven_zip_analyzer.cc
@@ -93,6 +93,11 @@
       awaiting_nested_ = true;
       return false;
     }
+  } else {
+    // If an unencrypted entry failed to unpack, mark the entire archive
+    // analysis as failed so we do not report it as a valid archive.
+    results()->success = false;
+    results()->analysis_result = ArchiveAnalysisResult::kFailedDuringIteration;
   }
 
   return true;
diff --git a/third_party/lzma_sdk/google/test_data/unsupported_coder_chain.7z b/third_party/lzma_sdk/google/test_data/unsupported_coder_chain.7z
new file mode 100644
index 0000000..589cbc3
--- /dev/null
+++ b/third_party/lzma_sdk/google/test_data/unsupported_coder_chain.7z
Binary files differ
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc b/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
index ad9ad97..86a2771 100644
--- a/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
+++ b/chrome/services/file_util/public/cpp/sandboxed_seven_zip_analyzer_unittest.cc
@@ -235,6 +235,18 @@
   EXPECT_FALSE(results.archived_binary[0].is_archive());
 }
 
+TEST_F(SandboxedSevenZipAnalyzerTest, UnsupportedCoderChainFailsAnalysis) {
+  safe_browsing::ArchiveAnalyzerResults results;
+  RunAnalyzer(
+      dir_test_data_.Append(FILE_PATH_LITERAL("unsupported_coder_chain.7z")),
+      &results);
+  EXPECT_FALSE(results.success);
+  EXPECT_EQ(ArchiveAnalysisResult::kFailedDuringIteration,
+            results.analysis_result);
+  EXPECT_FALSE(results.encryption_info.is_encrypted);
+  EXPECT_EQ(0, results.archived_binary.size());
+}
+
 TEST_F(SandboxedSevenZipAnalyzerTest, NotASevenZip) {
   safe_browsing::ArchiveAnalyzerResults results;
   RunAnalyzer(dir_test_data_.Append(FILE_PATH_LITERAL("not_a_seven_zip.7z")),
Loading diff…

Original Bug Report

reported by vm...@google.com

Safe Browsing bypass in 7z analysis due to ignored error and coder limit discrepancy

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A logic error in the 7z reader ignores errors during encryption detection, causing incorrect metadata reporting. Combined with a coder limit discrepancy, this allows crafted archives to bypass Safe Browsing analysis. Malicious payloads can be hidden from deep-scanning while remaining accessible to users.

Affected files:

  • third_party/lzma_sdk/google/seven_zip_reader.cc
  • chrome/utility/safe_browsing/seven_zip_analyzer.cc

Estimated timestamp from git blame: 2022-09-20

Summary

A potential vulnerability exists in Chromium’s Safe Browsing 7z archive analysis where an ignored return value in SevenZipReaderImpl::IsFolderEncrypted leads to incorrect metadata reporting. When combined with a ‘parser differential’—where the initial archive scan permits more coders than the subsequent extraction and metadata pass—an attacker can craft a 7z archive that Safe Browsing fails to correctly identify as containing encrypted or executable content. This may allow malicious payloads to bypass deep-scanning signals.

Root Cause Analysis

The issue resides in SevenZipReaderImpl::IsFolderEncrypted within third_party/lzma_sdk/google/seven_zip_reader.cc. This function calls SzGetNextFolderItem to parse a folder’s coder graph but ignores its SRes return value:

// third_party/lzma_sdk/google/seven_zip_reader.cc
CSzFolder folder;
SzGetNextFolderItem(&folder, &span);                 // <-- SRes return value IGNORED

for (size_t i = 0; i < folder.NumCoders && i < SZ_NUM_CODERS_IN_FOLDER_MAX; ++i) {
  // ...
}

In the LZMA SDK, SzGetNextFolderItem initializes f->NumCoders = 0 and only sets the actual value after all validation passes. If validation fails (e.g., returning SZ_ERROR_UNSUPPORTED), NumCoders remains 0. Consequently, the loop in IsFolderEncrypted never runs, and the function incorrectly returns false regardless of the actual folder contents.

Parser Differential

A discrepancy exists between the archive scanning pass (ReadUnpackInfo called during SzArEx_Open) and the decoding/metadata pass (SzGetNextFolderItem).

  1. The initial scanning pass in the LZMA SDK allows up to 64 coders (k_Scan_NumCoders_MAX).
  2. The decoding pass and metadata parsing used by Chrome’s reader limit this to 4 coders (SZ_NUM_CODERS_IN_FOLDER_MAX).

An archive folder utilizing 5 coders will be accepted during the initial SzArEx_Open call but will cause SzGetNextFolderItem to fail during the subsequent metadata-collection and extraction phases.

Potential Exploitation Steps

An attacker might follow these steps to potentially trigger the vulnerability:

  1. Craft a .7z file where a payload folder uses 5 coders, including an encryption method (e.g., 7zAES).
  2. When a user downloads the file, SevenZipAnalyzer initiates a scan in the sandboxed utility process.
  3. SzArEx_Open succeeds because its scanning pass allows up to 64 coders.
  4. IsFolderEncrypted is called for the payload entry. SzGetNextFolderItem fails due to the 4-coder limit and returns SZ_ERROR_UNSUPPORTED. The error is ignored, and entry.is_encrypted is incorrectly set to false (since folder.NumCoders was reset to 0).
  5. ExtractFile subsequently fails during SzAr_DecodeFolder for the same reason (the 4-coder limit), returning Result::kUnsupported.
  6. In SevenZipAnalyzer::EntryDone, the following logic is applied:
    if (result == seven_zip::Result::kSuccess || entry.is_encrypted) { ... }
    
    Since result is kUnsupported and entry.is_encrypted is false, the analyzer silently drops the entry.

The resulting Safe Browsing report sent to the backend will omit the malicious payload’s metadata (filename, size, and executable status). This suppresses potential warnings like ZIPPED_EXECUTABLE, while the malicious payload remains accessible to the user via standard desktop 7z applications that support more than 4 coders.

Impact

Successful exploitation allows malicious files to bypass Safe Browsing analysis, reducing the effectiveness of download protection. The attacker can hide executable content or encrypted payloads from the analysis infrastructure.

Suggested Fix

  1. Modify SevenZipReaderImpl::IsFolderEncrypted in third_party/lzma_sdk/google/seven_zip_reader.cc to check and handle the return value of SzGetNextFolderItem.
  2. Consider aligning the coder limits between the scanning pass and the decoding pass in the LZMA SDK integration to prevent parser differentials. Increasing SZ_NUM_CODERS_IN_FOLDER_MAX to match k_Scan_NumCoders_MAX (within safe limits) or ensuring consistent enforcement across all passes would mitigate the issue.

Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

Data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker