gate clide:// deep links: paranoid allowlist + confirmation prompt (T-56, D-90)

A clide:// link is an untrusted external vector (any webpage can fire one), so it
no longer translates to a command in parseArgv. It routes the raw URL to a new
builtin.deeplink handler that is doubly defensive: a default-deny allowlist
(kDeepLinkSafeActions — only the read-only 'open' verb; run/git/write/passthrough
rejected) AND a mandatory 'an external link wants to: … allow?' confirmation
before anything runs. Records the security boundary as D-90.

The earlier silent editor.open passthrough is replaced; open still works, now
behind the prompt. Tests cover the allowlist (the boundary) + the gating.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 22:57:43 +02:00
co-authored by Claude Opus 4.8
parent 2791776ab7
commit 7171a09fc2
11 changed files with 316 additions and 65 deletions
+1
View File
@@ -131,6 +131,7 @@ You might also want, project-permitting:
- [D-87: Output/log dock — bottom, toggled, read-only (logs + problems)](decisions/architecture.md#d-87-outputlog-dock--bottom-toggled-read-only-logs--problems) — _architecture_
- [D-88: clide-owned anchored popover + menu primitive](decisions/design.md#d-88-clide-owned-anchored-popover--menu-primitive) — _design_
- [D-89: inline pasted-image thumbnails that expand to the lightbox](decisions/design.md#d-89-inline-pasted-image-thumbnails-that-expand-to-the-lightbox) — _design_
- [D-90: clide:// deep links — paranoid allowlist + user confirmation](decisions/architecture.md#d-90-clide-deep-links--paranoid-allowlist--user-confirmation) — _architecture_
## Open questions
+9
View File
@@ -451,3 +451,12 @@ Core, rendering, IPC, kernel, panel manager.
- **Raised by:** 2026-06-06 — T-54 UX design session (Frame0 wireframe under `docs/design/wireframes/output-dock/`). User chose a status-bar-toggled bottom dock scoped to read-only output, Problems folded in, terminal kept first-class in the editor pane.
---
### D-90: clide:// deep links — paranoid allowlist + user confirmation
- **Date:** 2026-06-09
- **Decision:** The `clide://` URL scheme (T-56) is treated as an UNTRUSTED external vector. A clide:// link is NOT translated into a command in the CLI parser; `parseArgv` hands the raw URL to a `deeplink.invoke` handler that is doubly defensive: (1) **default-deny allowlist** — only the actions in `kDeepLinkSafeActions` (today just `open`, a read-only navigation verb) are even parseable; anything else (`run`, `git`, `write`, arbitrary command passthrough, non-`clide` schemes) is rejected outright; and (2) **mandatory user confirmation** — every allowlisted action shows a "an external link wants to: … allow?" modal, framed as untrusted, before it executes. The OS scheme registration (linux `.desktop` `x-scheme-handler/clide`, macOS `CFBundleURLTypes`) + the CLI→IPC route mean a link lands in the running window (single-instance).
- **Rationale:** The `clide` CLI is a *local, trusted* surface (D-1/D-6); a URL handler is the opposite — any webpage can fire `clide://…` at the OS. A generic passthrough to the full command surface would be maximally extensible but would turn a malicious link into a remote control for the IDE (trigger `git push`, file writes, session kills). Paranoid-allowlist + confirm keeps the useful "open this file at this line from a CI link / error report" case while making the dangerous surface unreachable. The allowlist is the security boundary and is unit-tested in isolation.
- **Cost:** Each new deep-link action is an explicit, reviewed addition to `kDeepLinkSafeActions` + its handler branch — extensibility is deliberately gated, not free. The confirmation prompt adds a click to every deep-link open (acceptable for an out-of-band entry point). macOS URL *delivery* (AppDelegate `openURLs` → Dart) is a separate follow-up (T-303); the security model applies once delivery lands.
- **Raised by:** 2026-06-09 — user, on reviewing the T-56 passthrough: "put a heavy blocklist with do-you-want-this prompts on it (a paranoid allowlist)." Spotted that routing clide:// through the CLI path is "incredibly extensible" and that extensibility is exactly the risk for an external vector.
---