CVE-2024-23280

Overview

Advisory: Apple Security Advisory

Impact:

Description: A maliciously crafted webpage may be able to fingerprint the user

Researchers: an anonymous researcher

Attribute Value
CVE CVE-2024-23280
Bugzilla 266703
Component WebCore
Bug Class LogicError
Severity medium
Commit 17c0ad98bb1ce2d5…
Advisory Apple Advisory

Root Cause Analysis

An injection issue was addressed with improved validation.

Files Changed

Source Files

  • Source/WebCore/Modules/entriesapi/DOMFileSystem.cpp

Test Files

  • LayoutTests/http/tests/security/file-system-access-via-dataTransfer-expected.txt
  • LayoutTests/http/tests/security/file-system-access-via-dataTransfer.html

Patch Preview

diff --git a/LayoutTests/http/tests/security/file-system-access-via-dataTransfer-expected.txt b/LayoutTests/http/tests/security/file-system-access-via-dataTransfer-expected.txt
new file mode 100644
index 000000000000..641ddaebab3e
--- /dev/null
+++ b/LayoutTests/http/tests/security/file-system-access-via-dataTransfer-expected.txt
@@ -0,0 +1,10 @@
+Test that accessing local file system metadata is not allowed
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Should not receive file
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/security/file-system-access-via-dataTransfer.html b/LayoutTests/http/tests/security/file-system-access-via-dataTransfer.html
new file mode 100644
index 000000000000..caf05e1f85fc
--- /dev/null
+++ b/LayoutTests/http/tests/security/file-system-access-via-dataTransfer.html
@@ -0,0 +1,50 @@
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+<body>
+
+<script>
+description("Test that accessing local file system metadata is not allowed");
+
+function runTest() {
+    if (!window.internals) {
+        alert("This test depends on Internals");
+        return;
+    }
+
+    window.jsTestIsAsync = true;
+
+    let path = location.pathname.split("/");
+    let targetFileName = internals.createTemporaryFile(`${path[path.length - 1]}`, "");
+
+    let input = document.createElement("input");
+    input.type = "file";
+
+    let file = new File([], targetFileName, {"type":"text/plain"});
+
+    dataTransfer = new DataTransfer();
+    dataTransfer.items.add(file)
+    input.files = dataTransfer.files;
+
+    var functionOnSuccess = function (file)
+    {
+        testFailed("Should not receive file");
+        finishJSTest()
+    }
+
+    var functionOnError = function (value)
+    {
+        testPassed("Should not receive file");
+        finishJSTest()
+    }
+
+    input.webkitEntries.forEach((entry) => {
+        entry.file(functionOnSuccess, functionOnError)
+    });
+}
+
+runTest();
+
+</script>
+</body>
+</html>
diff --git a/Source/WebCore/Modules/entriesapi/DOMFileSystem.cpp b/Source/WebCore/Modules/entriesapi/DOMFileSystem.cpp
index 0c08ddbec609..e86b3dcc356c 100644
--- a/Source/WebCore/Modules/entriesapi/DOMFileSystem.cpp
+++ b/Source/WebCore/Modules/entriesapi/DOMFileSystem.cpp
@@ -303,6 +303,9 @@ void DOMFileSystem::getEntry(ScriptExecutionContext& context, FileSystemDirector
         return;
     }
 
+    if (m_rootPath.isEmpty())
+        return completionCallback(Exception { ExceptionCode::NotFoundError, "Path does not exist"_s });
+
     m_workQueue->dispatch([protectedThis = Ref { *this }, context = Ref { context }, fullPath = crossThreadCopy(WTFMove(fullPath)), resolvedVirtualPath = crossThreadCopy(WTFMove(resolvedVirtualPath)), completionCallback = WTFMove(completionCallback)]() mutable {
         auto entryType = fileTypeIgnoringHiddenFiles(fullPath);
         callOnMainThread([protectedThis = WTFMove(protectedThis), context = WTFMove(context), resolvedVirtualPath = crossThreadCopy(WTFMove(resolvedVirtualPath)), entryType, completionCallback = WTFMove(completionCallback)]() mutable {
@@ -327,6 +330,8 @@ void DOMFileSystem::getEntry(ScriptExecutionContext& context, FileSystemDirector
 
 void DOMFileSystem::getFile(ScriptExecutionContext& context, FileSystemFileEntry& fileEntry, GetFileCallback&& completionCallback)
 {
+    if (m_rootPath.isEmpty())
+        return completionCallback(Exception { ExceptionCode::NotFoundError, "Path does not exist"_s });
     auto virtualPath = fileEntry.virtualPath();
     auto fullPath = evaluatePath(virtualPath);
     m_workQueue->dispatch([fullPath = crossThreadCopy(WTFMove(fullPath)), virtualPath = crossThreadCopy(WTFMove(virtualPath)), context = Ref { context }, completionCallback = WTFMove(completionCallback)]() mutable {