Skip to content

[Bug]: Unhandled ValidationError in DispatcherConnection crashes the whole driver process on malformed CDP data (connect_over_cdp) #41865

Description

@Yoshinaga-iwnl

Version

1.52.0

Steps to reproduce

Connect to a third-party CDP endpoint that reports a malformed value in a network event. Concrete case: Lightpanda <= 0.3.5 serializes response header values / suggestedFilename containing non-UTF-8 bytes (e.g. a Shift_JIS Content-Disposition filename, still common on Japanese government sites) as JSON byte arrays instead of strings (lightpanda-io/browser#2972, lightpanda-io/browser#2992).

# pip install playwright==1.52.0
# lightpanda serve --host 127.0.0.1 --port 19222   (0.3.4, https://github.com/lightpanda-io/browser)
import asyncio, socket, threading
from playwright.async_api import async_playwright

RESPONSE = (
    b'HTTP/1.1 200 OK\r\n'
    b'Content-Type: text/html\r\n'
    b'Content-Disposition: attachment; filename="\x82\xd3\x82\xe9\x82\xb3\x82\xc6.xlsx"\r\n'  # Shift_JIS bytes
    b'Content-Length: 5\r\nConnection: close\r\n\r\nhello'
)

def serve():
    s = socket.socket(); s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(("127.0.0.1", 18080)); s.listen(4)
    while True:
        c, _ = s.accept(); c.recv(65536); c.sendall(RESPONSE); c.close()

async def main():
    threading.Thread(target=serve, daemon=True).start()
    async with async_playwright() as pw:
        browser = await pw.chromium.connect_over_cdp("http://127.0.0.1:19222")
        page = await (await browser.new_context()).new_page()
        await page.goto("http://127.0.0.1:18080/", wait_until="domcontentloaded")

asyncio.run(main())

Expected behavior

A validation failure on data coming from the browser fails the corresponding request/event (or at worst closes that one connection). page.goto raising an error would be fine.

Actual behavior

The ValidationError thrown while building the outgoing protocol message is uncaught inside the dispatcher, and the whole Node driver process exits. Every unrelated browser/connection served by that driver dies with Connection closed while reading from the driver. In our production crawler (many independent CDP connections sharing one Python async_playwright instance) a single malformed HTTP response on one site took down the entire fleet.

ValidationError: headers[7].value: expected string, got object
    at tString (.../driver/package/lib/protocol/validatorPrimitives.js:75:9)
    ...
    at DispatcherConnection.sendCreate (.../lib/server/dispatchers/dispatcher.js:172:19)
    at new Dispatcher (.../lib/server/dispatchers/dispatcher.js:75:24)
    at new ResponseDispatcher (.../lib/server/dispatchers/networkDispatchers.js:70:5)
Node.js v22.14.0

(With Lightpanda 0.3.5 the same crash occurs via the download path: ValidationError: suggestedFilename: expected string, got object at DispatcherConnection.sendEvent -> PageDispatcher._dispatchEvent.)

Additional context

I understand third-party CDP endpoints are not officially supported targets for connect_over_cdp. Filing this because the failure mode seems disproportionate regardless of the data source: one malformed event escapes DispatcherConnection.sendCreate/sendEvent as an uncaught exception and kills the shared driver process. Catching validation errors at the dispatch boundary (dropping/sanitizing the offending event or failing the associated call) would keep the blast radius to one page/connection.

Environment: Python 3.12, playwright 1.52.0 (bundled driver, Node.js v22.14.0), reproduced on macOS arm64 and Ubuntu (mcr.microsoft.com/playwright/python:v1.52.0-noble).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions