Skip to content

security(CORE-1129): validate ipcMain senders against allowlist#3315

Open
jeanfbrito wants to merge 5 commits into
masterfrom
security/CORE-1129-ipc-validation
Open

security(CORE-1129): validate ipcMain senders against allowlist#3315
jeanfbrito wants to merge 5 commits into
masterfrom
security/CORE-1129-ipc-validation

Conversation

@jeanfbrito
Copy link
Copy Markdown
Member

@jeanfbrito jeanfbrito commented Apr 29, 2026

Summary

  • Adds src/ipc/validateSender.ts with isTrustedSender(sender, allow) helper and registerWindowGetter for local windows. Server-webview channels validate sender origin against state.servers in Redux; local-window channels (log-viewer, video-call) validate by WebContents instance identity via registered getters, covering both the window's own renderer and webviews it hosts.
  • Applies the helper to all four audited entry points (see table below). Each handler rejects untrusted senders with a console.warn and an early return / null returnValue.
  • log-viewer-window/get-server-tag now derives the server origin from event.sender.getURL() and ignores the renderer-supplied origin parameter entirely.

Channel allowlist table

Channel File Allowed classes
refresh-supported-versions src/servers/supportedVersions/main.ts server-webview
video-call-window/get-provider-sync src/videoCallWindow/ipc.ts video-call
video-call-window/screen-sharing-source-responded src/videoCallWindow/ipc.ts video-call
log-viewer-window/get-server-tag src/logging/index.ts log-viewer

How the wrapper enforces defaults

The generic handle wrapper in src/ipc/main.ts is not modified in this PR — only the four directly-audited call sites are hardened. The wrapper default (server-webview for all wrapped channels) is out of scope per the brief: mass-migrating all 143+ channels is a separate tracked item.

What is NOT in scope

  • CSP changes (separate PR)
  • secureKeyboardEntry (separate PR)
  • Renderer preload / contextBridge surface — unchanged
  • nodeIntegration / contextIsolation toggles
  • Generic wrapper channel-level allowlist (143-channel migration)

Test plan

  • yarn lint — passes clean
  • npx tsc --noEmit — no errors
  • yarn test — 227 tests, 18 suites, all pass
  • src/ipc/main/validateSender.spec.ts — 14 new tests covering all SenderClass variants (positive + negative), hosted-webview case, multi-class allow list, null getter, and invalid URL

Summary by CodeRabbit

  • Security Improvements

    • Strengthened IPC sender validation across main window, log viewer, video-call, and server-version endpoints; renderer-provided origins are ignored and untrusted senders are rejected.
    • IPC handlers now derive sender identity from actual sender state and reject mismatches or impersonation attempts.
  • Bug Fixes

    • Fixed screen-sharing response flow to ignore untrusted replies and only accept the first trusted response.
  • Tests

    • Added comprehensive tests covering sender-trust rules, multi-class allowlists, window/webview scenarios, and IPC listener-removal robustness.

Add isTrustedSender helper and apply it to all audited ipcMain handlers.
Server-webview channels validate sender origin against Redux state.servers;
local-window channels validate by WebContents instance identity (via
registered getters). log-viewer-window/get-server-tag now derives origin
from event.sender.getURL() and ignores the renderer-supplied parameter.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds IPC sender validation with a per-class window getter registry and an isTrustedSender check (classes: server-webview, main-window, log-viewer, video-call). Integrates checks into several IPC handlers and registers getters for main/log-viewer windows.

Changes

Cohort / File(s) Summary
Core sender validation + tests
src/ipc/validateSender.ts, src/ipc/main/validateSender.spec.ts
Adds SenderClass type, registerWindowGetter() and isTrustedSender() implementing server-webview origin checks and registered-window identity/host checks. Adds comprehensive Jest tests covering classes, allowlists, origin parsing edge cases, and IPC listener removal behavior.
Log viewer integration
src/logViewerWindow/ipc.ts, src/logging/index.ts
Registers 'log-viewer' getter; log-viewer-window/get-server-tag now authenticates via isTrustedSender(), derives URL from event.sender.getURL(), and rejects untrusted senders (warn + empty return).
Video call integration
src/videoCallWindow/ipc.ts
Enforces isTrustedSender for video-call flows: get-provider-sync returns null for untrusted senders; screen-share response handling switched from ipcMain.once to ipcMain.on and validates responses until a trusted sender is received, then forwards and removes listener.
Main window registration & tests
src/ui/main/rootWindow.ts, src/ui/main/rootWindow.spec.ts
Registers 'main-window' getter after root BrowserWindow creation and adds tests verifying registration and getter behavior.
Supported-versions protection
src/servers/supportedVersions/main.ts
refresh-supported-versions IPC handler now validates event.sender as main-window and exits with a warning when untrusted.

Sequence Diagram(s)

sequenceDiagram
    participant Sender as IPC Sender (WebContents)
    participant Handler as IPC Handler
    participant Validator as isTrustedSender()
    participant Store as Redux Store
    participant Registry as Window Registry

    Sender->>Handler: send IPC message
    Handler->>Validator: isTrustedSender(sender, allow)

    alt server-webview check
        Validator->>Sender: ensure type == "webview"
        Validator->>Sender: call sender.getURL()
        Validator->>Store: select servers list
        Store-->>Validator: return server URLs
        Validator->>Validator: compare origins
    else local-window check
        Validator->>Registry: call registered getter for class
        Registry-->>Validator: return trusted WebContents
        Validator->>Validator: compare sender.id or sender.hostWebContents.id
    end

    alt trusted
        Validator-->>Handler: true
        Handler->>Handler: process request
        Handler-->>Sender: respond
    else untrusted
        Validator-->>Handler: false
        Handler->>Handler: log warning / exit early
        Handler-->>Sender: return empty/null
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly identifies the main security-focused change: adding IPC sender validation against an allowlist mechanism. It is specific, relates directly to the core objective, and uses appropriate commit message format.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • CORE-1129: Request failed with status code 401

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
Review rate limit: 5/8 reviews remaining, refill in 19 minutes and 16 seconds.

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/logging/index.ts (1)

286-289: Prefer origin equality instead of URL prefix matching.

startsWith can misclassify look-alike URLs. Use new URL(...).origin equality for robust matching.

♻️ Proposed refactor
- const matchedServer = servers.find(
-   (s: any) =>
-     s.url && senderUrl.startsWith(s.url.replace(/\/$/, ''))
- );
+ const senderOrigin = new URL(senderUrl).origin;
+ const matchedServer = servers.find((s: any) => {
+   try {
+     return s.url && new URL(s.url).origin === senderOrigin;
+   } catch {
+     return false;
+   }
+ });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/logging/index.ts` around lines 286 - 289, The current servers.find that
sets matchedServer using startsWith on s.url (in the matchedServer assignment)
can misclassify similar URLs; change the logic to compare origins by
constructing URL objects and comparing new URL(senderUrl).origin === new
URL(s.url).origin (handle possible trailing slashes and wrap in try/catch to
guard bad URLs) instead of using senderUrl.startsWith(s.url.replace(/\/$/, ''))
so matching is done by origin equality.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/servers/supportedVersions/main.ts`:
- Around line 509-517: The handler for 'refresh-supported-versions' only
verifies sender type but doesn't bind the serverUrl to the sender origin; modify
the ipcMain.handle callback so after isTrustedSender succeeds you derive the
origin from event.sender.getURL() (or parse event.sender.getURL() into an
origin) and either validate that the provided serverUrl has the same origin or
replace serverUrl with the sender origin before calling
updateSupportedVersionsData; update the logic around isTrustedSender,
event.sender.getURL(), and updateSupportedVersionsData to enforce origin
binding.

In `@src/videoCallWindow/ipc.ts`:
- Around line 311-317: The early return when isTrustedSender(onceEvent.sender,
['video-call']) fails leaves the caller waiting; before returning, notify the
original caller (callerWebContents) with the
'video-call-window/screen-sharing-source-responded' channel indicating
rejection/failure and include any error reason, then safely return. Locate the
check around isTrustedSender and onceEvent.sender and ensure you call
callerWebContents.send('video-call-window/screen-sharing-source-responded', {
success: false, error: 'untrusted-sender' }) (or equivalent payload) before the
existing return so the caller-side listener is always completed.

---

Nitpick comments:
In `@src/logging/index.ts`:
- Around line 286-289: The current servers.find that sets matchedServer using
startsWith on s.url (in the matchedServer assignment) can misclassify similar
URLs; change the logic to compare origins by constructing URL objects and
comparing new URL(senderUrl).origin === new URL(s.url).origin (handle possible
trailing slashes and wrap in try/catch to guard bad URLs) instead of using
senderUrl.startsWith(s.url.replace(/\/$/, '')) so matching is done by origin
equality.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ea7440f-fc3e-443c-9e17-9a797ab7e144

📥 Commits

Reviewing files that changed from the base of the PR and between e1fe77e and 67a4945.

📒 Files selected for processing (6)
  • src/ipc/main/validateSender.spec.ts
  • src/ipc/validateSender.ts
  • src/logViewerWindow/ipc.ts
  • src/logging/index.ts
  • src/servers/supportedVersions/main.ts
  • src/videoCallWindow/ipc.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (windows-latest)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from @rocket.chat/fuselage for all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments

Files:

  • src/logViewerWindow/ipc.ts
  • src/servers/supportedVersions/main.ts
  • src/ipc/main/validateSender.spec.ts
  • src/logging/index.ts
  • src/videoCallWindow/ipc.ts
  • src/ipc/validateSender.ts
**/*.spec.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use *.spec.ts file naming convention for Renderer process tests

Files:

  • src/ipc/main/validateSender.spec.ts
**/*.{spec,main.spec}.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{spec,main.spec}.ts: Tests must run and pass on Windows, macOS, and Linux CI environments — always verify cross-platform compatibility
Only mock Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) when defensive coding with optional chaining isn't possible

Files:

  • src/ipc/main/validateSender.spec.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: Ram-sah19
Repo: RocketChat/Rocket.Chat.Electron PR: 3254
File: .github/workflows/build-release.yml:80-94
Timestamp: 2026-03-11T06:38:40.426Z
Learning: In the RocketChat/Rocket.Chat.Electron repository, the issues flagged in `.github/workflows/build-release.yml` (e.g., `node12` runtime in the release action and missing `snapcraft_token` input), i18n files, and `electron-builder.json` are pre-existing in the `develop` branch and are pulled in during merge conflict resolution. Do not flag these as new issues introduced by PRs that only modify `src/injected.ts` and `src/ui/main/rootWindow.ts`.
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.{spec,main.spec}.ts : Only mock Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) when defensive coding with optional chaining isn't possible

Applied to files:

  • src/ipc/main/validateSender.spec.ts
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.spec.ts : Use *.spec.ts file naming convention for Renderer process tests

Applied to files:

  • src/ipc/main/validateSender.spec.ts
🔇 Additional comments (5)
src/ipc/validateSender.ts (1)

41-89: Good centralized trust gate with deny-by-default behavior.

The split between server-webview origin checks and local-window identity checks is clean and security-oriented.

src/logViewerWindow/ipc.ts (1)

163-163: Window getter registration is correctly wired.

This ensures sender validation can resolve the active log viewer webContents at call time.

src/videoCallWindow/ipc.ts (1)

266-266: video-call getter registration looks correct.

This provides the expected trusted webContents identity source for validation.

src/ipc/main/validateSender.spec.ts (1)

45-201: Great coverage for the new sender trust model.

The suite exercises class-based trust, origin matching, hosted webview behavior, and mixed allowlists with useful negative cases.

src/logging/index.ts (1)

272-280: No action required—the allowlist is correct.

The ['log-viewer'] restriction on Line 273 correctly matches the only caller of this IPC. The log-viewer window is the only process that (1) imports the preload, (2) has processContext === 'renderer:webview', and (3) triggers the IPC call. Other webviews do not import the preload and rely on the executeJavaScript injection fallback instead (see the TODO at line 347), so they never attempt this IPC route and are unaffected by the allowlist.

Comment on lines +509 to 517
ipcMain.handle('refresh-supported-versions', async (event, serverUrl) => {
if (!isTrustedSender(event.sender, ['server-webview'])) {
console.warn(
'[ipc] refresh-supported-versions: rejected untrusted sender',
event.sender.getURL()
);
return;
}
updateSupportedVersionsData(serverUrl);
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.

⚠️ Potential issue | 🟠 Major

Bind serverUrl to the authenticated sender origin.

Right now, Line 510 only checks sender class. A trusted webview can still trigger refreshes for other servers by passing a different serverUrl. Add origin binding before calling updateSupportedVersionsData.

🔒 Proposed fix
 ipcMain.handle('refresh-supported-versions', async (event, serverUrl) => {
   if (!isTrustedSender(event.sender, ['server-webview'])) {
     console.warn(
       '[ipc] refresh-supported-versions: rejected untrusted sender',
       event.sender.getURL()
     );
     return;
   }
+
+  try {
+    const senderOrigin = new URL(event.sender.getURL()).origin;
+    const requestedOrigin = new URL(serverUrl).origin;
+    if (senderOrigin !== requestedOrigin) {
+      console.warn(
+        '[ipc] refresh-supported-versions: rejected origin mismatch',
+        senderOrigin,
+        requestedOrigin
+      );
+      return;
+    }
+  } catch {
+    return;
+  }
+
   updateSupportedVersionsData(serverUrl);
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ipcMain.handle('refresh-supported-versions', async (event, serverUrl) => {
if (!isTrustedSender(event.sender, ['server-webview'])) {
console.warn(
'[ipc] refresh-supported-versions: rejected untrusted sender',
event.sender.getURL()
);
return;
}
updateSupportedVersionsData(serverUrl);
ipcMain.handle('refresh-supported-versions', async (event, serverUrl) => {
if (!isTrustedSender(event.sender, ['server-webview'])) {
console.warn(
'[ipc] refresh-supported-versions: rejected untrusted sender',
event.sender.getURL()
);
return;
}
try {
const senderOrigin = new URL(event.sender.getURL()).origin;
const requestedOrigin = new URL(serverUrl).origin;
if (senderOrigin !== requestedOrigin) {
console.warn(
'[ipc] refresh-supported-versions: rejected origin mismatch',
senderOrigin,
requestedOrigin
);
return;
}
} catch {
return;
}
updateSupportedVersionsData(serverUrl);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/servers/supportedVersions/main.ts` around lines 509 - 517, The handler
for 'refresh-supported-versions' only verifies sender type but doesn't bind the
serverUrl to the sender origin; modify the ipcMain.handle callback so after
isTrustedSender succeeds you derive the origin from event.sender.getURL() (or
parse event.sender.getURL() into an origin) and either validate that the
provided serverUrl has the same origin or replace serverUrl with the sender
origin before calling updateSupportedVersionsData; update the logic around
isTrustedSender, event.sender.getURL(), and updateSupportedVersionsData to
enforce origin binding.

Comment thread src/videoCallWindow/ipc.ts Outdated
Comment on lines +311 to +317
if (!isTrustedSender(onceEvent.sender, ['video-call'])) {
console.warn(
'[ipc] video-call-window/screen-sharing-source-responded: rejected untrusted sender',
onceEvent.sender.getURL()
);
return;
}
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.

⚠️ Potential issue | 🟠 Major

Always complete the screen-sharing response path on rejection.

When Line 311 fails trust, the code returns without notifying callerWebContents. The caller-side listener can hang waiting for 'video-call-window/screen-sharing-source-responded'.

🛠️ Proposed fix
 if (!isTrustedSender(onceEvent.sender, ['video-call'])) {
   console.warn(
     '[ipc] video-call-window/screen-sharing-source-responded: rejected untrusted sender',
     onceEvent.sender.getURL()
   );
+  if (!callerWebContents.isDestroyed()) {
+    callerWebContents.send(
+      'video-call-window/screen-sharing-source-responded',
+      null
+    );
+  }
   return;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!isTrustedSender(onceEvent.sender, ['video-call'])) {
console.warn(
'[ipc] video-call-window/screen-sharing-source-responded: rejected untrusted sender',
onceEvent.sender.getURL()
);
return;
}
if (!isTrustedSender(onceEvent.sender, ['video-call'])) {
console.warn(
'[ipc] video-call-window/screen-sharing-source-responded: rejected untrusted sender',
onceEvent.sender.getURL()
);
if (!callerWebContents.isDestroyed()) {
callerWebContents.send(
'video-call-window/screen-sharing-source-responded',
null
);
}
return;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/videoCallWindow/ipc.ts` around lines 311 - 317, The early return when
isTrustedSender(onceEvent.sender, ['video-call']) fails leaves the caller
waiting; before returning, notify the original caller (callerWebContents) with
the 'video-call-window/screen-sharing-source-responded' channel indicating
rejection/failure and include any error reason, then safely return. Locate the
check around isTrustedSender and onceEvent.sender and ensure you call
callerWebContents.send('video-call-window/screen-sharing-source-responded', {
success: false, error: 'untrusted-sender' }) (or equivalent payload) before the
existing return so the caller-side listener is always completed.

…ons and log tag

refresh-supported-versions is invoked from ServerPane (root renderer /
main window), not from a server webview — change allowlist from
['server-webview'] to ['main-window'].

log-viewer-window/get-server-tag is sent by logging/preload.ts only
when processContext === 'renderer:webview' (server webviews hosted in
the main window), not by the log-viewer window — change allowlist from
['log-viewer'] to ['server-webview'].

Add test suites for both corrected allowlists (6 new cases, 20 total).
@jeanfbrito
Copy link
Copy Markdown
Member Author

Codex review findings addressed (commit 954be66)

Two P2 allowlist regressions identified in Codex review have been corrected:

1. refresh-supported-versions (src/servers/supportedVersions/main.ts:510)

  • Was: ['server-webview'] — incorrect, this channel is invoked from ServerPane.tsx in the root renderer (main window) via the window online event handler
  • Fixed: ['main-window']

2. log-viewer-window/get-server-tag (src/logging/index.ts:273)

  • Was: ['log-viewer'] — incorrect, this channel is sent by src/logging/preload.ts only when processContext === 'renderer:webview' (server webviews hosted in the main window)
  • Fixed: ['server-webview']

6 new test cases added to src/ipc/main/validateSender.spec.ts covering both corrected allowlists. All 20 tests pass, lint clean, typecheck clean.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@src/logging/index.ts`:
- Around line 274-277: The current rejection log prints the full sender URL via
event.sender.getURL(), which may leak sensitive query/fragment data; change the
console.warn in the 'ipc' log-viewer-window/get-server-tag rejection path to log
a normalized origin or the sender id instead: obtain the URL string from
event.sender.getURL(), parse it with the URL constructor to extract .origin
(wrapped in a try/catch to handle invalid URLs), and fall back to
event.sender.id when parsing fails; then pass that sanitized value to
console.warn rather than the raw URL.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3cd0e062-ac98-4540-a774-963914450e3e

📥 Commits

Reviewing files that changed from the base of the PR and between 67a4945 and 954be66.

📒 Files selected for processing (3)
  • src/ipc/main/validateSender.spec.ts
  • src/logging/index.ts
  • src/servers/supportedVersions/main.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/servers/supportedVersions/main.ts
  • src/ipc/main/validateSender.spec.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (windows-latest)
  • GitHub Check: Analyze (javascript)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from @rocket.chat/fuselage for all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments

Files:

  • src/logging/index.ts
🔇 Additional comments (1)
src/logging/index.ts (1)

269-280: Good hardening on sync IPC sender validation.

The early trust check plus immediate event.returnValue = '' fallback is a solid safeguard for this channel and keeps sendSync behavior safe.

Comment thread src/logging/index.ts
Comment on lines +274 to +277
console.warn(
'[ipc] log-viewer-window/get-server-tag: rejected untrusted sender',
event.sender.getURL()
);
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.

⚠️ Potential issue | 🟠 Major

Avoid logging full rejected sender URLs.

Logging event.sender.getURL() in this rejection path can persist sensitive query/fragment data into logs. Prefer logging a normalized origin (or just event.sender.id) instead.

Proposed fix
-        console.warn(
-          '[ipc] log-viewer-window/get-server-tag: rejected untrusted sender',
-          event.sender.getURL()
-        );
+        const rejectedSender = (() => {
+          try {
+            const senderUrl = event.sender.getURL();
+            return senderUrl ? new URL(senderUrl).origin : '<empty-url>';
+          } catch {
+            return '<invalid-url>';
+          }
+        })();
+        console.warn(
+          '[ipc] log-viewer-window/get-server-tag: rejected untrusted sender',
+          rejectedSender
+        );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/logging/index.ts` around lines 274 - 277, The current rejection log
prints the full sender URL via event.sender.getURL(), which may leak sensitive
query/fragment data; change the console.warn in the 'ipc'
log-viewer-window/get-server-tag rejection path to log a normalized origin or
the sender id instead: obtain the URL string from event.sender.getURL(), parse
it with the URL constructor to extract .origin (wrapped in a try/catch to handle
invalid URLs), and fall back to event.sender.id when parsing fails; then pass
that sanitized value to console.warn rather than the raw URL.

…lidation

registerWindowGetter('main-window', ...) was never called in production
code, causing isTrustedSender to always return false for the main window
and breaking the refresh-supported-versions IPC channel.
@jeanfbrito
Copy link
Copy Markdown
Member Author

P1 fix: main-window getter now registered in production code

Root cause confirmed: registerWindowGetter('main-window', ...) was never called outside of the spec file. isTrustedSender(sender, ['main-window']) always returned false in production, breaking refresh-supported-versions.

Fix (commit 2a2aa9b):

In src/ui/main/rootWindow.ts, inside createRootWindow(), immediately after _rootWindow is assigned:

```ts
registerWindowGetter('main-window', () => _rootWindow?.webContents ?? null);
```

The getter is a closure over the module-level _rootWindow variable, so it always reflects the current window instance (or null if not yet created).

Other windows: both log-viewer (src/logViewerWindow/ipc.ts:163) and video-call (src/videoCallWindow/ipc.ts:266) already register their getters at handler-setup time. Only main-window was missing.

Tests added to src/ui/main/rootWindow.spec.ts:

  • calls registerWindowGetter with "main-window" after creating the BrowserWindow
  • getter returned to registerWindowGetter returns the root window webContents

Verification: yarn test --testPathPattern="rootWindow.spec|validateSender.spec" → 34 tests pass. yarn lint and npx tsc --noEmit → clean.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/ui/main/rootWindow.spec.ts (1)

371-377: Tighten the catch blocks to avoid masking unrelated failures.

The empty catch will also swallow unexpected errors from createRootWindow(). Assert the expected error shape/message so the test still fails on unrelated regressions.

♻️ Suggested test hardening
       try {
         rootWindowModule.createRootWindow();
-      } catch {
-        // expected: tempWindow is undefined in this test context
+      } catch (error) {
+        expect(error).toBeInstanceOf(TypeError);
+        expect((error as Error).message).toMatch(/destroy|undefined/i);
       }
@@
       try {
         rootWindowModule.createRootWindow();
-      } catch {
-        // expected: tempWindow is undefined in this test context
+      } catch (error) {
+        expect(error).toBeInstanceOf(TypeError);
+        expect((error as Error).message).toMatch(/destroy|undefined/i);
       }

Also applies to: 391-395

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/main/rootWindow.spec.ts` around lines 371 - 377, The test currently
swallows all errors from rootWindowModule.createRootWindow() via a bare catch;
change the test to assert the specific expected failure instead of silencing
everything: call createRootWindow inside an assertion that checks the thrown
error shape/message (or use expect(() =>
rootWindowModule.createRootWindow()).toThrow(/tempWindow.*undefined|expected
message/) ), or in the catch inspect the error (e.g., error.message or a
specific error class) and rethrow if it doesn't match the expected "tempWindow
is undefined" condition; target the createRootWindow invocation and the
tempWindow-related error check so unrelated exceptions still fail the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/ui/main/rootWindow.spec.ts`:
- Around line 371-377: The test currently swallows all errors from
rootWindowModule.createRootWindow() via a bare catch; change the test to assert
the specific expected failure instead of silencing everything: call
createRootWindow inside an assertion that checks the thrown error shape/message
(or use expect(() =>
rootWindowModule.createRootWindow()).toThrow(/tempWindow.*undefined|expected
message/) ), or in the catch inspect the error (e.g., error.message or a
specific error class) and rethrow if it doesn't match the expected "tempWindow
is undefined" condition; target the createRootWindow invocation and the
tempWindow-related error check so unrelated exceptions still fail the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b621fd41-9972-4d40-ac79-0d21bc1eb752

📥 Commits

Reviewing files that changed from the base of the PR and between 954be66 and 2a2aa9b.

📒 Files selected for processing (2)
  • src/ui/main/rootWindow.spec.ts
  • src/ui/main/rootWindow.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: check (windows-latest)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: Analyze (javascript)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from @rocket.chat/fuselage for all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments

Files:

  • src/ui/main/rootWindow.ts
  • src/ui/main/rootWindow.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use *.spec.ts file naming convention for Renderer process tests

Files:

  • src/ui/main/rootWindow.spec.ts
**/*.{spec,main.spec}.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{spec,main.spec}.ts: Tests must run and pass on Windows, macOS, and Linux CI environments — always verify cross-platform compatibility
Only mock Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) when defensive coding with optional chaining isn't possible

Files:

  • src/ui/main/rootWindow.spec.ts
🧠 Learnings (5)
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.main.spec.ts : Use *.main.spec.ts file naming convention for Main process tests

Applied to files:

  • src/ui/main/rootWindow.spec.ts
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.{spec,main.spec}.ts : Tests must run and pass on Windows, macOS, and Linux CI environments — always verify cross-platform compatibility

Applied to files:

  • src/ui/main/rootWindow.spec.ts
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.spec.ts : Use *.spec.ts file naming convention for Renderer process tests

Applied to files:

  • src/ui/main/rootWindow.spec.ts
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.{spec,main.spec}.ts : Only mock Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) when defensive coding with optional chaining isn't possible

Applied to files:

  • src/ui/main/rootWindow.spec.ts
📚 Learning: 2026-04-06T18:34:44.375Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-06T18:34:44.375Z
Learning: Applies to **/*.{ts,tsx} : Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks

Applied to files:

  • src/ui/main/rootWindow.spec.ts
🔇 Additional comments (3)
src/ui/main/rootWindow.ts (1)

26-26: Solid integration of main-window sender registration.

Registering 'main-window' right after BrowserWindow creation with a null-safe getter is the right hook point for IPC sender trust checks.

Also applies to: 113-114

src/ui/main/rootWindow.spec.ts (2)

41-43: Nice targeted mock for sender validation dependency.

Mocking registerWindowGetter directly keeps these tests focused on root window behavior and registration semantics.


365-370: Good coverage for getter registration contract.

These assertions validate both registration arguments and the returned getter behavior, which is exactly what this security hook needs.

Also applies to: 397-404

…plies

Replace ipcMain.once with ipcMain.on + manual removeListener so that an
untrusted renderer firing the channel first does not consume the handler.
With once(), a malicious sender could permanently hang the screen-picker
request by removing the listener before the legitimate reply arrives.

Also adds two tests asserting: untrusted sender leaves listener intact,
trusted sender removes it and invokes handler exactly once.
@jeanfbrito
Copy link
Copy Markdown
Member Author

Fix: screen-picker listener no longer consumable by untrusted renderer

Commit: 786e69c

Problem

ipcMain.once('video-call-window/screen-sharing-source-responded', ...) at src/videoCallWindow/ipc.ts:308 consumed the listener on first call regardless of whether the sender passed the isTrustedSender check. An untrusted renderer could fire the channel first, silently remove the handler, and leave the legitimate picker reply with no listener — permanently hanging the request.

Fix

Replaced ipcMain.once with ipcMain.on + ipcMain.removeListener called only after the sender validates as 'video-call'. Untrusted senders now return early and the listener stays registered until a trusted reply arrives.

Other ipcMain.once usages audited

File Line Pattern Verdict
src/ipc/main.ts:14 ipcMain.once(\${channel}@${id}`, ...)` Internal correlation channel with unique per-request suffix — not exposed to untrusted renderers Safe, no change needed
src/screenSharing/ScreenSharingRequestTracker.ts:135 ipcMain.once(this.responseChannel, listener) Has its own cleanup/tracker mechanism; sender validation happens inside tracker Follow-up review recommended but out of scope for this PR

Tests added (src/ipc/main/validateSender.spec.ts)

  • untrusted sender does not consume the listener — fires channel with untrusted event, asserts listener count remains 1 and no value received
  • trusted sender consumes the listener and invokes handler exactly once — fires trusted event, asserts value received and listener removed; second trusted emit is a no-op

Result: 22 tests pass, lint clean, typecheck clean.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/videoCallWindow/ipc.ts (1)

291-333: ⚠️ Potential issue | 🟠 Major

Validate callerWebContents before relaying the picker result to match the authorization check in get-credentials.

The pickerResponseHandler validates only responseEvent.sender, but callerWebContents becomes the relay target without a local ownership check. Since the generic handle() wrapper performs no upstream sender validation, any renderer that can invoke this channel can receive the trusted picker result. The video-call-window/get-credentials handler already demonstrates the correct pattern—validate that the caller is either the video-call window itself or its hosted webview using:

const isAuthorizedCaller =
  !!videoCallWindow &&
  !videoCallWindow.isDestroyed() &&
  (callerWebContents.id === videoCallWindow.webContents.id ||
    callerWebContents.hostWebContents?.id === videoCallWindow.webContents.id);

Apply the same check before sending the screen-sharing response on line 329.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/videoCallWindow/ipc.ts` around lines 291 - 333, The pickerResponseHandler
in the handle('video-call-window/open-screen-picker') flow forwards the trusted
picker result to callerWebContents without verifying the caller is authorized;
mirror the get-credentials pattern by computing an isAuthorizedCaller check
using videoCallWindow and callerWebContents (ensure videoCallWindow exists and
is not destroyed, and that callerWebContents.id ===
videoCallWindow.webContents.id or callerWebContents.hostWebContents?.id ===
videoCallWindow.webContents.id) and only send the
'video-call-window/screen-sharing-source-responded' message when
isAuthorizedCaller is true (otherwise skip sending and optionally log a warning)
before removing the listener.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/videoCallWindow/ipc.ts`:
- Around line 291-333: The pickerResponseHandler in the
handle('video-call-window/open-screen-picker') flow forwards the trusted picker
result to callerWebContents without verifying the caller is authorized; mirror
the get-credentials pattern by computing an isAuthorizedCaller check using
videoCallWindow and callerWebContents (ensure videoCallWindow exists and is not
destroyed, and that callerWebContents.id === videoCallWindow.webContents.id or
callerWebContents.hostWebContents?.id === videoCallWindow.webContents.id) and
only send the 'video-call-window/screen-sharing-source-responded' message when
isAuthorizedCaller is true (otherwise skip sending and optionally log a warning)
before removing the listener.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 49501120-9ae6-4e5a-a796-3e73ca145b1f

📥 Commits

Reviewing files that changed from the base of the PR and between 2a2aa9b and 786e69c.

📒 Files selected for processing (2)
  • src/ipc/main/validateSender.spec.ts
  • src/videoCallWindow/ipc.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/ipc/main/validateSender.spec.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: check (windows-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from @rocket.chat/fuselage for all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments

Files:

  • src/videoCallWindow/ipc.ts

… to webContents identity

Gate hostWebContents-match in isLocalWindowSender to 'video-call' only.
'main-window' and 'log-viewer' now require exact WebContents identity,
preventing a server webview (which shares hostWebContents with the main
window) from bypassing the allowlist on channels like
refresh-supported-versions.

Adds regression test: 'rejects a server webview whose hostWebContents is
the main window (CORE-1129)'.
@jeanfbrito
Copy link
Copy Markdown
Member Author

Codex v4 P2 finding addressed (commit 90a3b3d)

The Codex v4 audit identified that `isLocalWindowSender` accepted both exact WebContents identity and `hostWebContents` match for all local window classes, including `main-window`. Since server webviews are hosted by the main window, a malicious server could call `refresh-supported-versions` with an arbitrary `serverUrl` by exploiting the `hostWebContents` path.

Fix: `hostWebContents`-match is now gated on `cls === 'video-call'` only — the only class with a legitimate hosted-webview use case (Jitsi). `main-window` and `log-viewer` now require exact WebContents identity match.

New regression test: "rejects a server webview whose hostWebContents is the main window (CORE-1129)" in `src/ipc/main/validateSender.spec.ts`.

Test suite: 23/23 passing. Lint and typecheck clean.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/ipc/main/validateSender.spec.ts (1)

41-44: Consider trimming section-banner comments.

The suite names already communicate intent; reducing divider comments would improve signal-to-noise.

As per coding guidelines, "Write self-documenting code through clear naming — avoid unnecessary comments."

Also applies to: 96-99, 125-128, 169-172, 215-218, 250-256, 334-337

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ipc/main/validateSender.spec.ts` around lines 41 - 44, Remove or trim the
large divider banner comments (e.g., the "//
---------------------------------------------------------------------------"
blocks that wrap titles like "server-webview") and similar banner blocks at the
other locations (lines around 96-99, 125-128, 169-172, 215-218, 250-256,
334-337), keeping only concise, single-line comments or relying on the existing
describe/it suite names (e.g., the validateSender.spec.ts test suite names) for
context so the test file is self-documenting and less noisy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/ipc/main/validateSender.spec.ts`:
- Around line 41-44: Remove or trim the large divider banner comments (e.g., the
"// ---------------------------------------------------------------------------"
blocks that wrap titles like "server-webview") and similar banner blocks at the
other locations (lines around 96-99, 125-128, 169-172, 215-218, 250-256,
334-337), keeping only concise, single-line comments or relying on the existing
describe/it suite names (e.g., the validateSender.spec.ts test suite names) for
context so the test file is self-documenting and less noisy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9de45762-697d-40a7-9585-6e4eb2547368

📥 Commits

Reviewing files that changed from the base of the PR and between 786e69c and 90a3b3d.

📒 Files selected for processing (2)
  • src/ipc/main/validateSender.spec.ts
  • src/ipc/validateSender.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/ipc/validateSender.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: check (windows-latest)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: Analyze (javascript)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from @rocket.chat/fuselage for all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments

Files:

  • src/ipc/main/validateSender.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use *.spec.ts file naming convention for Renderer process tests

Files:

  • src/ipc/main/validateSender.spec.ts
**/*.{spec,main.spec}.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{spec,main.spec}.ts: Tests must run and pass on Windows, macOS, and Linux CI environments — always verify cross-platform compatibility
Only mock Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) when defensive coding with optional chaining isn't possible

Files:

  • src/ipc/main/validateSender.spec.ts
🔇 Additional comments (4)
src/ipc/main/validateSender.spec.ts (4)

17-34: Solid WebContents test-double helper.

makeWebContents keeps test setup compact while still covering the fields needed by trust checks.


45-94: Good coverage for server-webview trust boundaries.

These cases exercise positive/negative origin matching, type checks, empty server state, and invalid sender URL handling.


100-213: Strong local-window trust regression coverage.

The suites correctly lock main-window/log-viewer to identity-only matching and keep hosted-webview matching scoped to video-call.


257-332: Nice robustness test for listener consumption semantics.

The ipcMain.on + manual removeListener simulation clearly validates that untrusted events do not consume the handler.

@jeanfbrito jeanfbrito changed the base branch from master to dev April 29, 2026 19:53
Base automatically changed from dev to master May 4, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant