132 lines
5.4 KiB
Bash
Executable file
132 lines
5.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.."
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf -- "$tmp"' EXIT
|
|
mkdir -p "$tmp/bin"
|
|
|
|
# install-xui allocates the shim with mktemp -d before populating it. Exercise
|
|
# that real lifecycle, then both the cached and rejected download paths.
|
|
source <(awk '/^write_xui_curl_shim\(\)/ { copying=1 } copying { print } copying && /^}/ { exit }' \
|
|
ochenstarik-server-supply-chain.sh)
|
|
mkdir -m 700 "$tmp/shim" "$tmp/vendor"
|
|
printf 'verified-fixture\n' > "$tmp/vendor/x-ui.sh"
|
|
write_xui_curl_shim "$tmp/vendor" "$tmp/shim"
|
|
SUPPLY_DIR="$tmp/vendor" "$tmp/shim/curl" -fLRo "$tmp/copied" \
|
|
https://raw.githubusercontent.com/MHSanaei/3x-ui/v3.10.2/x-ui.sh
|
|
cmp "$tmp/vendor/x-ui.sh" "$tmp/copied"
|
|
if SUPPLY_DIR="$tmp/vendor" "$tmp/shim/curl" -o "$tmp/unknown" \
|
|
https://untrusted.example.test/installer.sh >/dev/null 2>&1; then
|
|
printf 'Shim accepted an unpinned installer request.\n' >&2
|
|
exit 1
|
|
fi
|
|
[[ ! -e "$tmp/unknown" ]]
|
|
|
|
# Load only the production URL fetcher so this test never calls the network or
|
|
# runs the VPN installer.
|
|
source <(awk '/^fetch_subscription\(\)/ { copying=1 } copying { print } copying && /^}/ { exit }' \
|
|
ochenstarik-server-vpn-5.sh)
|
|
die() { printf '%s\n' "$*" >&2; exit 1; }
|
|
source <(awk '/^choose_xray_source\(\)/ { copying=1 } copying { print } copying && /^}/ { exit }' \
|
|
ochenstarik-server-vpn-5.sh)
|
|
choose_xray_source <<< $'2\nhttps://git.example.test/project/releases/download/vendor-20261023'
|
|
[[ "$XRAY_SOURCE" == forgejo \
|
|
&& "$XRAY_MIRROR_BASE" == 'https://git.example.test/project/releases/download/vendor-20261023' ]]
|
|
|
|
cat > "$tmp/bin/curl" <<'CURL_STUB'
|
|
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
printf '%s\n' "$*" > "$CURL_ARGS_LOG"
|
|
cat > "$CURL_CONFIG_LOG"
|
|
while (($#)); do
|
|
if [[ "$1" == -o ]]; then printf 'test payload\n' > "$2"; exit 0; fi
|
|
shift
|
|
done
|
|
exit 1
|
|
CURL_STUB
|
|
chmod +x "$tmp/bin/curl"
|
|
export PATH="$tmp/bin:$PATH"
|
|
export CURL_ARGS_LOG="$tmp/curl-args" CURL_CONFIG_LOG="$tmp/curl-config"
|
|
|
|
literal_url='https://subscriptions.example.test/path/a"b\c?key=literal-marker'
|
|
fetch_subscription "$literal_url" "$tmp/subscription"
|
|
[[ "$(cat "$tmp/subscription")" == 'test payload' ]]
|
|
grep -Fqx -- 'proto = "=https"' "$CURL_CONFIG_LOG"
|
|
grep -Fqx -- 'tlsv1.2' "$CURL_CONFIG_LOG"
|
|
grep -Fqx -- 'location' "$CURL_CONFIG_LOG"
|
|
expected_url="${literal_url//\\/\\\\}"
|
|
expected_url="${expected_url//\"/\\\"}"
|
|
grep -Fqx -- "url = \"$expected_url\"" "$CURL_CONFIG_LOG"
|
|
if grep -Fq 'literal-marker' "$CURL_ARGS_LOG"; then
|
|
printf 'Subscription URL leaked into curl arguments.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
if (fetch_subscription $'https://subscriptions.example.test/good\nurl = "http://bad.example"' "$tmp/blocked") \
|
|
>/dev/null 2>&1; then
|
|
printf 'Control-character URL was accepted.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
# A large value must not bypass rejection through grep -q / SIGPIPE under
|
|
# pipefail. Bash validates the entire value before curl sees any config.
|
|
printf -v padding '%131072s' ''
|
|
if (fetch_subscription $'https://subscriptions.example.test/\v'"${padding// /x}" "$tmp/blocked-large") \
|
|
>/dev/null 2>&1; then
|
|
printf 'Large control-character URL was accepted.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
# S8 already carries these flags; lock the redirect policy in as a regression.
|
|
grep -Fq -- "--proto '=https' --tlsv1.2" ochenstarik-server-ai-agents-8.sh
|
|
|
|
# A failed Forgejo mirror request must stop without trying GitHub.
|
|
cat > "$tmp/bin/curl" <<'CURL_FAIL_STUB'
|
|
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
printf '%s\n' "$*" >> "$CURL_ATTEMPTS"
|
|
exit 22
|
|
CURL_FAIL_STUB
|
|
chmod +x "$tmp/bin/curl"
|
|
export CURL_ATTEMPTS="$tmp/attempts"
|
|
if bash ./ochenstarik-server-supply-chain.sh prepare forgejo "$tmp/prepared" \
|
|
'https://git.example.test/project/releases/download/vendor-20261023' \
|
|
>/dev/null 2>&1; then
|
|
printf 'Failed Forgejo fetch unexpectedly succeeded.\n' >&2
|
|
exit 1
|
|
fi
|
|
[[ "$(wc -l < "$CURL_ATTEMPTS")" == 1 ]]
|
|
grep -Fq 'https://git.example.test/project/releases/download/vendor-20261023/xui-install.sh' "$CURL_ATTEMPTS"
|
|
if grep -Eq 'github\.com|raw\.githubusercontent\.com' "$CURL_ATTEMPTS"; then
|
|
printf 'Forgejo failure fell back to GitHub.\n' >&2
|
|
exit 1
|
|
fi
|
|
if bash ./ochenstarik-server-supply-chain.sh prepare-xray forgejo "$tmp/xray-prepared" \
|
|
'https://git.example.test/project/releases/download/vendor-20261023' \
|
|
>/dev/null 2>&1; then
|
|
printf 'Failed Forgejo Xray fetch unexpectedly succeeded.\n' >&2
|
|
exit 1
|
|
fi
|
|
[[ "$(wc -l < "$CURL_ATTEMPTS")" == 2 ]]
|
|
grep -Fq 'https://git.example.test/project/releases/download/vendor-20261023/xray-install.sh' "$CURL_ATTEMPTS"
|
|
if grep -Eq 'github\.com|raw\.githubusercontent\.com' "$CURL_ATTEMPTS"; then
|
|
printf 'Xray Forgejo failure fell back to GitHub.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Both installer steps must reach their pinned helper paths and avoid mutable
|
|
# upstream main installer URLs.
|
|
grep -Fq 'prepare-xray github' ochenstarik-server-vpn-5.sh
|
|
grep -Fq 'prepare-xray forgejo' ochenstarik-server-vpn-5.sh
|
|
grep -Fq 'install-xray "$XRAY_SUPPLY_DIR"' ochenstarik-server-vpn-5.sh
|
|
grep -Fq 'prepare github' ochenstarik-server-panel-warp-6.sh
|
|
grep -Fq 'prepare forgejo' ochenstarik-server-panel-warp-6.sh
|
|
grep -Fq 'install-xui "${TMP_DIR}/vendor"' ochenstarik-server-panel-warp-6.sh
|
|
if grep -Eq 'XTLS/Xray-install/main|MHSanaei/3x-ui/main' \
|
|
ochenstarik-server-vpn-5.sh ochenstarik-server-panel-warp-6.sh; then
|
|
printf 'An installer step still references a mutable upstream main URL.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf 'Download security tests passed.\n'
|