CVE-2026-119272
Overview
Background
- File System Access API (FSA)
- Web API letting a granted origin read/write files and directories on the user’s real filesystem via
showOpenFilePicker/showDirectoryPicker/showSaveFilePickerand programmatic handles. - `ChromeFileSystemAccessPermissionContext`
- The browser-process policy class (
chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc) that decides, per path, whether an FSA access is permitted.ConfirmSensitiveEntryAccessconsults a static blocklist of sensitive paths. - `BlockPath` / `BlockType`
- Blocklist entries:
CreateRelative/CreateAbsolute/CreateSuffixwithkBlockAllChildren(no access),kBlockWrite(reads allowed, writes denied). Matching is path/suffix based and case-insensitive (the test checks.GIT/CONFIG). - `AccessTrigger`
- The operation kind (
kOpen,kSave,kProgrammaticRead,kProgrammaticWrite) evaluated against the blocklist to produceSensitiveDirectoryResult::kAllowed/kAbort.
Root Cause Analysis
The sensitive-path blocklist in ChromeFileSystemAccessPermissionContext was incomplete and inconsistent across platforms, so several security-sensitive locations remained reachable through FSA. The patch adds entries to close the gaps: write-blocks on */.git/config and */.git/modules (via BlockPath::CreateSuffix(..., kBlockWrite), alongside the existing .git/hooks), while keeping reads allowed so web Git clients still work; a kBlockAllChildren block on ~/.config on all platforms (previously it was blocked only on Linux/ChromeOS/Android — the diff moves it out of the Linux-only section into the shared list); blocks on shell startup files in the home directory (.bash_profile, .bash_login, .bashrc, .profile, .zshenv, .zprofile, .zshrc, .zlogin, including the ones Git Bash reads on Windows); a /dev block on macOS to match Linux; and, on Linux/ChromeOS, blocks on ~/.local/share, the legacy fontconfig files ~/.fonts.conf and ~/.fonts.conf.d, and the NSS database directory ~/.pki.
The invariant being restored is that FSA must never let a web origin obtain write access to files that are executed, sourced, or trusted as configuration by the user’s shell, Git, or security tooling (and must not expose device nodes or credential stores). The most dangerous previously-reachable targets are the writable ones: .git/config (whose core.fsmonitor/alias/core.hooksPath directives can run arbitrary commands on the next git invocation), .git/modules/* (submodule git-dirs carrying their own hooks/config), and the shell rc/profile files (sourced on the next shell start). The tests confirm the intended granularity: .git/config and everything under .git/modules abort for kSave/kProgrammaticWrite but are allowed for kOpen/kProgrammaticRead; sibling files like config.bak or a config outside .git stay allowed; and the .git directory itself remains savable.
Critically, the advisory classifies this as “Out of bounds read in FileSystem,” but the diff contains no array/buffer indexing, no bounds arithmetic, and no memory-safety sink at all. It is purely an access-control/policy blocklist gap: sensitive paths that should have been denied were permitted. The real bug class is a policy bypass (sandbox/trust-boundary enforcement failure), not an OOB read — this is a clear advisory mislabel.
Attack Path
- Obtain an FSA handle A web origin persuades the user to grant a directory or file handle (e.g. “open your project folder” / a save dialog), the normal FSA permission step.
- Target a sensitive path
Using the granted (or picker-selected) handle, the page resolves a path into the repo’s
.git/config,.git/modules/*, or the user’s home-dir shell rc/profile files — paths the blocklist previously did not deny for write. - Write malicious content
The page writes a
.git/configwith a command-executing directive (e.g. a hooks path or fsmonitor hook) or appends an attacker command to~/.bashrc/~/.zshrc/.bash_profile. - Wait for trust
The next time the user runs
gitin that repo, or opens a new shell, the attacker-controlled configuration/script is sourced and executes. - Primitive
Arbitrary command execution on the host outside the browser sandbox (via Git/shell trust), or, for the read-side gaps, disclosure of credentials from
~/.pki(NSS DB) and other sensitive config. This is a sandbox/policy-boundary bypass, not a memory-corruption primitive.
Impact Assessment
~/.pki, ~/.config) on platforms where they were unblocked. The strength is high (host code execution / credential theft) but contingent on the user granting FSA access to a location containing those files and on a subsequent Git/shell invocation. No memory-safety primitive is involved, contrary to the advisory’s OOB-read label.Files Changed
chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.ccchrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
Audit Directions
- Cross-platform consistency of the blocklistDiff the per-
BUILDFLAGsections for other sensitive paths blocked on one OS but not others (this fix moved~/.configand/dev); credential, keyring, and config directories are prime candidates. - Other "write enables code execution" targetsReview for files beyond
.gitand shell rc that are auto-sourced/executed by tools: CI configs, editor dotfiles,.gitconfiginclude directives,.npmrc, systemd user units, and similar, which an FSA write could weaponize. - Suffix vs. absolute matching and symlinksAudit
CreateSuffixmatching for bypasses (alternate separators, trailing dots,.gitnesting) and whether handle resolution can reach blocked paths through symlinks or bind mounts not normalized before the blocklist check. - Read-allowed sensitive filesSince
.git/configreads stay permitted, review what other read-allowed config files can leak secrets (tokens embedded in URLs, credential helpers) via FSA.
Patch
From d6f2c70dbb4cd97f6eaf62aed88c8f2e57ef3fce Mon Sep 17 00:00:00 2001 From: Mingyu Lei <[email protected]> Date: Wed, 21 Oct 2026 23:00:11 -0700 Subject: [PATCH] FSA: Add missing sensitive paths to the blocklist Several sensitive locations are still reachable through File System Access because they are missing from the sensitive-path blocklist, or are only blocked on some platforms. Add them: - Block write access to */.git/config and */.git/modules on all platforms, alongside */.git/hooks. Reads stay allowed, so web Git clients can still read repository configuration. - Block ~/.config on all platforms. It was only blocked on Linux, ChromeOS and Android. - Block shell startup files in the home directory on all platforms, including the ones Git Bash reads on Windows. - Block /dev on macOS, matching Linux. - Block ~/.local/share, the legacy fontconfig files ~/.fonts.conf and ~/.fonts.conf.d, and the NSS database directory ~/.pki on Linux and ChromeOS. Bug: 572269631, 571913154, 569012015, 558362029 Bug: 569012543, 561996724, 559780982, 557367241 Test: unit_tests --gtest_filter=ChromeFileSystemAccessPermissionContextTest.*ConfirmSensitiveEntryAccess* Change-Id: Ia6fe9e51807e8106fbc6ac69e28d550660e49b38 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8619619 Reviewed-by: Fergal Daly <[email protected]> Commit-Queue: Mingyu Lei <[email protected]> Cr-Commit-Position: refs/heads/main@{#1724465} --- 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 112be22..be365904 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 @@ -441,10 +441,41 @@ // And limit access to ~/.gnupg as well. BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".gnupg"), BlockType::kBlockAllChildren), + // ~/.config holds configuration for many cross-platform tools, so block + // it on all platforms, see crbug.com/569012015. + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".config"), + BlockType::kBlockAllChildren), + // Shell startup files in the home directory, including the ones read by + // Git Bash on Windows, see crbug.com/558362029. + BlockPath::CreateRelative(base::DIR_HOME, + FILE_PATH_LITERAL(".bash_profile"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, + FILE_PATH_LITERAL(".bash_login"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".bashrc"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".profile"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".zshenv"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".zprofile"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".zshrc"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".zlogin"), + BlockType::kBlockAllChildren), // Block write access to */.git/hooks, see crbug.com/465668234 and // crbug.com/553115714. BlockPath::CreateSuffix(FILE_PATH_LITERAL(".git/hooks"), BlockType::kBlockWrite), + // Block write access to the repository config and to submodule git + // directories, which have their own hooks and config, see + // crbug.com/572269631 and crbug.com/571913154. + BlockPath::CreateSuffix(FILE_PATH_LITERAL(".git/config"), + BlockType::kBlockWrite), + BlockPath::CreateSuffix(FILE_PATH_LITERAL(".git/modules"), + BlockType::kBlockWrite), #if BUILDFLAG(IS_WIN) // Some Windows specific directories to block, basically all apps, the // operating system itself, as well as configuration data for apps. @@ -475,6 +506,10 @@ // volumes). BlockPath::CreateAbsolute(FILE_PATH_LITERAL("/System/Volumes"), BlockType::kBlockAllChildren), + // Block access to devices via /dev, matching Linux, see + // crbug.com/569012543. + BlockPath::CreateAbsolute(FILE_PATH_LITERAL("/dev"), + BlockType::kBlockAllChildren), BlockPath::CreateRelative(base::DIR_APP_DATA, BlockType::kBlockAllChildren), // Block access to the current bundle directory. @@ -525,14 +560,25 @@ BlockType::kBlockAllChildren), BlockPath::CreateAbsolute(FILE_PATH_LITERAL("/etc"), BlockType::kBlockAllChildren), - // And block all of ~/.config, matching the similar restrictions on mac - // and windows. - BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".config"), - BlockType::kBlockAllChildren), // Block ~/.dbus as well, just in case, although there probably isn't much // a website can do with access to that directory and its contents. BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".dbus"), BlockType::kBlockAllChildren), + // Block per-user application data, see crbug.com/561996724. + BlockPath::CreateRelative(base::DIR_HOME, + FILE_PATH_LITERAL(".local/share"), + BlockType::kBlockAllChildren), + // Block the legacy per-user fontconfig configuration, see + // crbug.com/559780982. The current location is under ~/.config. + BlockPath::CreateRelative(base::DIR_HOME, + FILE_PATH_LITERAL(".fonts.conf"), + BlockType::kBlockAllChildren), + BlockPath::CreateRelative(base::DIR_HOME, + FILE_PATH_LITERAL(".fonts.conf.d"), + BlockType::kBlockAllChildren), + // Block the per-user NSS database, see crbug.com/557367241. + BlockPath::CreateRelative(base::DIR_HOME, FILE_PATH_LITERAL(".pki"), + BlockType::kBlockAllChildren), // And block all of ~/.cache, matching the similar restrictions on mac // and windows. BlockPath::CreateRelative(base::DIR_CACHE, BlockType::kBlockAllChildren), 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 1bd9323..d500135 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 @@ -862,9 +862,8 @@ TEST_F(ChromeFileSystemAccessPermissionContextTest, ConfirmSensitiveEntryAccess_ExplicitPathBlock) { -// Linux is the only OS where we have some blocked directories with explicit -// paths (as opposed to PathService provided paths). -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \ + BUILDFLAG(IS_MAC) // /dev should be blocked. EXPECT_EQ(ConfirmSensitiveEntryAccessSync( permission_context(), PathInfo(FILE_PATH_LITERAL("/dev")), @@ -1604,6 +1603,101 @@ SensitiveDirectoryResult::kAllowed); } +// Testing that writes to */.git/config and */.git/modules are blocked, while +// reads stay allowed. +TEST_F(ChromeFileSystemAccessPermissionContextTest, + ConfirmSensitiveEntryAccess_GitConfigAndModulesWriteBlock) { +#if defined(FILE_PATH_USES_DRIVE_LETTERS) + base::FilePath root(FILE_PATH_LITERAL("c:\\")); +#else + base::FilePath root(FILE_PATH_LITERAL("/")); +#endif + const base::FilePath git_dir = + root.Append(FILE_PATH_LITERAL("a")).Append(FILE_PATH_LITERAL(".git")); + const base::FilePath git_config = git_dir.Append(FILE_PATH_LITERAL("config")); + const base::FilePath git_modules = + git_dir.Append(FILE_PATH_LITERAL("modules")); + const base::FilePath submodule_dir = + git_modules.Append(FILE_PATH_LITERAL("sub")); + + // .git/config is blocked for save and programmatic write. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_config), HandleType::kFile, + AccessTrigger::kSave), + SensitiveDirectoryResult::kAbort); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_config), HandleType::kFile, + AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAbort); + // .git/config is not blocked for read. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_config), HandleType::kFile, + AccessTrigger::kOpen), + SensitiveDirectoryResult::kAllowed); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_config), HandleType::kFile, + AccessTrigger::kProgrammaticRead), + SensitiveDirectoryResult::kAllowed); + // Case variations of .git/config are blocked for programmatic write. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), + PathInfo(root.Append(FILE_PATH_LITERAL("a")) + .Append(FILE_PATH_LITERAL(".GIT")) + .Append(FILE_PATH_LITERAL("CONFIG"))), + HandleType::kFile, AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAbort); + // Other files under .git, and files named config outside of .git, are + // allowed. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), + PathInfo(git_dir.Append(FILE_PATH_LITERAL("config.bak"))), + HandleType::kFile, AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAllowed); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), + PathInfo(root.Append(FILE_PATH_LITERAL("a")) + .Append(FILE_PATH_LITERAL("config"))), + HandleType::kFile, AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAllowed); + + // .git/modules and everything inside it is blocked for save and programmatic + // write. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_modules), + HandleType::kDirectory, AccessTrigger::kSave), + SensitiveDirectoryResult::kAbort); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_modules), + HandleType::kDirectory, AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAbort); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), + PathInfo(submodule_dir.Append(FILE_PATH_LITERAL("hooks")) + .Append(FILE_PATH_LITERAL("pre-commit"))), + HandleType::kFile, AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAbort); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), + PathInfo(submodule_dir.Append(FILE_PATH_LITERAL("config"))), + HandleType::kFile, AccessTrigger::kProgrammaticWrite), + SensitiveDirectoryResult::kAbort); + // .git/modules is not blocked for read. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_modules), + HandleType::kDirectory, AccessTrigger::kOpen), + SensitiveDirectoryResult::kAllowed); + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), + PathInfo(submodule_dir.Append(FILE_PATH_LITERAL("config"))), + HandleType::kFile, AccessTrigger::kProgrammaticRead), + SensitiveDirectoryResult::kAllowed); + // The .git directory itself is still allowed for save. + EXPECT_EQ(ConfirmSensitiveEntryAccessSync( + permission_context(), PathInfo(git_dir), HandleType::kDirectory, + AccessTrigger::kSave), + SensitiveDirectoryResult::kAllowed); +} + #if BUILDFLAG(IS_ANDROID) TEST_F(ChromeFileSystemAccessPermissionContextTest, ConfirmSensitiveEntryAccess_ContentUri) { @@ -1867,6 +1961,15 @@ {chrome::DIR_USER_DATA, nullptr, true, false}, {base::DIR_HOME, FILE_PATH_LITERAL(".ssh"), true, false}, {base::DIR_HOME, FILE_PATH_LITERAL(".gnupg"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".config"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".bash_profile"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".bash_login"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".bashrc"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".profile"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".zshenv"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".zprofile"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".zshrc"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".zlogin"), true, false}, #if BUILDFLAG(IS_WIN) {base::DIR_PROGRAM_FILES, nullptr, true, false}, @@ -1880,6 +1983,7 @@ #endif #if BUILDFLAG(IS_MAC) + {kNoBasePathKey, FILE_PATH_LITERAL("/dev"), true, false}, {base::DIR_APP_DATA, nullptr, true, false}, {chrome::DIR_OUTER_BUNDLE, nullptr, true, false}, {base::DIR_HOME, FILE_PATH_LITERAL("Applications"), true, false}, @@ -1900,8 +2004,11 @@ {kNoBasePathKey, FILE_PATH_LITERAL("/sys"), true, false}, {kNoBasePathKey, FILE_PATH_LITERAL("/boot"), true, false}, {kNoBasePathKey, FILE_PATH_LITERAL("/etc"), true, false}, - {base::DIR_HOME, FILE_PATH_LITERAL(".config"), true, false}, {base::DIR_HOME, FILE_PATH_LITERAL(".dbus"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".local/share"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".fonts.conf"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".fonts.conf.d"), true, false}, + {base::DIR_HOME, FILE_PATH_LITERAL(".pki"), true, false}, #endif #if BUILDFLAG(IS_ANDROID)
Regression Test / PoC
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 1bd9323..d500135 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
@@ -862,9 +862,8 @@
TEST_F(ChromeFileSystemAccessPermissionContextTest,
ConfirmSensitiveEntryAccess_ExplicitPathBlock) {
-// Linux is the only OS where we have some blocked directories with explicit
-// paths (as opposed to PathService provided paths).
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
+ BUILDFLAG(IS_MAC)
// /dev should be blocked.
EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
permission_context(), PathInfo(FILE_PATH_LITERAL("/dev")),
@@ -1604,6 +1603,101 @@
SensitiveDirectoryResult::kAllowed);
}
+// Testing that writes to */.git/config and */.git/modules are blocked, while
+// reads stay allowed.
+TEST_F(ChromeFileSystemAccessPermissionContextTest,
+ ConfirmSensitiveEntryAccess_GitConfigAndModulesWriteBlock) {
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+ base::FilePath root(FILE_PATH_LITERAL("c:\\"));
+#else
+ base::FilePath root(FILE_PATH_LITERAL("/"));
+#endif
+ const base::FilePath git_dir =
+ root.Append(FILE_PATH_LITERAL("a")).Append(FILE_PATH_LITERAL(".git"));
+ const base::FilePath git_config = git_dir.Append(FILE_PATH_LITERAL("config"));
+ const base::FilePath git_modules =
+ git_dir.Append(FILE_PATH_LITERAL("modules"));
+ const base::FilePath submodule_dir =
+ git_modules.Append(FILE_PATH_LITERAL("sub"));
+
+ // .git/config is blocked for save and programmatic write.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_config), HandleType::kFile,
+ AccessTrigger::kSave),
+ SensitiveDirectoryResult::kAbort);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_config), HandleType::kFile,
+ AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAbort);
+ // .git/config is not blocked for read.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_config), HandleType::kFile,
+ AccessTrigger::kOpen),
+ SensitiveDirectoryResult::kAllowed);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_config), HandleType::kFile,
+ AccessTrigger::kProgrammaticRead),
+ SensitiveDirectoryResult::kAllowed);
+ // Case variations of .git/config are blocked for programmatic write.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(),
+ PathInfo(root.Append(FILE_PATH_LITERAL("a"))
+ .Append(FILE_PATH_LITERAL(".GIT"))
+ .Append(FILE_PATH_LITERAL("CONFIG"))),
+ HandleType::kFile, AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAbort);
+ // Other files under .git, and files named config outside of .git, are
+ // allowed.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(),
+ PathInfo(git_dir.Append(FILE_PATH_LITERAL("config.bak"))),
+ HandleType::kFile, AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAllowed);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(),
+ PathInfo(root.Append(FILE_PATH_LITERAL("a"))
+ .Append(FILE_PATH_LITERAL("config"))),
+ HandleType::kFile, AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAllowed);
+
+ // .git/modules and everything inside it is blocked for save and programmatic
+ // write.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_modules),
+ HandleType::kDirectory, AccessTrigger::kSave),
+ SensitiveDirectoryResult::kAbort);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_modules),
+ HandleType::kDirectory, AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAbort);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(),
+ PathInfo(submodule_dir.Append(FILE_PATH_LITERAL("hooks"))
+ .Append(FILE_PATH_LITERAL("pre-commit"))),
+ HandleType::kFile, AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAbort);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(),
+ PathInfo(submodule_dir.Append(FILE_PATH_LITERAL("config"))),
+ HandleType::kFile, AccessTrigger::kProgrammaticWrite),
+ SensitiveDirectoryResult::kAbort);
+ // .git/modules is not blocked for read.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_modules),
+ HandleType::kDirectory, AccessTrigger::kOpen),
+ SensitiveDirectoryResult::kAllowed);
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(),
+ PathInfo(submodule_dir.Append(FILE_PATH_LITERAL("config"))),
+ HandleType::kFile, AccessTrigger::kProgrammaticRead),
+ SensitiveDirectoryResult::kAllowed);
+ // The .git directory itself is still allowed for save.
+ EXPECT_EQ(ConfirmSensitiveEntryAccessSync(
+ permission_context(), PathInfo(git_dir), HandleType::kDirectory,
+ AccessTrigger::kSave),
+ SensitiveDirectoryResult::kAllowed);
+}
+
#if BUILDFLAG(IS_ANDROID)
TEST_F(ChromeFileSystemAccessPermissionContextTest,
ConfirmSensitiveEntryAccess_ContentUri) {
@@ -1867,6 +1961,15 @@
{chrome::DIR_USER_DATA, nullptr, true, false},
{base::DIR_HOME, FILE_PATH_LITERAL(".ssh"), true, false},
{base::DIR_HOME, FILE_PATH_LITERAL(".gnupg"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".config"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".bash_profile"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".bash_login"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".bashrc"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".profile"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".zshenv"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".zprofile"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".zshrc"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".zlogin"), true, false},
#if BUILDFLAG(IS_WIN)
{base::DIR_PROGRAM_FILES, nullptr, true, false},
@@ -1880,6 +1983,7 @@
#endif
#if BUILDFLAG(IS_MAC)
+ {kNoBasePathKey, FILE_PATH_LITERAL("/dev"), true, false},
{base::DIR_APP_DATA, nullptr, true, false},
{chrome::DIR_OUTER_BUNDLE, nullptr, true, false},
{base::DIR_HOME, FILE_PATH_LITERAL("Applications"), true, false},
@@ -1900,8 +2004,11 @@
{kNoBasePathKey, FILE_PATH_LITERAL("/sys"), true, false},
{kNoBasePathKey, FILE_PATH_LITERAL("/boot"), true, false},
{kNoBasePathKey, FILE_PATH_LITERAL("/etc"), true, false},
- {base::DIR_HOME, FILE_PATH_LITERAL(".config"), true, false},
{base::DIR_HOME, FILE_PATH_LITERAL(".dbus"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".local/share"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".fonts.conf"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".fonts.conf.d"), true, false},
+ {base::DIR_HOME, FILE_PATH_LITERAL(".pki"), true, false},
#endif
#if BUILDFLAG(IS_ANDROID)