Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions scan/trustabl-scan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ if [ "$VER" = "latest" ]; then
fi
if [ -z "$VER" ] || [ "$VER" = "null" ]; then
echo "Could not resolve trustabl version. Pin 'VERSION' to a tag, or set GITHUB_TOKEN."
exit 1
exit 2
fi
# One path segment only. A slash, '..', or URL metacharacter in a pin or in
# tag_name from /releases/latest would change
# /releases/download/${VER}/${ASSET} and the local -o filename.
if [[ "$VER" == */* || "$VER" == *\\* || "$VER" == *..* || "$VER" == *[[:space:]]* || "$VER" == *:* || "$VER" == *@* ]]; then
echo "Invalid trustabl version. Pin VERSION to a single release tag."
exit 2
fi
echo "Trustabl version: $VER"

Expand All @@ -70,12 +77,12 @@ VNUM="${VER#v}"
case "$(uname -s)" in
Linux) OS=linux ;;
Darwin) OS=darwin ;;
*) echo "Unsupported OS $(uname -s)"; exit 1 ;;
*) echo "Unsupported OS $(uname -s)"; exit 2 ;;
esac
case "$(uname -m)" in
x86_64|amd64) ARCH=amd64 ;;
aarch64|arm64) ARCH=arm64 ;;
*) echo "Unsupported arch $(uname -m)"; exit 1 ;;
*) echo "Unsupported arch $(uname -m)"; exit 2 ;;
esac
ASSET="trustabl_${VNUM}_${OS}_${ARCH}.tar.gz"
DEST="$(pwd)/.trustabl-bin"
Expand Down
73 changes: 73 additions & 0 deletions test/test-setup-exit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Offline: unresolved or path-breaking VERSION is setup I/O, so exit 2.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
STUB="$(mktemp -d)"
LOG="$(mktemp)"
trap 'rm -rf "$STUB" "$LOG"' EXIT

run_scan() {
set +e
PATH="$STUB:$PATH" bash "$ROOT/scan/trustabl-scan.sh" >"$LOG" 2>&1
rc=$?
set -e
}

expect_exit_2() {
local why="$1"
[ "$rc" -eq 2 ] || {
echo "expected exit 2 ($why), got $rc"
cat "$LOG"
exit 1
}
}

# ---- unresolved latest ----
cat > "$STUB/curl" <<'EOF'
#!/usr/bin/env bash
echo '{"tag_name":""}'
exit 0
EOF
chmod +x "$STUB/curl"

VERSION=latest run_scan
expect_exit_2 "unresolved VERSION"
echo "ok: unresolved VERSION exits 2"

# ---- pin that would leave /releases/download/${VER}/ ----
cat > "$STUB/curl" <<'EOF'
#!/usr/bin/env bash
echo "CURL_RAN $*" >&2
exit 0
EOF
chmod +x "$STUB/curl"

VERSION='v1.0.0/../../../tmp/pwn' run_scan
expect_exit_2 "VERSION path breakout"
if grep -q CURL_RAN "$LOG"; then
echo "curl must not run when VERSION leaves the download path"
cat "$LOG"
exit 1
fi
echo "ok: VERSION with slash exits 2 without fetching"

# ---- tag_name from /releases/latest that would leave the path ----
cat > "$STUB/curl" <<'EOF'
#!/usr/bin/env bash
if printf '%s' "$*" | grep -q 'releases/download'; then
echo "DOWNLOAD_RAN $*" >&2
exit 0
fi
echo '{"tag_name":"v1.0.0/../evil"}'
exit 0
EOF
chmod +x "$STUB/curl"

VERSION=latest run_scan
expect_exit_2 "latest tag_name path breakout"
if grep -q DOWNLOAD_RAN "$LOG"; then
echo "binary fetch must not run when latest tag_name leaves the download path"
cat "$LOG"
exit 1
fi
echo "ok: latest tag_name with slash exits 2 without downloading"