Skip to content

Fatal: host process exits when WebView2 web message is not a string (TryGetWebMessageAsString -> E_INVALIDARG) #34

@shellphy

Description

@shellphy

Summary

On Windows, the host process can exit when a page posts a non-string payload via chrome.webview.postMessage(...).
go-webview2 currently calls TryGetWebMessageAsString() unconditionally in Chromium.MessageReceived(). If the payload is not a string (e.g. object/JSON), WebView2 returns E_INVALIDARG ("The parameter is incorrect."), and go-webview2 treats it as fatal and exits the process (via os.Exit(1)).

This makes the host vulnerable: any website that posts a non-string web message can crash the host app.

Environment

  • OS: Windows 10 Pro, Version 2009 (Build 26200) (branding shows Windows 11 Pro)
  • WebView2 Runtime: 144.0.3719.82
  • go-webview2: v1.0.22
  • Go: 1.25.x
  • (Optional) Wails v3: v3.0.0-alpha.61

Steps to Reproduce

Repro A (real-world website)

  1. Create a WebView2 instance using go-webview2 (any embed scenario, e.g. Wails window/panel, or a minimal go-webview2 host).
  2. Navigate to https://yiyan.baidu.com/.
  3. Wait until the page finishes part of its UI initialization (often 1–2 seconds after some UI is visible).
  4. The host process exits.

Repro B (minimal)

  1. Load a page that runs:
    chrome.webview.postMessage({ hello: "world" });
  2. The host receives WebMessageReceived.
    TryGetWebMessageAsString() fails with E_INVALIDARG, and the host exits.

Expected Behavior

  • Receiving a non-string web message must not terminate the host process.
  • The message should either:
    • be read as JSON (GetWebMessageAsJSON) and passed to callbacks, or
    • be ignored safely if it cannot be read.

Actual Behavior

  • Host process exits after a non-string message is posted.
  • Observed error: The parameter is incorrect.

Relevant Code

In pkg/edge/chromium.go, MessageReceived() currently does:

  • args.TryGetWebMessageAsString() unconditionally
  • treats errors as fatal

Suggested Fix

In Chromium.MessageReceived():

  1. Attempt TryGetWebMessageAsString().
  2. If it fails, do not call the fatal error handler.
  3. Fallback to GetWebMessageAsJSON() to obtain a JSON string.
  4. If both fail, ignore the message and return 0.
  5. Only echo back with PostWebMessageAsString(message) when the message is truly a string payload (avoid changing semantics for JSON messages).

This would prevent arbitrary websites from crashing the host.

Logs / Stack (trimmed)

When instrumented on the app side, the fatal path points to MessageReceived() -> TryGetWebMessageAsString():

  • .../go-webview2@v1.0.22/pkg/edge/chromium.go:402
  • args.TryGetWebMessageAsString() -> E_INVALIDARG ("The parameter is incorrect.")
  • then fatal exit occurs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions