Skip to content

app: validate resolved path in open-plugin-folder before opening it#6473

Open
krsatyamthakur-droid wants to merge 1 commit into
kubernetes-sigs:mainfrom
krsatyamthakur-droid:app/plugin-folder-path-traversal
Open

app: validate resolved path in open-plugin-folder before opening it#6473
krsatyamthakur-droid wants to merge 1 commit into
kubernetes-sigs:mainfrom
krsatyamthakur-droid:app/plugin-folder-path-traversal

Conversation

@krsatyamthakur-droid

Copy link
Copy Markdown
Contributor

Summary

The open-plugin-folder IPC handler joined the renderer-supplied folderName onto the plugins base directory and passed the result straight to shell.openPath, with no check that the joined path actually stayed inside that directory. A folderName like "../../../../etc" resolves outside the plugins folder entirely, and shell.openPath doesn't just browse directories - given a file path it opens that file with the OS's default handler, so this could end up launching something rather than just showing the wrong folder.

Added isPathWithinDirectory() in plugin-management.ts and used it to reject any resolved path that escapes the expected base directory before calling shell.openPath, logging the attempt instead.

Related Issue

Fixes #6472

Changes

  • app/electron/plugin-management.ts: added isPathWithinDirectory(), a small helper that checks a resolved path stays inside a base directory
  • app/electron/main.ts: use isPathWithinDirectory() in the open-plugin-folder handler, refusing shell.openPath if the resolved path escapes the plugins directory
  • app/electron/plugin-management.test.ts: tests for isPathWithinDirectory covering a normal plugin folder, a nested subdirectory, a traversal attempt, the base directory itself, and an unrelated absolute path

Steps to Test

  1. Trigger the open-plugin-folder IPC channel with folderName set to something like ../../../../etc and a valid type (e.g. user)
  2. Before this change, the handler joins the path and calls shell.openPath on whatever it resolves to, even outside the plugins folder
  3. After this change, it logs "Refusing to open plugin folder outside of ..." and shell.openPath never gets called
  4. A normal plugin folderName still opens fine like before

Screenshots (if applicable)

N/A, this is a main-process validation change with nothing visual to show.

Notes for the Reviewer

I pulled the check out into plugin-management.ts instead of leaving it inline in main.ts since that file already has test coverage, and nothing else in the codebase imports main.ts directly in a test (would mean mocking electron, yargs, dotenv, etc for basically no benefit).

@kubernetes-prow kubernetes-prow Bot requested a review from illume July 11, 2026 09:29
@kubernetes-prow kubernetes-prow Bot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jul 11, 2026
@kubernetes-prow kubernetes-prow Bot requested a review from sniok July 11, 2026 09:29
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: krsatyamthakur-droid
Once this PR has been reviewed and has the lgtm label, please assign ashu8912 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jul 11, 2026
@illume illume requested a review from Copilot July 13, 2026 07:07

Copilot AI 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.

Pull request overview

This PR hardens the Electron desktop app’s open-plugin-folder IPC handler against path traversal by ensuring the renderer-supplied folderName cannot resolve outside the expected plugins base directory before calling shell.openPath.

Changes:

  • Added isPathWithinDirectory() helper to validate a target path stays within a base directory.
  • Updated the open-plugin-folder IPC handler to reject resolved paths that escape the expected plugins directory and log the attempt.
  • Added unit tests covering allowed and rejected path cases for isPathWithinDirectory().

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
app/electron/plugin-management.ts Adds isPathWithinDirectory() helper used for validating renderer-influenced paths.
app/electron/main.ts Applies the helper in the open-plugin-folder IPC handler before invoking shell.openPath.
app/electron/plugin-management.test.ts Adds test coverage for the new path-within-directory helper.

Comment thread app/electron/plugin-management.ts
Comment thread app/electron/main.ts
Comment thread app/electron/main.ts Outdated

@illume illume 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.

Thanks for these changes.

Can you please address the open review comments? Once you've resolved each one, please mark it as resolved.

@krsatyamthakur-droid

Copy link
Copy Markdown
Contributor Author

@illume all three fixed, ptal

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

The open-plugin-folder IPC handler joined the renderer-supplied
folderName onto the plugins base directory and passed the result
straight to shell.openPath, with no check that it stayed inside that
directory. A folderName like "../../../../etc" resolves outside the
plugins folder, and shell.openPath opens (or, for a file, launches)
whatever it lands on, so a crafted name could open something well
outside the plugins directory.

Add isPathWithinDirectory() in plugin-management.ts and use it to
reject any resolved path that escapes the base directory before
calling shell.openPath. Since the IPC payload is untrusted, also guard
against a null or non-string folderName, and check the string that
shell.openPath resolves with (it resolves with an error message rather
than rejecting) so failures are logged.

Add tests for isPathWithinDirectory covering a normal folder, a nested
subdirectory, a name that starts with "..", a traversal attempt, the
base directory itself, and an unrelated absolute path.

Signed-off-by: satyam kumar <krsatyamthakur@gmail.com>
@krsatyamthakur-droid krsatyamthakur-droid force-pushed the app/plugin-folder-path-traversal branch from bc0d3b8 to b4c82da Compare July 13, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app: open-plugin-folder IPC allows path traversal via folderName

3 participants