From ed78ff056e89da814ff5ae05da6fb32b7e10c0db Mon Sep 17 00:00:00 2001 From: lorenzozanee Date: Sun, 20 Sep 2026 16:44:10 +0800 Subject: [PATCH 1/5] fix(install): reject Android portable binary Signed-off-by: lorenzozanee --- install.sh | 11 ++++++++ tests/test-install-android-guard.sh | 41 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100755 tests/test-install-android-guard.sh diff --git a/install.sh b/install.sh index 9f4b4ec999..01ab6c3781 100755 --- a/install.sh +++ b/install.sh @@ -148,8 +148,19 @@ detect_arch() { esac } +is_android() { + [ "$(uname -o 2>/dev/null || true)" = "Android" ] \ + || [ -n "${TERMUX_VERSION:-}" ] \ + || [[ "${PREFIX:-}" == /data/data/com.termux/* ]] +} + OS=$(detect_os) ARCH=$(detect_arch) +if [ "$OS" = "linux" ] && is_android; then + echo "error: Android/Termux is not supported by the Linux portable binary." >&2 + echo "Build from source with scripts/build.sh in Termux or use a supported Linux host." >&2 + exit 1 +fi echo "codebase-memory-mcp installer" echo " os: $OS" diff --git a/tests/test-install-android-guard.sh b/tests/test-install-android-guard.sh new file mode 100755 index 0000000000..6b3a383a29 --- /dev/null +++ b/tests/test-install-android-guard.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT + +mkdir -p "$WORK/bin" "$WORK/home" +cat >"$WORK/bin/uname" <<'EOF' +case "$1" in + -s) printf '%s\n' Linux ;; + -m) printf '%s\n' aarch64 ;; + -o) printf '%s\n' Android ;; + *) exit 1 ;; +esac +EOF +cat >"$WORK/bin/curl" <<'EOF' +printf 'curl must not run for Android/Termux\n' >&2 +exit 99 +EOF +chmod +x "$WORK/bin/uname" "$WORK/bin/curl" + +set +e +output=$(PATH="$WORK/bin:$PATH" HOME="$WORK/home" bash "$ROOT/install.sh" --skip-config 2>&1) +rc=$? +set -e + +if [ "$rc" -eq 0 ]; then + printf 'FAIL: installer accepted Android/Termux\n' >&2 + exit 1 +fi +if ! grep -Fq 'Android/Termux' <<<"$output"; then + printf 'FAIL: missing Android/Termux guidance\n%s\n' "$output" >&2 + exit 1 +fi +if grep -Fq 'curl must not run' <<<"$output"; then + printf 'FAIL: installer downloaded before rejecting Android/Termux\n' >&2 + exit 1 +fi + +printf 'PASS: Android/Termux is rejected before download\n' From 17415f6a3806a8529c0fc217b04f0cd9a056ce9f Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 1 Nov 2026 22:43:58 +0100 Subject: [PATCH 2/5] test(install): rename the Android guard test to the test_*.sh convention Every shell contract test under tests/ is named test_*.sh with underscores. A pure rename, so history and blame follow the file. Refs #1202 Signed-off-by: Martin Vogel --- ...est-install-android-guard.sh => test_install_android_guard.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test-install-android-guard.sh => test_install_android_guard.sh} (100%) diff --git a/tests/test-install-android-guard.sh b/tests/test_install_android_guard.sh similarity index 100% rename from tests/test-install-android-guard.sh rename to tests/test_install_android_guard.sh From 1fc70c2024ed6ff7e4fb5c735a342143c8572e02 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 1 Nov 2026 22:43:58 +0100 Subject: [PATCH 3/5] test(install): run the Android guard test as Step 0x2 of scripts/test.sh scripts/test.sh lists every shell contract test explicitly and does not glob tests/, so an unlisted test never ran on any leg. Register tests/test_install_android_guard.sh as Step 0x2, right after Step 0x, in the same two-line shape as its neighbours. Give the two PATH stubs (uname, curl) the same shebang every other stub under tests/ uses, so they are proper executables on every leg instead of relying on the shell fallback for files without one. Refs #1202 Signed-off-by: Martin Vogel --- scripts/test.sh | 3 +++ tests/test_install_android_guard.sh | 2 ++ 2 files changed, 5 insertions(+) diff --git a/scripts/test.sh b/scripts/test.sh index 992aea8370..baf41a9351 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -278,6 +278,9 @@ bash "$ROOT/tests/test_language_count_contract.sh" echo "=== Step 0x: packaging version-metadata contract ===" bash "$ROOT/tests/test_version_metadata_contract.sh" +echo "=== Step 0x2: installer Android/Termux guard contract (#1202) ===" +bash "$ROOT/tests/test_install_android_guard.sh" + # Step 0y: the Windows leg must not decide its verdict from an exit status that # the ssh/msys2_shell chain can mangle — a channel that turns 0 into 1 can turn # 1 into 0, and that direction reports a RED Windows leg as green. Runs diff --git a/tests/test_install_android_guard.sh b/tests/test_install_android_guard.sh index 6b3a383a29..59503fc7d1 100755 --- a/tests/test_install_android_guard.sh +++ b/tests/test_install_android_guard.sh @@ -7,6 +7,7 @@ trap 'rm -rf "$WORK"' EXIT mkdir -p "$WORK/bin" "$WORK/home" cat >"$WORK/bin/uname" <<'EOF' +#!/usr/bin/env bash case "$1" in -s) printf '%s\n' Linux ;; -m) printf '%s\n' aarch64 ;; @@ -15,6 +16,7 @@ case "$1" in esac EOF cat >"$WORK/bin/curl" <<'EOF' +#!/usr/bin/env bash printf 'curl must not run for Android/Termux\n' >&2 exit 99 EOF From 8b2b0d769f00dcfb994fd250ecbd9f58fd395973 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 1 Nov 2026 22:43:59 +0100 Subject: [PATCH 4/5] fix(install): say that Termux is not a supported platform yet The guard told users to build from source with scripts/build.sh in Termux, which reads as a supported path. Source builds under Termux still have open problems tracked in #1202, so the message now says why the portable binary cannot run there and that a source build may work but is not supported yet, pointing at #1202. The test still matches Android/Termux in the new message. Refs #1202 Signed-off-by: Martin Vogel --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 01ab6c3781..f3666e5d44 100755 --- a/install.sh +++ b/install.sh @@ -157,8 +157,8 @@ is_android() { OS=$(detect_os) ARCH=$(detect_arch) if [ "$OS" = "linux" ] && is_android; then - echo "error: Android/Termux is not supported by the Linux portable binary." >&2 - echo "Build from source with scripts/build.sh in Termux or use a supported Linux host." >&2 + echo 'error: Android/Termux cannot run the Linux portable binary (static glibc; Android kills it with "Bad system call").' >&2 + echo "Building from source in Termux may work but is not a supported platform yet - see issue #1202." >&2 exit 1 fi From 7a7ecb7356c152e0f6d22ac4d208b5919a21c862 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Sun, 1 Nov 2026 23:02:46 +0100 Subject: [PATCH 5/5] test(install): keep the Android guard test off the network Point CBM_DOWNLOAD_URL, the documented download-base override in install.sh, at a closed loopback port. If a curl stub were ever missed on some leg, the download would then fail locally instead of fetching a real release. Check that the uname stub is the one PATH resolves before running install.sh. Otherwise the test would quietly exercise the real host instead of an Android one and prove nothing. Refs #1202 Signed-off-by: Martin Vogel --- tests/test_install_android_guard.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_install_android_guard.sh b/tests/test_install_android_guard.sh index 59503fc7d1..b4bd6a7047 100755 --- a/tests/test_install_android_guard.sh +++ b/tests/test_install_android_guard.sh @@ -22,8 +22,16 @@ exit 99 EOF chmod +x "$WORK/bin/uname" "$WORK/bin/curl" +# The stubs must be what install.sh sees, or this test proves nothing. +if [ "$(PATH="$WORK/bin:$PATH" uname -o)" != "Android" ]; then + printf 'FAIL: the uname stub is not picked up from PATH\n' >&2 + exit 1 +fi + set +e -output=$(PATH="$WORK/bin:$PATH" HOME="$WORK/home" bash "$ROOT/install.sh" --skip-config 2>&1) +output=$(PATH="$WORK/bin:$PATH" HOME="$WORK/home" \ + CBM_DOWNLOAD_URL="http://127.0.0.1:9/cbm-android-guard-test" \ + bash "$ROOT/install.sh" --skip-config 2>&1) rc=$? set -e