fix: harden Ctrl+click URL handling (activation, allow-list, hover preview)#86
Open
manuacl wants to merge 1 commit into
Open
fix: harden Ctrl+click URL handling (activation, allow-list, hover preview)#86manuacl wants to merge 1 commit into
manuacl wants to merge 1 commit into
Conversation
manuacl
added a commit
to manuacl/limux
that referenced
this pull request
May 24, 2026
0e169a7 to
2bd1dd7
Compare
manuacl
added a commit
to manuacl/limux
that referenced
this pull request
May 25, 2026
67c9cb6 to
3ad3c51
Compare
…review Three related fixes around Ctrl+click on terminal URLs. 1. Raise the browser window via xdg-activation (am-will#85) open_url_in_external_browser previously called gio::AppInfo::launch_default_for_uri(url, None). Passing no AppLaunchContext means GIO emits no xdg-activation token, so under Wayland focus-stealing prevention the target browser opens the URL but cannot raise its window. Konsole works because KIO wires the token in its own launch path. - Pass Some(&display.app_launch_context()) so GIO emits the token. - Fall back to spawning xdg-open when GIO returns Err (AppImage / sandboxed contexts), with a detached reaper thread to avoid zombie children. - Preserve the GIO error message in the fallback log so a future silent-launch failure stays diagnosable. 2. Tighten the URL allow-list to http/https/mailto Threat-model the Ctrl+click hand-off as hostile terminal output: an OSC 8 hyperlink crafted by a remote shell, a `cat` of a malicious file, or a colleague's repro that includes a link. Clicking such a link must not lead to code execution. The previous list included ftp/ftps/file, which all delegate to gvfs / the local file handler: - file:// runs .desktop, scripts, and binaries via the registered handler — direct RCE on a hostile link. - ftp://, ftps:// auto-mount via gvfs and let the mounted share execute binaries (positive.security/blog/url-open-rce). Drop them. Keep only http/https/mailto — the minimal set recommended by the Positive Security writeup. Document the rationale in code so future additions need a proper threat-model review. Test matrix now explicitly rejects file:, ftp:, ftps:, smb:, nfs:, dav:, davs:, sftp:, vbscript:, vscode:, slack:. 3. Show OSC 8 URL preview on Ctrl+hover Ghostty already detects OSC 8 hyperlinks but the C embedding API leaves it to the host to surface the target URL. Limux wasn't handling GHOSTTY_ACTION_MOUSE_OVER_LINK at all, so users had no way to tell where a labelled link actually pointed before clicking — the well-known OSC 8 link-masking vector. - Add the GHOSTTY_ACTION_MOUSE_OVER_LINK tag and its {url, len} payload to the FFI bindings. - Surface the URL through a libadwaita gtk::Popover parented to the GLArea, so the look matches the right-click context menu by construction (same widget, same styling helpers). Two small helpers — build_floating_popover and build_popover_inner_box — are extracted and reused by both the hover preview and the existing context menu to keep them in sync. - Track the cursor position on every motion event and reposition the popover while it's visible; Ghostty only emits MOUSE_OVER_LINK on enter/leave, so without manual repositioning the popover would freeze at its initial anchor. - Anchor the popover above the cursor with a 14 px vertical gap big enough to clear an accessibility cursor skin. GTK auto-flips below the cursor when there isn't room above. - Drop the unused .limux-link-preview CSS rules (the popover is styled by the shared build_popover_inner_box() helper, not by a dedicated class). Closes am-will#85 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3ad3c51 to
f3d02a2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three layered changes to the OSC 8 / Ctrl+click URL hand-off:
Activation token (fix Ctrl+click on terminal URLs doesn't raise the browser window on Wayland #85). Pass an
AppLaunchContextfrom the defaultGdkDisplaywhen callinggio::AppInfo::launch_default_for_uri, so Wayland gets a valid xdg-activation token and the browser window can actually raise itself (Konsole works this way via KIO; we didn't). Fall back to spawningxdg-open(with a detached reaper thread, no zombie children) when GIO returns Err, for AppImage / sandboxed environments where the bundled GIO can't dispatch. Preserve the GIO error in the fallback log so future silent-launch failures stay diagnosable.Strict URI scheme allow-list (security hardening). Validate the scheme against
http/https/mailtoonly, case-insensitive per RFC 3986 §3.1. The issue Ctrl+click on terminal URLs doesn't raise the browser window on Wayland #85 description has the full rationale; short version is that anything beyond web + email opens us up to single-click RCE viafile://, gvfs auto-mount (ftp/ftps/smb/nfs/dav/sftp), or app-specific URI handlers with a history of CVEs.OSC 8 hover URL preview. Limux wasn't handling
GHOSTTY_ACTION_MOUSE_OVER_LINKat all, so users couldn't tell where a labelled hyperlink actually pointed before clicking — classic OSC 8 link-masking vector. Now a libadwaitagtk::Popover(parented to the GLArea, identical look to the right-click context menu by construction — same helpers) shows the target URL above the cursor while Ctrl is held, following the cursor inside the link region and auto-flipping below if there's no room above.Closes #85.
Test plan
./scripts/check.sh— fmt, clippy-D warnings, full workspace tests pass (189 inlimux-host-linux).http/https/mailto)HTTPS://,Https://,MAILTO:, …)javascript:,data:,vbscript:,file:,ftp:/ftps:,smb:/nfs:/dav:/davs:/sftp:,ssh:,magnet:,chrome:,about:,vscode:,slack:, leading whitespace, bare paths, malformed inputs.https://example.com→ opens Firefox and raises the window (was: window stayed hidden).HTTPS://example.com) → works (was: silently ignored).ps -ef | grep defunctclean after many Ctrl+clicks (reaper thread).\e]8;;https://example.com\e\\Click here\e]8;;\e\\) → libadwaita popover with the target URL appears above the cursor, tracks the cursor inside the link region, hides on leave.Commits
3641b72fix: raise browser window on Ctrl+click via xdg-activation token0f241dffix: tighten Ctrl+click URL allow-list to http/https/mailto0e169a7feat: show OSC 8 URL preview on Ctrl+hover(Can be squashed on merge.)