Skip to content

fix(run): only ShellExecute http/https post-run URLs - #87

Merged
AThraen merged 1 commit into
mainfrom
fix/post-run-url-scheme-guard
Aug 18, 2026
Merged

fix(run): only ShellExecute http/https post-run URLs#87
AThraen merged 1 commit into
mainfrom
fix/post-run-url-scheme-guard

Conversation

@AThraen

@AThraen AThraen commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Found during the pre-release review for v0.6.0.

Problem

PostRunUrl went straight to Process.Start with UseShellExecute = true, and nothing anywhere validated it. ShellExecute resolves far more than web URLs — a local executable, a .ps1, a UNC path, or any registered protocol handler (ms-settings:, steam://) would all be launched.

Two things make this worth closing rather than filing as "user's own config":

  1. It fires automatically when a run exits 0 — no click, no confirmation.
  2. ImportExportService.ImportAsync deserializes an entire AppState — run commands included — from any JSON file the user points at. An imported state file can therefore carry a run command that launches a program on its first successful run.

Import is a trust boundary either way (CommandLine is just as arbitrary), so this doesn't make importing untrusted state safe. It closes the automatic trigger.

Fix

RunInstance.IsLaunchableUrl gates the launch on an absolute http or https URI. Rejections are logged to crash.log alongside launch failures — we can't pop UI from the PTY-exit callback thread.

Scheme-less input like localhost:5173 is rejected rather than silently upgraded to http://; guessing on the user's behalf would defeat the check. The dialog tooltip now states the requirement explicitly, since that's the one input a user might reasonably expect to work.

Tests

19 new cases in PostRunUrlTests — accepted schemes (incl. case-insensitivity), rejected schemes (Windows paths, UNC, file:, javascript:, protocol handlers), and the empty / scheme-less cases.

Check Result
Unit tests 241/241 (222 + 19 new)
App + Tests build 0 errors, 0 warnings

Note

The solution build reports 14 warnings, all pre-existing nullable warnings in CodeShellManager.UITests, untouched by this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NDsEfog5kVkT5NmX1Ya5be

PostRunUrl went straight to Process.Start with UseShellExecute=true and
nothing validated it. ShellExecute resolves far more than web URLs — a
local executable, a .ps1, a UNC path, or any registered protocol handler
(ms-settings:, steam://) would all be launched.

This fires automatically when a run exits 0, with no confirmation step.
And ImportExportService deserializes an entire AppState — run commands
included — from any JSON file the user points at, so an imported state
file could carry a run command that launches a program on its first
successful run. Import is a trust boundary either way (CommandLine is
just as arbitrary), but the automatic trigger is worth closing.

RunInstance.IsLaunchableUrl now gates the launch on an absolute http or
https URI. Rejections are logged to crash.log alongside launch failures,
since we can't pop UI from the PTY-exit callback thread.

Scheme-less input like "localhost:5173" is rejected rather than silently
upgraded to http:// — guessing would defeat the check. The dialog tooltip
now says so explicitly.

19 new tests cover the accepted schemes, the rejected ones, and the
empty/scheme-less cases. Suite is 241/241.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NDsEfog5kVkT5NmX1Ya5be
@AThraen
AThraen merged commit f79d5b1 into main Aug 18, 2026
1 check passed
@AThraen
AThraen deleted the fix/post-run-url-scheme-guard branch August 18, 2026 12:34
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