describe the bug
The POST /connections/browsers/owned-default/eval endpoint reports success but the supplied JS does not actually run against the page document. The same JS works correctly against user-browser/eval.
This breaks the documented "escape hatch when navigate + snapshot aren't enough" use case for the owned webview, and silently — there's no error to catch.
to reproduce
# 1. load a real page in owned-default
curl -sH "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-XPOST http://localhost:3030/connections/browsers/owned-default/navigate \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
sleep 3
# 2. attempt the simplest possible mutation via eval
curl -sH "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
-XPOST http://localhost:3030/connections/browsers/owned-default/eval \
-H "Content-Type: application/json" \
-d '{"code": "document.title = \"changed\";"}'
# => {"error":null,"result":null,"success":true}
# 3. snapshot — title is still "Example Domain", not "changed"
curl -sH "Authorization: Bearer $SCREENPIPE_LOCAL_API_KEY" \
http://localhost:3030/connections/browsers/owned-default/snapshot
# => {"title":"Example Domain","tree":" [h1] Example Domain ...","url":"https://example.com/"}
The exact same sequence against user-browser/eval mutates the title as expected, and is what I'm using today to drive github comment + issue submission flows in this repo (PR #3660 comment, issue #3674).
expected behavior
Either:
- The JS executes against the page document and
document.title becomes "changed" on the next snapshot, or
- If eval runs in an isolated world / sandboxed context by design, the response should make that explicit (e.g.
{"success": false, "error": "eval_not_supported_in_owned_default"} or a documented note that mutations don't propagate) rather than success:true with a silent no-op.
The current behavior is the worst of both worlds: callers think it worked, snapshots reveal it didn't, debugging takes a while because the response looks healthy.
also: result is always null even for pure expressions
Even simple non-mutating evals like '1+1' or 'navigator.userAgent' return {"result": null} rather than the value of the expression. So eval can't be used as a read-side probe either. (Possibly related to the same execution-context issue, possibly separate — flagging in case it helps triage.)
system info
- os: macOS 26.5 (25F71), Apple Silicon (MacBookPro18,3)
- screenpipe version: 2.4.288
- webview backend per binary strings: WKWebView via tauri/wry
additional context
Discovered while investigating fingerprint-surface claims from https://github.com/pleasedodisturb/web-agent-comparison — a benchmark of 7 browser-automation MCPs scored on 8 weighted dimensions, including a finding that headless Chromium leaks three independently fingerprintable signals by default (HeadlessChrome/ UA, SwiftShader WebGL, navigator.plugins.length=0).
I wanted to verify whether owned-default was leak-vulnerable, which required eval-ing navigator.userAgent / navigator.plugins.length / WebGL debug-renderer-info against the page. Eval silently no-op'd, which (a) blocked the investigation, (b) turned out to be the more interesting bug.
Side note for the fingerprint question once eval is fixed: based on strings analysis of the shipped binary (WKWebView, WKWebViewConfiguration, tauri_runtime_wry), owned-default is WKWebView via wry on macOS — not headless Chromium — so the three Chromium-specific leaks above don't apply on this platform. Equivalent per-platform investigation would still be worth doing for Linux (webkit2gtk) and Windows (WebView2) builds, but that's a separate issue and depends on this one being fixed first.
Happy to test a patch.
describe the bug
The
POST /connections/browsers/owned-default/evalendpoint reports success but the supplied JS does not actually run against the page document. The same JS works correctly againstuser-browser/eval.This breaks the documented "escape hatch when navigate + snapshot aren't enough" use case for the owned webview, and silently — there's no error to catch.
to reproduce
The exact same sequence against
user-browser/evalmutates the title as expected, and is what I'm using today to drive github comment + issue submission flows in this repo (PR #3660 comment, issue #3674).expected behavior
Either:
document.titlebecomes"changed"on the next snapshot, or{"success": false, "error": "eval_not_supported_in_owned_default"}or a documented note that mutations don't propagate) rather thansuccess:truewith a silent no-op.The current behavior is the worst of both worlds: callers think it worked, snapshots reveal it didn't, debugging takes a while because the response looks healthy.
also:
resultis alwaysnulleven for pure expressionsEven simple non-mutating evals like
'1+1'or'navigator.userAgent'return{"result": null}rather than the value of the expression. So eval can't be used as a read-side probe either. (Possibly related to the same execution-context issue, possibly separate — flagging in case it helps triage.)system info
additional context
Discovered while investigating fingerprint-surface claims from https://github.com/pleasedodisturb/web-agent-comparison — a benchmark of 7 browser-automation MCPs scored on 8 weighted dimensions, including a finding that headless Chromium leaks three independently fingerprintable signals by default (
HeadlessChrome/UA, SwiftShader WebGL,navigator.plugins.length=0).I wanted to verify whether
owned-defaultwas leak-vulnerable, which required eval-ingnavigator.userAgent/navigator.plugins.length/ WebGL debug-renderer-info against the page. Eval silently no-op'd, which (a) blocked the investigation, (b) turned out to be the more interesting bug.Side note for the fingerprint question once eval is fixed: based on strings analysis of the shipped binary (
WKWebView,WKWebViewConfiguration,tauri_runtime_wry),owned-defaultis WKWebView via wry on macOS — not headless Chromium — so the three Chromium-specific leaks above don't apply on this platform. Equivalent per-platform investigation would still be worth doing for Linux (webkit2gtk) and Windows (WebView2) builds, but that's a separate issue and depends on this one being fixed first.Happy to test a patch.