← All issues

[2] Attachment-element arbitrary file read via unvalidated IPC path

Severity: High | Component: WebKit UIProcess attachment handling | c6cd4e0

Rated High because the diff adds a previously-missing provenance check that let a compromised renderer name any UI-process-readable file and bind its contents to an attachment; escalation to a sandbox-filesystem-escape information leak requires only a prior renderer compromise, and the /etc/passwd regression test confirms the path was reachable.

Maintain an allowlist of file paths (m_allowedAttachmentFilePaths) in WebProcessProxy that tracks paths legitimately provided to the web process via pasteboard and drag-drop operations. Validate incoming paths in RegisterAttachmentIdentifierFromFilePath against this allowlist using MESSAGE_CHECK, terminating the web process for unauthorized paths.

Source/WebKit/UIProcess/WebPageProxy.cpp

void WebPageProxy::registerAttachmentIdentifierFromFilePath(IPC::Connection& con...
{
MESSAGE_CHECK_BASE(protect(preferences())->attachmentElementEnabled(), connection);
MESSAGE_CHECK_BASE(IdentifierToAttachmentMap::isValidKey(identifier), connection);
+ MESSAGE_CHECK_BASE(WebProcessProxy::fromConnection(connection)->isAllowedAttachmentFilePath(filePath), connection);
...
+#if ENABLE(ATTACHMENT_ELEMENT)
+ for (auto& filename : dragData.fileNames())
+ protect(protectedThis->legacyMainFrameProcess())->addAllowedAttachmentFilePath(filename);
+#endif

Source/WebKit/UIProcess/WebProcessProxy.cpp

+void WebProcessProxy::addAllowedAttachmentFilePath(const String& filePath)
+{
+ if (!filePath.isEmpty())
+ m_allowedAttachmentFilePaths.add(filePath);
+}
+bool WebProcessProxy::isAllowedAttachmentFilePath(const String& filePath) const
+{
+ return m_allowedAttachmentFilePaths.contains(filePath);
+}

Tools/TestWebKitAPI/Tests/WebKit/WKWebView/WKAttachmentTests.mm

+ [webView evaluateJavaScript:
+ @"IPC.sendMessage('UI', IPC.webPageProxyID, IPC.messages.WebPageProxy_RegisterAttachmentIdentifierFromFilePath.name, ["
+ " {type: 'String', value: 'fake-identifier'},"
+ " {type: 'String', value: 'application/octet-stream'},"
+ " {type: 'String', value: '/etc/passwd'}"
+ "])"
+ completionHandler:nil];
+ [navigationDelegate waitForWebContentProcessDidTerminate];

The patch adds HashSet<String> m_allowedAttachmentFilePaths to WebProcessProxy, populated at every legitimate point where the UI process hands real filesystem paths to the web process: drag-drop (performDragOperation iterates dragData.fileNames()) and pasteboard reads in WebPasteboardProxyCocoa.mm via a new addAllowedAttachmentFilePaths helper. Enforcement is a new MESSAGE_CHECK_BASE(... isAllowedAttachmentFilePath(filePath), connection) in registerAttachmentIdentifierFromFilePath, terminating the web process for paths never legitimately granted. A secondary hardening adds an isValidKey check to registerAttachmentsFromSerializedData.

Missing provenance validation on a filesystem path crossing the WebContent-to-UIProcess IPC boundary, letting a sandboxed sender name files it was never granted.

A WebProcessProxy is the UI-process object representing one web content process; it runs with full user privileges outside the WebContent sandbox. An <attachment> element's backing data can be a file on disk, registered by identifier; registerAttachmentIdentifierFromFilePath is the UI-process IPC handler that creates such an attachment from a path supplied by the web process. The only legitimate way the UI process exposes real filesystem paths to a renderer is when the user drags files in or pastes file URLs, at which point the UI process resolves and shares those specific paths via sandbox extensions. MESSAGE_CHECK_BASE terminates the sending process when its assertion fails.

This is a classic confused-deputy / missing-IPC-validation bug. Before the fix, registerAttachmentIdentifierFromFilePath accepted an arbitrary filePath string from the renderer and registered an attachment backed by that path, with no check that the UI process had ever legitimately exposed it. The missing invariant: a file path used to create an attachment must trace back to a real user-driven grant (drag-drop or pasteboard read).

🔒

How a single unvalidated IPC argument turns a privileged-process file operation into a renderer-visible disclosure is traced end to end.

Subscribe to read more

🔒

Three reusable audit patterns for confused-deputy IPC bugs are identified, with concrete UIProcess starting points for variant discovery.

Subscribe to read more