← All issues

[7] IndexedDB Connection/Transaction Identifier Confusion

Severity: High | Component: WebKit NetworkProcess | d854553

Rated High because the diff fixes broker-side IDB registries that dereferenced renderer-supplied identifiers without rebinding to the sender; the resulting primitive is cross-renderer (effectively cross-origin) read, write, and destroy of IndexedDB records.

NetworkStorageManager's IDB IPC handlers looked up IDBDatabaseConnectionIdentifier/IDBResourceIdentifier via IDBStorageRegistry keyed only by handle. Any WebContent process could submit another renderer's identifier and have the NetworkProcess act on it.

Source/WebKit/NetworkProcess/storage/IDBStorageRegistry.cpp

+bool IDBStorageRegistry::isValidConnectionForIPC(WebCore::IDBServer::UniqueIDBDatabaseConnection& databaseConnection, IPC::Connection& ipcConnection)
+{
+ auto connectionIdentifier = databaseConnection.connectionToClient().identifier();
+ auto it = m_connectionsToClient.find(connectionIdentifier);
+ if (it == m_connectionsToClient.end())
+ return true;
+ return it->value->ipcConnection() == ipcConnection.uniqueID();
+}
+SUPPRESS_NODELETE RefPtr<WebCore::IDBServer::UniqueIDBDatabaseConnection> IDBStorageRegistry::connection(WebCore::IDBDatabaseConnectionIdentifier identifier, IPC::Connection& ipcConnection)
+{
+ RefPtr databaseConnection = m_connections.get(identifier);
+ if (!databaseConnection)
+ return nullptr;
+ MESSAGE_CHECK_WITH_RETURN_VALUE(isValidConnectionForIPC(*databaseConnection, ipcConnection), ipcConnection, nullptr);
+ return databaseConnection;
+}

connection() and transaction() now take IPC::Connection& and call isValidConnectionForIPC(), which resolves the database connection's owning client and compares ipcConnection() against the sender's uniqueID(). Every IDB IPC handler (establishTransaction, commitTransaction, putOrAdd, getRecord, openCursor, iterateCursor, etc.) is updated to thread IPC::Connection& through.

Missing sender-to-resource binding at an IPC trust boundary, where opaque identifiers minted by the broker are dereferenced without verifying that the originating IPC connection owns them.

IndexedDB splits into a renderer-side WebCore layer and a NetworkProcess broker. IDBStorageRegistry holds m_connectionsToClient (keyed by IDBConnectionIdentifier, value records the originating IPC::Connection::UniqueID), m_connections (keyed by IDBDatabaseConnectionIdentifier), and m_transactions (keyed by IDBResourceIdentifier). IDBResourceIdentifier::connectionIdentifier() links back to a client connection. MESSAGE_CHECK terminates the offending child process on failure.

Identifiers handed back to a renderer are capabilities; the broker must rebind on every call. Before the fix, WebContent A could send establishTransaction / putOrAdd / getRecord carrying WebContent B's identifier and have NetworkProcess execute against B's connection.

🔒

How a NetworkProcess-side registry of IndexedDB handles became a cross-renderer capability — and what classes of primitive the missing sender check exposed.

Subscribe to read more

🔒

Multiple reusable broker-authorization audit patterns, with concrete starting points across NetworkProcess and GPUProcess registries.

Subscribe to read more