diff --git a/scripts/ci_drive_gate.py b/scripts/ci_drive_gate.py
index f3ff37c..941345e 100644
--- a/scripts/ci_drive_gate.py
+++ b/scripts/ci_drive_gate.py
@@ -48,9 +48,11 @@ import sys
from playwright.sync_api import sync_playwright
# DOM built on about:blank (no data: URL to re-normalize → no spurious nav).
+# No inline onclick — inline handlers are CSP-sensitive; we wire the listener
+# via addEventListener inside the (function, not eval'd) setup call below.
BODY = (
"
hello-drive
"
- ""
+ ""
""
)
@@ -75,27 +77,33 @@ def _drive(exe: str) -> str:
try:
page = browser.new_page()
page.goto("about:blank") # canonical, never re-navigates
- # Build the DOM + attach the mousemove counter in one shot.
+ # Build the DOM + wire click/mousemove listeners in one shot. Passed
+ # as a FUNCTION (Playwright callFunction, not eval) so a page CSP that
+ # blocks eval()/inline-handlers can't break the gate. All evaluates
+ # below are arrow functions for the same reason.
page.evaluate(
- "(html) => { document.body.innerHTML = html;"
+ "(html) => {"
+ " document.body.innerHTML = html;"
+ " document.getElementById('b').addEventListener('click', () => { window.__clicked = 1; });"
" window.__moves = 0;"
- " window.addEventListener('mousemove', () => { window.__moves++; }); }",
+ " window.addEventListener('mousemove', () => { window.__moves++; });"
+ "}",
BODY,
)
- ua = page.evaluate("navigator.userAgent")
- webdriver = page.evaluate("navigator.webdriver")
+ ua = page.evaluate("() => navigator.userAgent")
+ webdriver = page.evaluate("() => navigator.webdriver")
text = page.evaluate("() => document.getElementById('x').textContent")
# firefox-2 / issue-#9 catcher: real mouse + keyboard over juggler.
page.wait_for_selector("#b")
page.mouse.move(20, 20)
page.mouse.move(120, 90) # exercises synthesizeMouseEvent path
- page.click("#b") # mousedown/up/click → onclick fires
+ page.click("#b") # mousedown/up/click → listener fires
page.click("#inp")
page.keyboard.type("ok")
- clicked = page.evaluate("window.__clicked")
- moves = page.evaluate("window.__moves")
+ clicked = page.evaluate("() => window.__clicked")
+ moves = page.evaluate("() => window.__moves")
typed = page.evaluate("() => document.getElementById('inp').value")
# stealth-determinism catcher: identical draw → identical dataURL.
@@ -103,8 +111,8 @@ def _drive(exe: str) -> str:
canvas_b = page.evaluate(CANVAS_DRAW)
# BotD navigator-surface tells (proxy-free subset).
- langs = page.evaluate("navigator.languages.length")
- plugins = page.evaluate("navigator.plugins instanceof PluginArray")
+ langs = page.evaluate("() => navigator.languages.length")
+ plugins = page.evaluate("() => navigator.plugins instanceof PluginArray")
finally:
browser.close()