CVE-2025-24143
Overview
Background
- Entries API (webkitEntries)
- A DOM API exposing FileSystemEntry/FileSystemDirectoryEntry objects from a DataTransfer or file input, allowing scripted navigation of dropped files and folders.
- DOMFileSystem m_rootPath
- The base filesystem path that scopes all path resolution for a DOMFileSystem instance to authorized content; an empty value means no legitimate root was established.
- getParent / readEntries
- FileSystemEntry operations that walk to a containing directory or enumerate a directory’s children, both of which reach real-filesystem metadata calls in WebCore.
- Fingerprinting oracle
- A side channel where success-vs-error callbacks (or returned metadata) let a page infer the existence or attributes of local files without directly reading their contents.
- Work queue dispatch
- The pattern of moving blocking filesystem I/O to a background thread and marshalling the result back to the main thread via callOnMainThread; the guard is added before this dispatch.
Root Cause Analysis
The patch touches Source/WebCore/Modules/entriesapi/DOMFileSystem.cpp, the implementation behind the Entries API (webkitEntries / FileSystemEntry) that a page can obtain from a DataTransfer during drag-and-drop or a file input. Each DOMFileSystem is created with an m_rootPath that scopes all path resolution to files the user actually granted. In DOMFileSystem::listDirectory and DOMFileSystem::getParent, the code resolved a virtual path and then dispatched work to a background queue to enumerate directory children (listDirectoryWithMetadata) or validate/stat the parent directory on the real filesystem. The violated invariant is that these filesystem operations must only run when the object has a valid, non-empty root path scoping it to authorized content; when m_rootPath is empty (for example an entry synthesized from a dropped File whose real path was never actually admitted), path evaluation can still resolve to something outside the intended sandbox, letting the background job touch and report metadata about the local filesystem.
The fix adds an explicit guard at the top of both functions: if m_rootPath.isEmpty(), immediately invoke the completion handler/callback with a NotFoundError (‘Path does not exist’) and return, before any work is dispatched to the work queue. This ensures that an un-rooted DOMFileSystem cannot be used to enumerate a directory’s children or walk to a parent directory. The updated LayoutTest confirms the intent: it now also adds a directory File to the DataTransfer and, for each entry, calls entry.file(), entry.getParent(), and (for directories) createReader().readEntries(), all of which must fail with ‘Should not receive file’ errors. Notably file() was already guarded (the pre-existing single PASS), but getParent() and readEntries() were the newly-closed holes, which is exactly what the two new guards in listDirectory and getParent cover.
The result is that previously an attacker could distinguish existence/metadata of local paths (a fingerprinting/info-leak oracle) via these two entry points; the fix removes the oracle by refusing the operation outright when there is no legitimate root.
Attack Path
- Obtain a FileSystemEntry without a real root Get the page to receive entries via webkitEntries from a DataTransfer (drag-and-drop or a crafted file input), producing a DOMFileSystem whose m_rootPath is empty.
- Walk to a parent directory Call entry.getParent(success, error); before the fix this dispatched a background job that resolved and validated a full filesystem path despite the empty root.
- Enumerate directory children For a directory entry, call entry.createReader().readEntries(…) which reached listDirectory and ran listDirectoryWithMetadata against a path outside the intended sandbox.
- Read back the outcome as an oracle Observe whether the success or error callback fires (and any returned metadata) to infer the existence and attributes of local files/directories, building a fingerprint of the user’s system.
- Repeat across paths Probe multiple candidate paths to accumulate fingerprinting signal about installed software, usernames, or directory layout.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
DOMFileSystem::listDirectorySource/WebCore/Modules/entriesapi/DOMFileSystem.cpp |
modified | Adds an early guard: if m_rootPath.isEmpty(), return a NotFoundError via completionHandler before dispatching the directory-enumeration job to the work queue. |
DOMFileSystem::getParentSource/WebCore/Modules/entriesapi/DOMFileSystem.cpp |
modified | Adds the same guard after path evaluation: if m_rootPath.isEmpty(), return a NotFoundError via completionCallback before dispatching the parent-directory validation job. |
file-system-access-via-dataTransfer test (runTest)LayoutTests/http/tests/security/file-system-access-via-dataTransfer.html |
modified | Extends the regression test to also add a directory entry and to exercise getParent() and readEntries() in addition to file(), asserting all must error. |
expected resultsLayoutTests/http/tests/security/file-system-access-via-dataTransfer-expected.txt |
modified | Adds two more 'PASS Should not receive file' lines reflecting the newly-guarded getParent/readEntries paths. |
mac-wk1 expected resultsLayoutTests/platform/mac-wk1/http/tests/security/file-system-access-via-dataTransfer-expected.txt |
added | New WebKit1/mac platform-specific expectation file with four PASS lines for the expanded test. |
Audit Directions
- Other DOMFileSystem entry pointsReview every public method of DOMFileSystem.cpp that resolves or evaluates a path (grep for ’evaluatePath’, ‘resolveRelativeVirtualPath’, ’m_workQueue->dispatch’, ’listDirectoryWithMetadata’, ‘validatePathIsExpectedType’) and confirm each has the m_rootPath.isEmpty() guard before dispatching filesystem work.
- Root/precondition consistency across the Entries APICheck FileSystemEntry, FileSystemDirectoryEntry, FileSystemDirectoryReader and DOMFileSystemSync for the same class of missing guard; grep for ‘rootPath’, ‘isEmpty()’ near path evaluation and ensure new operations added later inherit the check.
- Empty/unvalidated base-path assumptions elsewhereSearch WebCore filesystem and File/Blob code for callbacks that return metadata based on a stored base path without validating it is non-empty and in-sandbox; grep for ‘crossThreadCopy’ of a fullPath immediately after ’evaluatePath’ without a preceding emptiness/authorization check.