Skip to content

fix(electron): constrain renderer navigation and child windows#739

Merged
meiiie merged 3 commits into
mainfrom
fix/electron-navigation-policy
Jul 11, 2026
Merged

fix(electron): constrain renderer navigation and child windows#739
meiiie merged 3 commits into
mainfrom
fix/electron-navigation-policy

Conversation

@meiiie

@meiiie meiiie commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds one global navigation policy for Recordly BrowserWindow contents before any app window is created.

  • exact renderer reloads remain allowed;
  • renderer-selected destination/query changes are cancelled;
  • server redirects are cancelled;
  • valid, credential-free cross-origin HTTP(S) links open in the system browser;
  • window.open/target=_blank always returns deny, so external pages never become Electron child
    windows;
  • file, data, JavaScript, mail, malformed, credentialed, and custom-scheme targets are never opened
    externally.

The global web-contents-created hook covers the editor, HUD, update toast, source selector, countdown,
and transient source-highlight BrowserWindows without duplicating policy in six constructors.

Motivation

Recordly currently has privileged renderer windows and extension-provided homepage links, but no
top-frame navigation or child-window policy. Navigating a privileged WebContents to external content,
or opening that content inside a new Electron window, creates unnecessary ambient authority.

This follows Electron's official guidance to
limit navigation and new windows.

Type of Change

  • New Feature
  • Bug Fix
  • Refactor / Code Cleanup
  • Documentation Update
  • Other

Related Issue(s)

Architecture remediation Electron-hardening finding. PR #737 establishes the standard quality workflow
and contains the unrelated current-main typecheck baseline fix.

Testing Guide

npx vitest --run electron/navigationPolicy.test.ts electron/mainCjsNormalize.test.mjs
npx biome lint electron/navigationPolicy.ts electron/navigationPolicy.test.ts electron/main.ts
npm test
npx vite build --config vite.config.ts
npm run normalize:electron-main-cjs
npm run smoke:electron-main-cjs

Results:

  • navigation policy: 31/31 tests passed;
  • focused policy/main tests: 35/35 passed;
  • focused Biome lint and relaxed-unused typecheck passed;
  • full Vitest: 97/97 files and 872/872 tests passed;
  • production renderer, Electron main, and preload bundles built successfully;
  • Electron-main normalize and CJS parse smoke passed.

Standard tsc --noEmit reaches only the unrelated unused import on current main, already fixed by
#737. A packaged GUI/device smoke was not run in this source-only environment.

Risk and non-goals

Electron documents that will-navigate does not fire for intentional main-process loadURL/loadFile
calls, so existing startup/fallback loads are unchanged. Exact reload is preserved; renderer query/path
mutation is deliberately fail-closed because those query flags can carry privileged local paths.

This PR does not claim complete Electron or extension isolation. It intentionally defers:

  • origin/window-scoped media and device permissions;
  • migration of extension/media assets away from file://;
  • removal of webSecurity: false and enforcement of CSP;
  • moving third-party extension code out of the editor main world.

Those require separate runtime characterization and compatibility gates.

Checklist

  • I have performed a self-review of my code.
  • Screenshots/videos are not applicable.
  • I added regression coverage for navigation, redirects, child windows, URL parsing, and failures.
  • Independent adversarial review found no blocker.

Summary by CodeRabbit

  • Security

    • Strengthened navigation protection for app windows, including “trusted reload” handling to avoid treating renderer history changes as safe.
    • Blocks redirects and prevents navigation to internal targets when appropriate.
    • Opens only validated external HTTP(S) links in the system browser; denies unsafe or unsupported schemes.
    • Denies unauthorized child window openings and reports failures to open external links.
  • Tests

    • Added comprehensive automated coverage for URL normalization, navigation/redirect handling, trusted reload behavior, and external link opening outcomes.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 793f4975-21b5-4d09-a06b-e13633b08b34

📥 Commits

Reviewing files that changed from the base of the PR and between b175913 and eb6a7fa.

📒 Files selected for processing (2)
  • electron/navigationPolicy.test.ts
  • electron/navigationPolicy.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron/navigationPolicy.test.ts

📝 Walkthrough

Walkthrough

Adds centralized Electron navigation policies, trusted reload tracking, navigation interception, safe external URL handling through the system browser, and hardening for newly created window web contents.

Changes

Navigation hardening

Layer / File(s) Summary
Navigation policy contracts
electron/navigationPolicy.ts
Defines URL normalization, internal-target detection, web contents eligibility, exact reload checks, and safe external-opening error handling.
Navigation interception and trusted reload wiring
electron/navigationPolicy.ts
Blocks redirects and unsafe or internal navigations, preserves trusted exact reloads, denies child windows, and tracks completed navigations.
Main-process integration and validation
electron/main.ts, electron/navigationPolicy.test.ts
Applies hardening to eligible web contents through shell.openExternal, with tests covering classification, handlers, failures, trusted reloads, and wiring.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ElectronApp
  participant WebContents
  participant NavigationPolicy
  participant SystemBrowser
  ElectronApp->>WebContents: web-contents-created
  ElectronApp->>NavigationPolicy: check web contents type
  ElectronApp->>NavigationPolicy: register navigation handlers
  WebContents->>NavigationPolicy: navigation or window-open event
  NavigationPolicy->>WebContents: prevent navigation or deny child window
  NavigationPolicy->>SystemBrowser: open safe external HTTP(S) URL
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: tightening Electron renderer navigation and child-window behavior.
Description check ✅ Passed The description covers purpose, motivation, change type, issue link, testing, and checklist; only the optional screenshots/video section is absent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/electron-navigation-policy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@meiiie
meiiie marked this pull request as ready for review July 11, 2026 03:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@electron/navigationPolicy.ts`:
- Around line 96-100: Replace the use of getCurrentUrl() in the exact-reload
check with a trusted URL snapshot that is not derived from the mutable renderer
location; maintain or update this snapshot only at approved navigation
boundaries, such as did-navigate-in-page, and use it in isExactRendererLocation.
Add a regression test covering replaceState changing the query followed by a
reload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 15d12811-f0a1-4e50-85c3-1590ea1bc972

📥 Commits

Reviewing files that changed from the base of the PR and between 6889765 and b175913.

📒 Files selected for processing (3)
  • electron/main.ts
  • electron/navigationPolicy.test.ts
  • electron/navigationPolicy.ts

Comment thread electron/navigationPolicy.ts Outdated
@meiiie
meiiie merged commit a2e66b0 into main Jul 11, 2026
4 checks passed
@meiiie
meiiie deleted the fix/electron-navigation-policy branch July 11, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant