Skip to content

Fix NSURL misdetection routing SSH commands to openURL - #302

Open
ThatdBeSid wants to merge 1 commit into
fitztrev:masterfrom
ThatdBeSid:master
Open

Fix NSURL misdetection routing SSH commands to openURL#302
ThatdBeSid wants to merge 1 commit into
fitztrev:masterfrom
ThatdBeSid:master

Conversation

@ThatdBeSid

Copy link
Copy Markdown

Only treat command strings as URLs when they have an explicit http/https scheme, since NSURL's parser has become more lenient over time and was misrouting SSH commands to NSWorkspace openURL. Also logs AppleScript execution errors instead of discarding them. Bumps minimum deployment target from 10.9 to 10.13.

Only treat command strings as URLs when they have an explicit http/https scheme, since NSURL's parser has become more lenient over time and was misrouting SSH commands to NSWorkspace openURL. Also logs AppleScript execution errors instead of discarding them. Bumps minimum deployment target from 10.9 to 10.13.
@morri5

morri5 commented Jul 30, 2026

Copy link
Copy Markdown

Hit the same bug independently and landed on a slightly different rule, sharing in case it's useful.

Restricting to http/https means vnc:// and ssh:// entries fall through to the terminal branch and get typed in as shell commands. Shuttle handled those before, since openURL: passes them to Screen Sharing and the registered SSH handler.

An alternative that keeps them working: treat an entry as a URL only when it has a scheme and contains no whitespace.

- (NSURL *) urlForEntry: (NSString *) entry
{
    if ([entry rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location != NSNotFound)
        return nil;

    NSURL *url = [NSURL URLWithString:entry];
    return url.scheme.length ? url : nil;
}

The whitespace test is what does the work. Every realistic command contains a space, and the ones that legitimately contain a colon (docker run -v a:b img) are caught by it too.

Root cause, for anyone who finds this by searching the error message: -URLWithString: moved to a lenient WHATWG-style parser, and the behaviour is gated on the SDK the binary was linked against. That's why the 2016 release still works and anything built on a current Xcode does not. Every command percent-escapes into a non-nil URL, so openURL: fires, Launch Services returns paramErr, the user sees "The application can't be opened.", and the entire iTerm/Terminal AppleScript branch below becomes unreachable dead code.

Separately, +1 on logging the AppleScript execution errors. That's a real improvement I didn't have.

I have a fork at https://github.com/morri5/shuttle carrying this plus a universal arm64 build and a launchd-based replacement for the LSSharedFileList login-item code, if that's useful to anyone landing here.

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.

2 participants