Thanks to visit codestin.com
Credit goes to github.com

Skip to content

webdriver-probe: route inline fallback through chrome.scripting.executeScript to bypass strict CSP #131

Description

@twschiller

Category

Robustness fix for webdriver-probe-annotate.

Problem

The rule has two delivery paths (see extension/src/rules/webdriver-probe-annotate.ts:19-37):

  1. Primarybackground.ts registers webdriver-probe.js as a dynamic content script with world: "MAIN" + runAt: "document_start". Extension main-world scripts registered via chrome.scripting are exempt from page CSP, so this path lands on subsequent navigations regardless of CSP.
  2. Fallback — the rule's apply() runs at document_idle and creates an inline <script> with textContent = PROBE_SOURCE, then appends it to document.documentElement. Purpose: cover the tab the user was already viewing when they flipped the toggle on, since dynamic registrations only apply to future navigations.

The fallback is blocked on strict script-src origins. Repro: open https://shield-dark-pattern-demo.vercel.app/, toggle webdriver-probe-annotate on. Console:

Refused to execute inline script because it violates the following Content
Security Policy directive 'script-src 'self' 'wasm-unsafe-eval' ...'

Coverage gap: on strict-CSP sites, the current pageview gets no probe. The next navigation is fine.

Proposed solution

Replace the inline-script fallback with a message-to-background that calls chrome.scripting.executeScript:

// content-side
chrome.runtime.sendMessage({ type: "inject-webdriver-probe" });

// background-side
case "inject-webdriver-probe": {
  const tabId = sender.tab?.id;
  if (tabId == null) return;
  await chrome.scripting.executeScript({
    target: { tabId, frameIds: sender.frameId == null ? undefined : [sender.frameId] },
    world: "MAIN",
    func: installProbe,
  });
}

executeScript with world: "MAIN" bypasses page CSP the same way the registered content script does — same primitive, just on-demand. The probe's own __abs_webdriver_probe_installed guard makes re-execution a no-op, so dedupe is already handled.

Considered alternatives

  • CSP detection then skip. Sniff <meta http-equiv="Content-Security-Policy"> or attempt a no-op inline first; abandon if it fails. Quieter console but same coverage gap on the current pageview.
  • Reload the tab on toggle-on. Heavy-handed; surprises the user.
  • Suppress the console violation. Not possible from JS — Chrome emits it before script execution.

Downsides

  • One additional content↔background round-trip per first apply on the active tab. Negligible.
  • Slightly more background-side surface area: a new message type and frame-aware executeScript call.
  • No new permissions — scripting is already in use for the primary path.

Out of scope

  • Catching early-parse reads on the toggle-on tab. The fallback today already runs at document_idle; moving to executeScript doesn't change that. Covering early-parse reads on the existing tab would require a tab reload.

🤖 Generated with Claude Code

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