Skip to content

No way to opt out of the renderer bridge — preload is injected into every session, with no sender validation on the IPC channel #175

Description

@willschnicke-silkline

We're integrating @datadog/electron-sdk (0.6.0) for main-process-only telemetry in an Electron shell that hosts both a trusted first-party web app and untrusted third-party pages in a sandboxed WebContentsView. Three interacting behaviors caused real problems:

1. The bridge preload is registered on every session, unconditionally.
instrument's patchBrowserWindow hooks app.on('session-created') and calls session.registerPreloadScript(...) on all sessions — including custom partitions deliberately created with no preload as a security boundary. There is no InitConfiguration option to disable this.

2. allowedWebViewHosts: [] does not disable the bridge.
The preload always adds the page's own hostname to the advertised allowed hosts:

const allowedHosts = [...new Set([location.hostname, ...configuredHosts])];

so every page is always bridge-eligible for itself, regardless of config.

3. The main-process handler does no sender validation.
ipcMain.on('datadog:bridge-send', ...) forwards any parsed message into the RUM intake without checking the sender's frame/origin/session.

Observed consequences:

  • Our trusted window's page runs its own @datadog/browser-rum (separate RUM application). On detecting window.DatadogEventBridge, it silently diverted its events through the bridge, which re-tagged them with the Electron SDK's applicationId — corrupting attribution for our existing web RUM application (events were moved, not duplicated).
  • Untrusted third-party pages in the sandboxed view received window.DatadogEventBridge and could inject arbitrary fabricated RUM events into our account via (3).

Workaround: after session creation, we strip the SDK's preload with session.getPreloadScripts() / unregisterPreloadScript() on every session. This works but relies on unspecified registration-timing behavior.

Requests:

  1. An init/config option to disable renderer bridge injection entirely (main-process-only mode), or scope injection to sessions/partitions matching an allowlist.
  2. Treat allowedWebViewHosts as authoritative in the preload — don't implicitly add location.hostname.
  3. Validate the sender (e.g. event.senderFrame.origin against allowed hosts) in the datadog:bridge-send handler.

Happy to provide more detail. Environment: Electron 43.1.0, SDK 0.6.0, esbuild plugin, macOS.

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