Low watch CVSS 6.5 chrome OOB 🔧 Commit mapped

Overview

Low
Severity
6.5
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactOut of bounds read in FileSystem
DescriptionOut of bounds read in FileSystem
ComponentFileSystem
Bug ClassOOB
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker513361380
Fix commitf57f21128430 (chromium/src) +8/-4
CWECWE-125 (Out-of-bounds read)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-05-15 (per vendor advisory)
Fix landed2026-07-22 (public git)
Disclosed2026-08-25
Patch gap34 days — fix public in source before the advisory

Background

File System Access API
a web platform API that, after a user picks a file or directory, grants the page read/write handles to that location on disk.
Blocklist in `ChromeFileSystemAccessPermissionContext`
a static table of sensitive paths (BlockPath entries) that the permission context refuses to expose, so IsOpenAbort-style checks deny handles to those paths, their parents, and their children.
`base::DIR_CACHE`
the platform path key for the user cache directory (~/.cache on Linux/ChromeOS), which can hold app state whose contents or presence are security- or privacy-sensitive.
`BlockType::kBlockAllChildren`
a block mode that denies the directory itself, its parent, and everything beneath it.

Root Cause Analysis

The File System Access blocklist added base::DIR_CACHE (via BlockPath::CreateRelative) only inside the BUILDFLAG(IS_ANDROID) section, so on Linux and ChromeOS ~/.cache was not on the blocklist and web content that obtained a directory handle covering it could read (and write) user cache contents. The invariant that platform cache directories are off-limits to arbitrary web content held on Android, macOS, and Windows but not on Linux/ChromeOS, leaving a gap in the sensitive-path policy.

The fix moves the DIR_CACHE BlockPath::CreateRelative(..., BlockType::kBlockAllChildren) entry out of the Android-only block and into the shared Linux/ChromeOS/Android section (the non-IS_ANDROID #endif-guarded region alongside the ~/.dbus block), so ~/.cache and everything under it are now denied on those platforms too. The accompanying unit test change generalizes the cache-directory assertion from Android-only to IS_LINUX || IS_CHROMEOS || IS_ANDROID, confirming IsOpenAbort now aborts opens of the cache dir, its parent, and paths inside it. Note the patch is purely a blocklist scope change; the diff itself does not contain any out-of-bounds memory operation.

Key insight
The single mistake was scoping the ~/.cache (base::DIR_CACHE) blocklist entry to Android only, leaving Linux/ChromeOS unprotected; the fix relocates that entry into the shared platform section so cache access is blocked there as well.

Attack Path

  1. Lure a directory grant A malicious or misleading page uses the File System Access API to prompt the user to select a directory that resolves to or contains ~/.cache on Linux/ChromeOS.
  2. Escape the blocklist gap Because base::DIR_CACHE was only blocked under BUILDFLAG(IS_ANDROID), the permission context did not abort the open on Linux/ChromeOS, so the handle to the cache directory is granted.
  3. Read cache contents With the granted handle the page enumerates and reads files under ~/.cache, exposing cached application data whose contents or mere presence are sensitive. (inferred — the diff shows only the blocklist gap, not the specific data read)
  4. Persist or tamper Because the entry is kBlockAllChildren covering write access too, an unblocked handle could also let the page write into cache subdirectories. (inferred)

Impact Assessment

An attacker-controlled page could gain read (and potentially write) access to the user’s ~/.cache directory on Linux/ChromeOS via the File System Access API, disclosing sensitive cached data. The precondition is that the user grants a directory handle covering the cache path; the API’s own picker/permission UI is the gate. The advisory labels this an out-of-bounds read in FileSystem, but the patch demonstrates only a missing sensitive-path blocklist entry; any characterization beyond a blocklist-scope gap is per the advisory, not shown by the diff, and no exploited-in-the-wild status is stated.

Files Changed

  • chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
  • chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc

Audit Directions

  • Per-platform blocklist scoping
    Audit sensitive-path blocklists for entries fenced behind a single BUILDFLAG that should apply on more platforms, especially where the underlying path key (e.g. base::DIR_CACHE, config/state dirs) exists across OSes.
  • Cross-platform parity of sensitive dirs
    Compare the File System Access blocklist across mac/win/linux/chromeos/android and reconcile which base::DIR_* keys are protected on each.
  • Directory-handle exposure of app state
    Look for other user-writable directories (config, temp, profile subdirs) reachable via directory handles that reveal or let web content mutate application state.
From f57f211284300f47f7834a902d89e8ff493424e3 Mon Sep 17 00:00:00 2001
From: Etienne Bergeron <etienneb@google.com>
Date: Wed, 22 Jul 2026 07:47:33 -0700
Subject: [PATCH] Block base::DIR_CACHE in File System Access API on Linux/ChromeOS

Add base::DIR_CACHE (~/.cache) to the File System Access blocklist
on Linux and ChromeOS platforms in addition to Android, preventing web
content from gaining write access to user cache directories.

Also add unit tests in fontconfig_util_unittest and
chrome_file_system_access_permission_context_unittest.

Bug: 513361380
Change-Id: I085954d4cc09a126e916e2fe0053fe5c1f0fd1aa
Fixed: 513361380
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8126779
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: Antonio Sartori <antoniosartori@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1666284}
---
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
index aa7ec45..d16db9f9 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
@@ -478,11 +478,13 @@
       // a website can do with access to that directory and its contents.
       BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".dbus"),
                                 BlockType::kBlockAllChildren),
+      // And block all of ~/.cache, matching the similar restrictions on mac
+      // and windows.
+      BlockPath::CreateRelative(base::DIR_CACHE, BlockType::kBlockAllChildren),
 #endif
 #if BUILDFLAG(IS_ANDROID)
       BlockPath::CreateRelative(base::DIR_ANDROID_APP_DATA,
                                 BlockType::kBlockAllChildren),
-      BlockPath::CreateRelative(base::DIR_CACHE, BlockType::kBlockAllChildren),
 #endif
       // TODO(crbug.com/40095723): Refine this list, for example add
       // XDG_CONFIG_HOME when it is not set ~/.config?
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
index 93dd451..50d7a6d9 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
@@ -684,20 +684,22 @@
   EXPECT_TRUE(IsOpenAbort(app_data_dir.AppendASCII("foo"), HandleType::kFile));
   EXPECT_TRUE(
       IsOpenAbort(app_data_dir.AppendASCII("foo"), HandleType::kDirectory));
+#endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
   base::FilePath cache_dir = temp_dir_.GetPath().AppendASCII("cache");
   base::ScopedPathOverride cache_override(base::DIR_CACHE, cache_dir, true,
                                           true);
   ResetBlockPath();
-  // The android cache directory, its parent and paths inside should not be
+  // The cache directory, its parent and paths inside should not be
   // allowed.
   EXPECT_TRUE(IsOpenAbort(cache_dir, HandleType::kDirectory));
   EXPECT_TRUE(IsOpenAbort(temp_dir_.GetPath(), HandleType::kDirectory));
   EXPECT_TRUE(IsOpenAbort(cache_dir.AppendASCII("foo"), HandleType::kFile));
   EXPECT_TRUE(
       IsOpenAbort(cache_dir.AppendASCII("foo"), HandleType::kDirectory));
-
-#endif  // BUILDFLAG(IS_ANDROID)
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
+        // BUILDFLAG(IS_ANDROID)
 }
 
 // TODO(crbug.com/432011571): Flaky test.
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
index 93dd451..50d7a6d9 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
@@ -684,20 +684,22 @@
   EXPECT_TRUE(IsOpenAbort(app_data_dir.AppendASCII("foo"), HandleType::kFile));
   EXPECT_TRUE(
       IsOpenAbort(app_data_dir.AppendASCII("foo"), HandleType::kDirectory));
+#endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
   base::FilePath cache_dir = temp_dir_.GetPath().AppendASCII("cache");
   base::ScopedPathOverride cache_override(base::DIR_CACHE, cache_dir, true,
                                           true);
   ResetBlockPath();
-  // The android cache directory, its parent and paths inside should not be
+  // The cache directory, its parent and paths inside should not be
   // allowed.
   EXPECT_TRUE(IsOpenAbort(cache_dir, HandleType::kDirectory));
   EXPECT_TRUE(IsOpenAbort(temp_dir_.GetPath(), HandleType::kDirectory));
   EXPECT_TRUE(IsOpenAbort(cache_dir.AppendASCII("foo"), HandleType::kFile));
   EXPECT_TRUE(
       IsOpenAbort(cache_dir.AppendASCII("foo"), HandleType::kDirectory));
-
-#endif  // BUILDFLAG(IS_ANDROID)
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
+        // BUILDFLAG(IS_ANDROID)
 }
 
 // TODO(crbug.com/432011571): Flaky test.
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.