Audit metadata
- Priority: P1
- Estimated effort: M
- Implementation risk: MED
- Category: bug
- Evidence baseline:
07be5be7ce69bea0c3118744ab90d148b010fce0 (origin/main on 2026-07-17)
Dependencies
- P1 proposal 040 — Enforce DNS-pinned browser policy across redirects and subresources. Included in the current P1 issue wave.
Description and impact
On desktop, the visible browser is an Electron <webview>, while agent browser
tools drive a separate server-side Chromium page. The user can be looking at one
URL/state while the agent reads or clicks another, contradicting the UI promise
that they share a surface. The web build already uses the CDP screencast; using
it everywhere removes duplicated state and makes the security policy auditable.
Current state
frontend/src/features/agent/ui/agent-browser.tsx:31-45 defines a custom
Electron webview type and lines 122-166 dispatch desktop navigation to it.
agent-browser.tsx:281-311 renders <webview> in Electron and
ScreencastSurface on web, despite describing one agent-driven surface.
services/agent-runtime/src/browser-host/browser-host.ts:1-7 identifies the
CDP host as the replacement for the old webview.
frontend/desktop/logic/window-manager.ts:20-34 enables webviewTag: true;
frontend/desktop/logic/security.ts contains guest-attachment hardening needed
only while webviews exist.
agent-browser-panel.tsx and tools/browser-url.ts accept file:// for the
desktop webview. The server browser must not inherit arbitrary disk access;
project files already have Files/canvas viewers.
Steps to reproduce
- Launch the packaged desktop app and navigate the visible browser pane to a
loopback test page A.
- In the same agent session, invoke a browser tool that navigates or reads a
different loopback test page B.
- Compare the URL and DOM reported by the tool with the page still visible in
the desktop pane.
Expected: the user and agent act on the same protected page and observe the same
URL/state. Actual: the desktop pane remains in its Electron webview while the
agent tool operates a separate server-side Chromium page.
Verification commands
| Purpose |
Command |
Expected on success |
| Browser regression |
npm run test:frontend:regression -- agent-browser-tools-regressions |
shared-surface cases pass |
| Frontend tests |
npm --prefix frontend run test |
all pass |
| Frontend quality |
npm --prefix frontend run check:quality |
exit 0 |
| Full integration |
npm run test:integration |
all pass |
| Desktop package |
npm --prefix frontend run desktop:dist |
production app built |
Scope
In scope:
frontend/src/features/agent/ui/agent-browser.tsx
frontend/src/features/agent/ui/agent-browser-effects.ts
frontend/src/features/agent/ui/agent-browser-panel.tsx
frontend/src/features/agent/ui/agent-browser-screencast.tsx
frontend/src/features/agent/tools/browser-url.ts
- File-link routing caller only if needed to open the existing Files/canvas view
frontend/desktop/logic/window-manager.ts
frontend/desktop/logic/security.ts
- Focused frontend/regression tests
Out of scope:
- Browser session isolation; audit proposal 042 follows this issue.
- Reintroducing file URLs through CDP or serving arbitrary disk files over HTTP.
- Browser networking policy changes beyond consuming audit proposal 040.
- Redesigning the browser toolbar or Files/canvas viewers.
Solution design
Render ScreencastSurface in live mode for every platform. All toolbar, address,
frame, viewport, and input requests use the same browser-host endpoints that Pi
tools call. Remove webview refs/types/effects and the isElectron branch. Set
webviewTag: false or remove it, and delete guest-only security handlers once no
other webview consumer exists. Reject file:// in browser navigation; file links
should open the existing workspace Files/canvas viewer when inside the permitted
workspace, otherwise show a clear unsupported message.
Implementation plan
Step 1: Characterize cross-surface divergence
Add a regression that navigates through the visible pane, calls agent get-url,
then navigates through the agent and polls visible state. It must expose the
current desktop divergence and pass on the web screencast path.
Verify: the new test fails only for the old desktop webview branch before implementation.
Step 2: Remove the webview rendering/effect path
Delete WebviewElement, refs, initial webview state, Electron navigation
branches, and the <webview> render. Drive back/forward/reload and location
updates through the existing host/screencast APIs on every platform. Keep reader
fallback behavior unchanged.
Verify: rg -n 'webview|WebviewElement|webviewRef|initialWebviewUrl' frontend/src/features/agent returns no live browser-surface matches; focused tests pass.
Step 3: Remove desktop guest capability
Disable webviewTag in window-manager.ts. Remove will-attach-webview and
guest-only code only after rg proves no other product surface uses a webview.
Retain all main-window navigation, permission, sandbox, and origin hardening.
Verify: rg -n 'webviewTag: true|will-attach-webview|<webview' frontend returns no matches, while desktop security tests pass.
Step 4: Route files away from the browser
Remove file URL normalization/acceptance from browser panel code. Use the
existing workspace-relative file opening action for eligible file links and a
clear error for paths outside its boundary. Do not add an HTTP file-serving route.
Verify: tests assert file:// is rejected by browser navigation, in-workspace
links open Files/canvas, and out-of-workspace links do not read or render data.
Step 5: Prove one visible/tool state machine
Test navigate, URL/title, back/forward/reload, click/fill/scroll, viewport, and
reader fallback from both visible and tool callers against the same page/session.
Verify: browser regression suite passes with no platform-specific expected URL.
Step 6: Run gates and reinstall desktop
Run all frontend/repository checks, build desktop:dist, replace
/Applications/Local Studio.app using the exact AGENTS.md sequence, relaunch,
and query the installed /api/desktop-health endpoint.
Verify: npm --prefix frontend run check:quality && npm --prefix frontend run test && npm run check && npm run test:integration && npm --prefix frontend run desktop:dist → all exit 0; installed desktop health is HTTP 200 with ok: true.
Test plan
- Visible navigation is returned by agent
get-url/get-text and agent navigation
updates visible frame/address.
- Back/forward/reload and pointer/keyboard input affect that same history/page.
- Web and packaged desktop use identical endpoint flow.
- Reader fallback still activates when Chromium is unavailable.
- Browser rejects file URLs; workspace file action enforces its root boundary.
- Static regression proves no webview capability remains enabled.
Acceptance criteria
Risks and stop conditions
Stop and report if:
- Another required product feature still uses Electron webviews.
- audit proposal 040 is not complete enough to make CDP the sole network surface.
- The existing Files/canvas action cannot enforce workspace boundaries.
- CDP input/frame behavior cannot meet an existing accessibility requirement.
- Desktop reinstall or health verification cannot complete.
Maintenance considerations
Do not add platform-specific browser state again. Reviewers should manually
observe a user navigation followed by an agent read in the packaged app. Plan
042 must key this unified surface by agent session before concurrent sessions are
considered isolated.
Generated from Local Studio 2.0 main-branch audit proposal 041.
Audit metadata
07be5be7ce69bea0c3118744ab90d148b010fce0(origin/mainon 2026-07-17)Dependencies
Description and impact
On desktop, the visible browser is an Electron
<webview>, while agent browsertools drive a separate server-side Chromium page. The user can be looking at one
URL/state while the agent reads or clicks another, contradicting the UI promise
that they share a surface. The web build already uses the CDP screencast; using
it everywhere removes duplicated state and makes the security policy auditable.
Current state
frontend/src/features/agent/ui/agent-browser.tsx:31-45defines a customElectron webview type and lines 122-166 dispatch desktop navigation to it.
agent-browser.tsx:281-311renders<webview>in Electron andScreencastSurfaceon web, despite describing one agent-driven surface.services/agent-runtime/src/browser-host/browser-host.ts:1-7identifies theCDP host as the replacement for the old webview.
frontend/desktop/logic/window-manager.ts:20-34enableswebviewTag: true;frontend/desktop/logic/security.tscontains guest-attachment hardening neededonly while webviews exist.
agent-browser-panel.tsxandtools/browser-url.tsacceptfile://for thedesktop webview. The server browser must not inherit arbitrary disk access;
project files already have Files/canvas viewers.
Steps to reproduce
loopback test page A.
different loopback test page B.
the desktop pane.
Expected: the user and agent act on the same protected page and observe the same
URL/state. Actual: the desktop pane remains in its Electron webview while the
agent tool operates a separate server-side Chromium page.
Verification commands
npm run test:frontend:regression -- agent-browser-tools-regressionsnpm --prefix frontend run testnpm --prefix frontend run check:qualitynpm run test:integrationnpm --prefix frontend run desktop:distScope
In scope:
frontend/src/features/agent/ui/agent-browser.tsxfrontend/src/features/agent/ui/agent-browser-effects.tsfrontend/src/features/agent/ui/agent-browser-panel.tsxfrontend/src/features/agent/ui/agent-browser-screencast.tsxfrontend/src/features/agent/tools/browser-url.tsfrontend/desktop/logic/window-manager.tsfrontend/desktop/logic/security.tsOut of scope:
Solution design
Render
ScreencastSurfacein live mode for every platform. All toolbar, address,frame, viewport, and input requests use the same browser-host endpoints that Pi
tools call. Remove webview refs/types/effects and the
isElectronbranch. SetwebviewTag: falseor remove it, and delete guest-only security handlers once noother webview consumer exists. Reject
file://in browser navigation; file linksshould open the existing workspace Files/canvas viewer when inside the permitted
workspace, otherwise show a clear unsupported message.
Implementation plan
Step 1: Characterize cross-surface divergence
Add a regression that navigates through the visible pane, calls agent
get-url,then navigates through the agent and polls visible state. It must expose the
current desktop divergence and pass on the web screencast path.
Verify: the new test fails only for the old desktop webview branch before implementation.
Step 2: Remove the webview rendering/effect path
Delete
WebviewElement, refs, initial webview state, Electron navigationbranches, and the
<webview>render. Drive back/forward/reload and locationupdates through the existing host/screencast APIs on every platform. Keep reader
fallback behavior unchanged.
Verify:
rg -n 'webview|WebviewElement|webviewRef|initialWebviewUrl' frontend/src/features/agentreturns no live browser-surface matches; focused tests pass.Step 3: Remove desktop guest capability
Disable
webviewTaginwindow-manager.ts. Removewill-attach-webviewandguest-only code only after
rgproves no other product surface uses a webview.Retain all main-window navigation, permission, sandbox, and origin hardening.
Verify:
rg -n 'webviewTag: true|will-attach-webview|<webview' frontendreturns no matches, while desktop security tests pass.Step 4: Route files away from the browser
Remove file URL normalization/acceptance from browser panel code. Use the
existing workspace-relative file opening action for eligible file links and a
clear error for paths outside its boundary. Do not add an HTTP file-serving route.
Verify: tests assert
file://is rejected by browser navigation, in-workspacelinks open Files/canvas, and out-of-workspace links do not read or render data.
Step 5: Prove one visible/tool state machine
Test navigate, URL/title, back/forward/reload, click/fill/scroll, viewport, and
reader fallback from both visible and tool callers against the same page/session.
Verify: browser regression suite passes with no platform-specific expected URL.
Step 6: Run gates and reinstall desktop
Run all frontend/repository checks, build
desktop:dist, replace/Applications/Local Studio.appusing the exactAGENTS.mdsequence, relaunch,and query the installed
/api/desktop-healthendpoint.Verify:
npm --prefix frontend run check:quality && npm --prefix frontend run test && npm run check && npm run test:integration && npm --prefix frontend run desktop:dist→ all exit 0; installed desktop health is HTTP 200 withok: true.Test plan
get-url/get-textand agent navigationupdates visible frame/address.
Acceptance criteria
<webview>, webview ref,webviewTag: true, or guest handler remains.Risks and stop conditions
Stop and report if:
Maintenance considerations
Do not add platform-specific browser state again. Reviewers should manually
observe a user navigation followed by an agent read in the packaged app. Plan
042 must key this unified surface by agent session before concurrent sessions are
considered isolated.
Generated from Local Studio 2.0 main-branch audit proposal 041.