* Guard plugin-add against git transport-helper URLs omarchy-plugin-add cloned a user-supplied git URL without the transport-helper guard that omarchy-theme-install already applies (added in #7884, which did not touch plugin-add). Port that guard (reject ext::/fd:: and leading-dash forms, keep https/ssh/scp-style incl. IPv6) and add a regression test. Stock systems are unaffected (git default protocol.ext.allow=never); this removes the silent dependency on that default and aligns the two install paths. * Test the plugin-add guard's leading-dash arm via the gum input path The prior leading-dash cases only exercised the argv option parser, not the guard (removing the guard's -* arm left them green). Drive a dash value through the interactive gum prompt under a pty so the post-input guard is actually covered; skip cleanly where util-linux script is unavailable.
164 lines
5.8 KiB
Bash
164 lines
5.8 KiB
Bash
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
|
|
|
TMPDIR=$(mktemp -d)
|
|
trap 'rm -rf "$TMPDIR"' EXIT
|
|
|
|
write_plugin() {
|
|
local dir="$1"
|
|
local id="$2"
|
|
local name="$3"
|
|
|
|
mkdir -p "$dir"
|
|
cat >"$dir/manifest.json" <<JSON
|
|
{
|
|
"schemaVersion": 1,
|
|
"id": "$id",
|
|
"name": "$name",
|
|
"version": "1.0.0",
|
|
"kinds": ["bar-widget"],
|
|
"entryPoints": { "barWidget": "Widget.qml" },
|
|
"barWidget": {
|
|
"displayName": "$name",
|
|
"category": "Test",
|
|
"allowMultiple": false
|
|
}
|
|
}
|
|
JSON
|
|
printf 'import QtQuick\nItem {}\n' >"$dir/Widget.qml"
|
|
}
|
|
|
|
stub_dir="$TMPDIR/stubs"
|
|
mkdir -p "$stub_dir"
|
|
cat >"$stub_dir/omarchy-shell" <<'STUB'
|
|
#!/bin/bash
|
|
exit 0
|
|
STUB
|
|
chmod +x "$stub_dir/omarchy-shell"
|
|
|
|
test_home="$TMPDIR/home"
|
|
write_plugin "$test_home/.config/omarchy/plugins/different-folder" "acme.same" "Installed"
|
|
|
|
incoming="$TMPDIR/incoming"
|
|
write_plugin "$incoming" "acme.same" "Incoming"
|
|
git -C "$incoming" init -q
|
|
git -C "$incoming" add .
|
|
git -C "$incoming" -c user.name=Test -c user.email=test@example.com commit -qm "Initial"
|
|
|
|
output=$(HOME="$test_home" OMARCHY_PATH="$ROOT" PATH="$stub_dir:$ROOT/bin:$PATH" \
|
|
omarchy-plugin-add "$incoming" --yes 2>&1) &&
|
|
fail "plugin add accepts an id already installed under another directory" "$output"
|
|
grep -qF "plugin id 'acme.same' is already used by" <<<"$output" ||
|
|
fail "plugin add explains the installed id collision" "$output"
|
|
[[ ! -e $test_home/.config/omarchy/plugins/acme.same ]] ||
|
|
fail "plugin add leaves a target behind after refusing a duplicate id"
|
|
pass "plugin add refuses an installed manifest id regardless of directory name"
|
|
|
|
# --- URL transport-helper guard -------------------------------------------
|
|
#
|
|
# The guard refuses git transport helpers (`<name>::…`) 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" <<STUB
|
|
#!/bin/bash
|
|
if [[ \$1 == "clone" ]]; then
|
|
touch "$clone_marker"
|
|
exit 1
|
|
fi
|
|
exit 0
|
|
STUB
|
|
chmod +x "$guard_stubs/git"
|
|
|
|
# A gum stub that answers `gum input` with a caller-chosen value, so a test can
|
|
# drive any URL through the interactive prompt path.
|
|
cat >"$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"
|