Skip to content

fix(#118): validate URL scheme before calling shell.openExternal#137

Open
anshul23102 wants to merge 1 commit into
SamXop123:mainfrom
anshul23102:fix/118-open-external-scheme-validation
Open

fix(#118): validate URL scheme before calling shell.openExternal#137
anshul23102 wants to merge 1 commit into
SamXop123:mainfrom
anshul23102:fix/118-open-external-scheme-validation

Conversation

@anshul23102
Copy link
Copy Markdown

@anshul23102 anshul23102 commented May 30, 2026

Summary

Both the app:open-external IPC handler and the visualizer-action open-url path passed caller-supplied URLs directly to shell.openExternal without any scheme validation. On Windows, registered custom protocols such as ms-settings:, ms-officecmd:, and search-ms: are dispatched to the OS shell, allowing a malicious or compromised renderer to silently launch arbitrary system applications or trigger privileged OS actions without user consent. Electron's own security documentation explicitly requires scheme validation before calling shell.openExternal.

Closes #118

Root Cause

// Before: no scheme check in either caller
ipcMain.handle('app:open-external', (_event, url) => {
  openExternalUrl(url);
});

} else if (action === 'open-url') {
  openExternalUrl(data);  // data is renderer-supplied
}

openExternalUrl called shell.openExternal(url) unconditionally.

Fix

Added an ALLOWED_EXTERNAL_SCHEMES allowlist (https: and http:) inside openExternalUrl. The function parses the URL with new URL() and returns early if the resulting protocol is not in the allowlist. Invalid URL strings (parse errors) also return early without reaching shell.openExternal. All callers go through the same central function so the guard applies uniformly.

const ALLOWED_EXTERNAL_SCHEMES = new Set(["https:", "http:"]);

function openExternalUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    return;
  }
  if (!ALLOWED_EXTERNAL_SCHEMES.has(parsed.protocol)) {
    return;
  }
  shell.openExternal(url).catch(() => {});
}

Files Changed

  • main.js: Added ALLOWED_EXTERNAL_SCHEMES constant and scheme validation at the top of openExternalUrl.

How to Test

  1. From renderer DevTools: window.paralineApp.openExternal('ms-settings:') should do nothing.
  2. window.paralineApp.openExternal('https://github.com') should open the browser as before.
  3. window.paralineApp.openExternal('javascript:alert(1)') should do nothing.

Checklist

  • Only targets the identified vulnerability.
  • No functional change for callers that already supply https: or http: URLs.
  • No new dependencies.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced security by implementing URL scheme validation for external link handling. External URLs are now restricted to HTTPS and HTTP protocols only, with invalid URLs silently blocked.

Review Change Stack

…rnal

Both the app:open-external IPC handler and the visualizer-action open-url
path passed caller-supplied URLs directly to shell.openExternal without any
scheme check. On Windows, registered custom protocols such as ms-settings:,
ms-officecmd:, or search-ms: are handled by the OS shell, so a renderer that
can invoke either path could silently launch arbitrary system applications or
trigger OS actions.

Added an ALLOWED_EXTERNAL_SCHEMES allowlist (https: and http:) checked inside
openExternalUrl before the shell call. Strings that are not valid URLs or that
use any other scheme return immediately without reaching shell.openExternal.
All callers go through the same central function so the guard applies
uniformly to both the IPC handler and the tray action path.

Fixes SamXop123#118
@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

@anshul23102 is attempting to deploy a commit to the Dot_NotSam's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d727420c-ddc2-44eb-9ef9-39b572a1b571

📥 Commits

Reviewing files that changed from the base of the PR and between 3e9da7b and 9daabd4.

📒 Files selected for processing (1)
  • main.js

📝 Walkthrough

Walkthrough

The pull request hardens the openExternalUrl function in main.js by adding URL scheme validation. An allowlist restricting external URL opening to http: and https: protocols is enforced; any other scheme or unparseable URL is silently rejected before shell.openExternal is invoked.

Changes

External URL Scheme Validation

Layer / File(s) Summary
Restrict external URL schemes
main.js
openExternalUrl adds an ALLOWED_EXTERNAL_SCHEMES allowlist and validates input URLs via new URL() parsing before calling shell.openExternal. Malformed or non-allowlisted scheme URLs are silently dropped.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A rabbit hops through schemes so bright,
But only https and http feel right,
Bad protocols are caught and dropped,
No dangerous handlers shall be popped! 🛡️

🚥 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 title accurately describes the main change: adding URL scheme validation before calling shell.openExternal, which directly addresses the security fix.
Linked Issues check ✅ Passed The PR implementation meets all coding requirements from issue #118: validates URL scheme with an allowlist (http:/https:), parses with new URL(), and applies validation uniformly to openExternalUrl.
Out of Scope Changes check ✅ Passed All changes are directly related to the security fix objective: the modification adds scheme validation logic to openExternalUrl in main.js with no unrelated alterations.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

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.

Security: app:open-external and visualizer-action open-url pass caller-supplied URLs to shell.openExternal without scheme validation

1 participant