diff --git a/bin/omarchy-plugin-add b/bin/omarchy-plugin-add index f0bdfca5..9fa0e6c0 100755 --- a/bin/omarchy-plugin-add +++ b/bin/omarchy-plugin-add @@ -93,6 +93,15 @@ if [[ -z $url ]]; then [[ -n $url ]] || fail "a git URL is required" fi +# git reads a leading dash as an option, and `::
` as a remote +# helper to run at clone time. Reject both so an untrusted URL cannot smuggle a +# transport helper that executes before the plugin is validated or enabled. An +# scp-style IPv6 host such as git@[2001:db8::1]:org/repo.git carries `::` too and +# must still clone. +if [[ $url == -* || $url =~ ^[A-Za-z0-9][A-Za-z0-9+.-]*:: ]]; then + fail "'$url' names a git option or transport helper, not a repository." +fi + if (( ! ASSUME_YES )); then cat >&2 <::…`) and option-shaped URLs +# before `git clone` runs, matching omarchy-theme-install. A git stub records +# whether clone was reached, so the guard is exercised with no network: reaching +# the stub proves a URL passed the guard; not reaching it proves the guard +# rejected the URL first. + +guard_stubs="$TMPDIR/guard-stubs" +mkdir -p "$guard_stubs" +cat >"$guard_stubs/omarchy-shell" <<'STUB' +#!/bin/bash +exit 0 +STUB +chmod +x "$guard_stubs/omarchy-shell" + +clone_marker="$TMPDIR/git-clone-reached" +cat >"$guard_stubs/git" <"$guard_stubs/gum" <<'STUB' +#!/bin/bash +if [[ $1 == "input" ]]; then + printf '%s\n' "$GUM_INPUT_VALUE" +fi +STUB +chmod +x "$guard_stubs/gum" + +add_url() { + HOME="$test_home" OMARCHY_PATH="$ROOT" PATH="$guard_stubs:$ROOT/bin:$PATH" \ + omarchy-plugin-add "$1" --yes 2>&1 +} + +# Transport helpers reach the guard, are named as such, and never reach clone. +for bad in "ext::sh -c touch /tmp/omarchy-guard-test" "fd::17"; do + rm -f "$clone_marker" + output=$(add_url "$bad") && + fail "plugin add rejects a transport-helper URL: $bad" "$output" + grep -qF "names a git option or transport helper" <<<"$output" || + fail "plugin add names the transport-helper rejection: $bad" "$output" + [[ ! -e $clone_marker ]] || + fail "plugin add reached git clone for a transport-helper URL: $bad" +done +pass "plugin add rejects transport-helper URLs before cloning" + +# Option-shaped URLs on argv are refused before clone — by the option parser +# (`-*` falls to "unknown add option"), not the guard. The guard's own +# leading-dash arm is only reachable through the interactive gum prompt and is +# exercised separately below. +for bad in "-oProxyCommand=x" "--upload-pack=x"; do + rm -f "$clone_marker" + output=$(add_url "$bad") && + fail "plugin add rejects an option-shaped URL: $bad" "$output" + [[ ! -e $clone_marker ]] || + fail "plugin add reached git clone for an option-shaped URL: $bad" +done +pass "plugin add rejects option-shaped URLs before cloning" + +# The guard's leading-dash arm is only reachable through `gum input`: argv +# dashes die in the option parser first. interactive() requires a TTY on stdin +# and stdout, so run this one case on a pty via util-linux `script -qec` (the +# suite's existing pty idiom); gum itself is stubbed, so no rendering happens. +# Probe script's util-linux syntax first and skip cleanly where it is missing. +if script -qec true /dev/null >/dev/null 2>&1; then + rm -f "$clone_marker" + status=0 + raw=$(GUM_INPUT_VALUE="-oProxyCommand=x" HOME="$test_home" OMARCHY_PATH="$ROOT" \ + PATH="$guard_stubs:$ROOT/bin:$PATH" \ + script -qec "omarchy-plugin-add --yes" /dev/null) || status=$? + output=$(tr -d '\r' <<<"$raw") + (( status != 0 )) || + fail "plugin add rejects an option-shaped URL from the gum prompt" "$output" + grep -qF "names a git option or transport helper" <<<"$output" || + fail "plugin add names the guard rejection for the gum-prompt URL" "$output" + [[ ! -e $clone_marker ]] || + fail "plugin add reached git clone for an option-shaped gum-prompt URL" + pass "plugin add guard rejects an option-shaped URL from the interactive prompt" +else + pass "script -qec unavailable; skipping the interactive gum-prompt guard case" +fi + +# Legitimate URL forms pass the guard and reach git clone (stubbed, no network). +for good in \ + "https://github.com/acme/omarchy-weather.git" \ + "git@github.com:acme/repo.git" \ + "ssh://git@github.com/acme/repo.git" \ + "git@[2001:db8::1]:org/repo.git"; do + rm -f "$clone_marker" + output=$(add_url "$good") || true + ! grep -qF "names a git option or transport helper" <<<"$output" || + fail "plugin add wrongly rejected a legitimate URL: $good" "$output" + [[ -e $clone_marker ]] || + fail "plugin add did not reach git clone for a legitimate URL: $good" "$output" +done +pass "plugin add lets legitimate git URLs reach git clone"