fix(installer): harden greenfield detector contracts

This commit is contained in:
2026-08-05 17:46:58 -05:00
parent 99e28d4100
commit 3edde464b3
18 changed files with 924 additions and 190 deletions
+221 -8
View File
@@ -4,6 +4,8 @@ set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TMP="$(mktemp -d "${TMPDIR:-/tmp}/mosaic-next-install-test-XXXXXX")"
trap 'rm -rf "$TMP"' EXIT
export TMPDIR="$TMP/runtime-tmp"
mkdir -p "$TMPDIR"
FAKE_BIN="$TMP/bin"
HOME_DIR="$TMP/home"
@@ -13,6 +15,48 @@ STATE="$TMP/state"
LOG="$TMP/npm.log"
mkdir -p "$FAKE_BIN" "$HOME_DIR" "$STATE"
# Model the supported non-root/glibc target explicitly even when this harness
# itself runs as root in Alpine/BusyBox CI.
cat > "$FAKE_BIN/id" <<'FAKE_ID'
#!/usr/bin/env bash
case "${1:-}" in
-u) echo 1001 ;;
-g) echo 1001 ;;
-un) echo fixture-user ;;
*) exec /bin/id "$@" ;;
esac
FAKE_ID
cat > "$FAKE_BIN/getent" <<FAKE_GETENT
#!/usr/bin/env bash
printf 'fixture-user:x:1001:1001::%s:/bin/bash\n' '$HOME_DIR'
FAKE_GETENT
cat > "$FAKE_BIN/ldd" <<'FAKE_LDD'
#!/usr/bin/env bash
printf 'ldd (GNU libc) 2.36\n'
FAKE_LDD
cat > "$FAKE_BIN/stat" <<'FAKE_STAT'
#!/usr/bin/env bash
if [[ "${1:-} ${2:-}" == '-c %u' ]]; then
[[ "${3:-}" == "${MOSAIC_TEST_WRONG_OWNER_PATH:-__none__}" ]] && echo 9999 || echo 1001
exit 0
fi
if [[ "${1:-} ${2:-}" == '-c %g' ]]; then
[[ "${3:-}" == "${MOSAIC_TEST_WRONG_GROUP_PATH:-__none__}" ]] && echo 9999 || echo 1001
exit 0
fi
exec /bin/stat "$@"
FAKE_STAT
cat > "$FAKE_BIN/realpath" <<'FAKE_REALPATH'
#!/usr/bin/env python3
import os, sys
args=sys.argv[1:]
mode=args.pop(0) if args and args[0] in ('-e','-m') else '-m'
if args and args[0]=='--': args.pop(0)
if len(args)!=1 or (mode=='-e' and not os.path.exists(args[0])): raise SystemExit(1)
print(os.path.realpath(args[0]))
FAKE_REALPATH
chmod 0755 "$FAKE_BIN/id" "$FAKE_BIN/getent" "$FAKE_BIN/ldd" "$FAKE_BIN/stat" "$FAKE_BIN/realpath"
cat > "$FAKE_BIN/npm" <<'FAKE_NPM'
#!/usr/bin/env bash
set -euo pipefail
@@ -31,6 +75,15 @@ install_cli() {
mkdir -p "${MOSAIC_PREFIX:?}/bin"
cat > "$MOSAIC_PREFIX/bin/mosaic" <<CLI
#!/usr/bin/env bash
set -euo pipefail
if [[ "\${1:-}" == "wizard" ]]; then
printf 'wizard\n' >> "\${MOSAIC_TEST_NPM_LOG:?}"
mkdir -p "\${MOSAIC_HOME:?}" "\${HOME:?}/.config/mosaic-gateway"
printf '# Soul\\n\\nConfigured.\\n' > "\$MOSAIC_HOME/SOUL.md"
printf '# User\\n\\nConfigured.\\n' > "\$MOSAIC_HOME/USER.md"
chmod 0600 "\$MOSAIC_HOME/SOUL.md" "\$MOSAIC_HOME/USER.md"
exit 0
fi
printf '%s\\n' '$version'
CLI
chmod +x "$MOSAIC_PREFIX/bin/mosaic"
@@ -51,6 +104,12 @@ if [[ "$1" == "view" ]]; then
fi
if [[ "$1" == "install" ]]; then
if [[ -n "${MOSAIC_INSTALL_SECRET_CANARY:-}" ]]; then
printf 'registry diagnostic authToken=%s\n' "$MOSAIC_INSTALL_SECRET_CANARY"
printf 'urls=https://alice:p@[email protected]/a https://bob:pa:[email protected]/b https://carol:p%%[email protected]/c https://[email protected]/d https://user%%[email protected]/e\n'
printf 'Authorization: Basic QWxhZGRpbjpvcGVu\n//registry/:_auth=Ym9iOnNlY3JldA==\nCookie: session=abc123\nSet-Cookie: sid=xyz789\n'
printf '%s\n' "$MOSAIC_INSTALL_SECRET_CANARY" > "${MOSAIC_TEST_CANARY_OBSERVATION:?}"
fi
case "$*" in
*"@mosaicstack/[email protected]"*)
install_cli "0.0.49-next.999"
@@ -141,7 +200,21 @@ if [[ -z "$dest" ]]; then
echo "fake tar missing -C destination" >&2
exit 1
fi
mkdir -p "$dest/stack/packages/mosaic" "$dest/stack/apps/gateway"
mkdir -p "$dest/stack/packages/mosaic/framework" "$dest/stack/apps/gateway"
cat > "$dest/stack/packages/mosaic/framework/install.sh" <<'FRAMEWORK'
#!/usr/bin/env bash
set -euo pipefail
expected="${MOSAIC_PREFIX:?}/bin/mosaic"
[[ "${MOSAIC_CLI_PATH:-}" == "$expected" && -x "$MOSAIC_CLI_PATH" ]] || {
echo "framework did not receive P3 absolute CLI (got=${MOSAIC_CLI_PATH:-unset} expected=$expected)" >&2
exit 61
}
printf 'framework-cli=%s version=%s\n' "$MOSAIC_CLI_PATH" "$($MOSAIC_CLI_PATH --version)" >> "${MOSAIC_TEST_NPM_LOG:?}"
mkdir -p "${MOSAIC_HOME:?}/credentials"
chmod 0700 "$MOSAIC_HOME/credentials"
printf '# framework fixture\n' > "$MOSAIC_HOME/AGENTS.md"
FRAMEWORK
chmod 0755 "$dest/stack/packages/mosaic/framework/install.sh"
FAKE_TAR
chmod +x "$FAKE_BIN/tar"
@@ -187,15 +260,28 @@ reset_state() {
rm -f "$STATE"/*
}
prefix_fingerprint() {
if [[ ! -d "$PREFIX" ]]; then printf 'ABSENT\n'; return; fi
(
cd "$PREFIX"
find . -mindepth 1 -printf '%P|%y|%m|%l\n' | LC_ALL=C sort
find . -type f -print0 | LC_ALL=C sort -z | xargs -0 -r sha256sum
) | sha256sum | awk '{print $1}'
tree_fingerprint() {
local root="$1"
if [[ ! -d "$root" ]]; then printf 'ABSENT\n'; return; fi
python3 - "$root" <<'PY'
import hashlib, os, stat, sys
root=os.path.abspath(sys.argv[1]); rows=[]
for current, dirs, files in os.walk(root, topdown=True, followlinks=False):
for name in dirs + files:
path=os.path.join(current,name); meta=os.lstat(path)
rel=os.path.relpath(path,root)
target=os.readlink(path) if stat.S_ISLNK(meta.st_mode) else ''
digest=''
if stat.S_ISREG(meta.st_mode):
with open(path,'rb') as handle: digest=hashlib.sha256(handle.read()).hexdigest()
rows.append((rel,stat.S_IFMT(meta.st_mode),stat.S_IMODE(meta.st_mode),target,digest))
payload='\n'.join('|'.join(map(str,row)) for row in sorted(rows)).encode()
print(hashlib.sha256(payload).hexdigest())
PY
}
prefix_fingerprint() { tree_fingerprint "$PREFIX"; }
reset_state
echo "[test] --next fast path pins resolved package versions"
OUTPUT="$(
@@ -356,4 +442,131 @@ set -e
[[ "$CHECK_STATUS" -ne 0 ]]
grep -q '^\[P2\] FAIL: resolved_version=unavailable' <<<"$OUTPUT"
printf '[test] full framework path receives P3 absolute CLI without relying on PATH\n'
rm -rf "$HOME_DIR" "$STATE"; mkdir -p "$HOME_DIR" "$STATE"; reset_state
set +e
OUTPUT="$(
HOME="$HOME_DIR" MOSAIC_HOME="$MOSAIC_HOME" MOSAIC_PREFIX="$PREFIX" \
MOSAIC_INSTALL_STATE_DIR="$TMP/full-state" MOSAIC_NO_COLOR=1 \
MOSAIC_TEST_NPM_LOG="$LOG" MOSAIC_TEST_STATE="$STATE" \
PATH="$FAKE_BIN:/usr/local/bin:/usr/bin:/bin" \
bash "$ROOT/tools/install.sh" --next --yes --no-auto-launch 2>&1
)"
FULL_STATUS=$?
set -e
[[ "$FULL_STATUS" -ne 0 ]] # P4 remains intentionally undeclared until C5.
grep -qF "framework-cli=$PREFIX/bin/mosaic version=0.0.49-next.999" "$LOG"
if grep -q "CLI not found on PATH\|did not receive P3 absolute CLI" <<<"$OUTPUT"; then
echo "internal framework phase depended on PATH instead of P3 absolute CLI" >&2
exit 1
fi
printf '[test] captured diagnostics redact seeded credential canary everywhere\n'
rm -rf "$HOME_DIR" "$STATE"; mkdir -p "$HOME_DIR" "$STATE"; reset_state
canary='C1_SECRET_CANARY_7df4c2'
OUTPUT="$(
HOME="$HOME_DIR" MOSAIC_HOME="$MOSAIC_HOME" MOSAIC_PREFIX="$PREFIX" \
MOSAIC_INSTALL_STATE_DIR="$TMP/secret-state" MOSAIC_NO_COLOR=1 \
MOSAIC_INSTALL_SECRET_CANARY="$canary" MOSAIC_TEST_CANARY_OBSERVATION="$TMP/canary-observed" \
MOSAIC_TEST_NPM_LOG="$LOG" MOSAIC_TEST_STATE="$STATE" \
PATH="$FAKE_BIN:/usr/local/bin:/usr/bin:/bin" \
bash "$ROOT/tools/install.sh" --cli --next --yes --no-auto-launch 2>&1
)"
if grep -qF "$canary" <<<"$OUTPUT"; then echo 'credential canary leaked to terminal output' >&2; exit 1; fi
if grep -Eq 'alice:p@ss|bob:pa:ss|carol:p%40ss|token@example|user%3Apass|QWxhZGRpbjpvcGVu|Ym9iOnNlY3JldA|session=abc123|sid=xyz789' <<<"$OUTPUT"; then
echo 'credentialed URL userinfo leaked to terminal output' >&2; exit 1
fi
[[ "$(grep -oF '[REDACTED]@' <<<"$OUTPUT" | wc -l | tr -d ' ')" -ge 5 ]] \
|| { echo 'credentialed URL redaction controls were not all exercised' >&2; exit 1; }
secret_active="$TMP/secret-state/active.json"
secret_journal="$(node -p "require('$secret_active').journal")"
secret_command_log="$(dirname "$secret_journal")/commands.log"
if grep -R -F "$canary" "$secret_command_log" "$HOME_DIR" 2>/dev/null; then
echo 'credential canary leaked to persistent installer output' >&2; exit 1
fi
if grep -E 'alice:p@ss|bob:pa:ss|carol:p%40ss|token@example|user%3Apass|QWxhZGRpbjpvcGVu|Ym9iOnNlY3JldA|session=abc123|sid=xyz789' "$secret_command_log" >/dev/null; then
echo 'credentialed URL userinfo leaked to persistent installer output' >&2; exit 1
fi
if [[ "$(cat "$TMP/canary-observed" 2>/dev/null || true)" != "$canary" ]]; then
echo 'credential canary positive control was not exercised' >&2; exit 1
fi
if find "$TMPDIR" -maxdepth 1 -type f \( -name 'mosaic-phase-redacted.*' -o -name 'mosaic-post-redacted.*' \) -print -quit | grep -q .; then
echo 'redacted diagnostic staging file survived normal completion' >&2; exit 1
fi
printf '[test] framework nested capture redacts the same canary and URL variants\n'
framework_test_home="$TMP/framework-redact-home"
framework_target="$framework_test_home/.config/mosaic"
framework_cli="$TMP/framework-redact-cli"
framework_log="$TMP/framework-redact-commands.log"
framework_status="$TMP/framework-redact-status.tsv"
mkdir -p "$framework_test_home"; : > "$framework_log"; : > "$framework_status"
cat > "$framework_cli" <<'FRAMEWORK_CLI'
#!/usr/bin/env bash
printf 'nested authToken=%s\n' "${MOSAIC_INSTALL_SECRET_CANARY:?}"
printf 'nested=https://alice:p@[email protected]/a https://bob:pa:[email protected]/b https://carol:p%%[email protected]/c https://[email protected]/d https://user%%[email protected]/e\n'
printf 'Authorization: Basic QWxhZGRpbjpvcGVu\n//registry/:_auth=Ym9iOnNlY3JldA==\nCookie: session=abc123\nSet-Cookie: sid=xyz789\n'
exit 1
FRAMEWORK_CLI
chmod 0755 "$framework_cli"
set +e
FRAMEWORK_OUTPUT="$(
HOME="$framework_test_home" MOSAIC_HOME="$framework_target" MOSAIC_INSTALL_MODE=overwrite \
MOSAIC_CLI_PATH="$framework_cli" MOSAIC_INSTALL_SECRET_CANARY="$canary" \
MOSAIC_INSTALL_COMMAND_LOG="$framework_log" MOSAIC_INSTALL_PHASE_STATUS_FILE="$framework_status" \
MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1 MOSAIC_SKIP_SKILLS_SYNC=1 \
bash "$ROOT/packages/mosaic/framework/install.sh" 2>&1
)"
framework_install_status=$?
set -e
[[ "$framework_install_status" -eq 0 ]]
if grep -Eq "$canary|alice:p@ss|bob:pa:ss|carol:p%40ss|token@example|user%3Apass|QWxhZGRpbjpvcGVu|Ym9iOnNlY3JldA|session=abc123|sid=xyz789" <<<"$FRAMEWORK_OUTPUT" \
|| grep -Eq "$canary|alice:p@ss|bob:pa:ss|carol:p%40ss|token@example|user%3Apass|QWxhZGRpbjpvcGVu|Ym9iOnNlY3JldA|session=abc123|sid=xyz789" "$framework_log"; then
echo 'framework nested capture leaked credential diagnostics' >&2; exit 1
fi
[[ "$(grep -oF '[REDACTED]@' "$framework_log" | wc -l | tr -d ' ')" -ge 5 ]] \
|| { echo 'framework URL redaction controls were not exercised' >&2; exit 1; }
printf '[test] real P2-P8 actions run under fault injection and restore actual surfaces\n'
for phase in P2 P3 P4 P5 P6 P7 P8; do
rm -rf "$HOME_DIR" "$STATE" "$TMP/fault-$phase"; mkdir -p "$HOME_DIR" "$STATE" "$TMP/fault-$phase"
printf 'operator-sentinel\n' > "$HOME_DIR/operator.txt"
reset_state
before="$(tree_fingerprint "$HOME_DIR")"
set +e
HOME="$HOME_DIR" MOSAIC_HOME="$MOSAIC_HOME" MOSAIC_PREFIX="$PREFIX" \
MOSAIC_INSTALL_STATE_DIR="$TMP/fault-$phase" MOSAIC_INSTALL_FAULT_AFTER="$phase" \
MOSAIC_INSTALL_SELF_TEST_ALLOW=1 MOSAIC_NO_COLOR=1 \
MOSAIC_TEST_NPM_LOG="$LOG" MOSAIC_TEST_STATE="$STATE" \
PATH="$FAKE_BIN:/usr/local/bin:/usr/bin:/bin" \
bash "$ROOT/tools/install.sh" --state-machine-self-test --next --yes \
>"$TMP/fault-$phase.log" 2>&1
status=$?
set -e
[[ "$status" -eq 97 ]] || { echo "$phase real fault expected 97, got $status" >&2; exit 1; }
[[ -s "$LOG" ]] || { echo "$phase fault never entered the real action path" >&2; exit 1; }
[[ "$(tree_fingerprint "$HOME_DIR")" == "$before" ]] || { echo "$phase real rollback mismatch" >&2; exit 1; }
grep -q "phase=$phase" "$TMP/fault-$phase.log"
if find "$TMP/fault-$phase" -type f -exec grep -l '"status"[[:space:]]*:[[:space:]]*"in-progress"' {} + 2>/dev/null | grep -q .; then
echo "$phase left an in-progress transaction" >&2; exit 1
fi
done
printf '[test] stale projection is preserved while the real fault path acquires a free OS lock\n'
rm -rf "$HOME_DIR" "$STATE" "$TMP/stale-state"; mkdir -p "$HOME_DIR" "$STATE" "$TMP/stale-state"
printf '{"status":"in-progress","journal":"%s"}\n' "$TMP/stale-state/dead-run/journal.ndjson" > "$TMP/stale-state/active.json"
reset_state
set +e
HOME="$HOME_DIR" MOSAIC_HOME="$MOSAIC_HOME" MOSAIC_PREFIX="$PREFIX" \
MOSAIC_INSTALL_STATE_DIR="$TMP/stale-state" MOSAIC_INSTALL_FAULT_AFTER=P2 \
MOSAIC_INSTALL_SELF_TEST_ALLOW=1 MOSAIC_NO_COLOR=1 \
MOSAIC_TEST_NPM_LOG="$LOG" MOSAIC_TEST_STATE="$STATE" \
PATH="$FAKE_BIN:/usr/local/bin:/usr/bin:/bin" \
bash "$ROOT/tools/install.sh" --state-machine-self-test --next --yes >"$TMP/stale.log" 2>&1
stale_status=$?
set -e
[[ "$stale_status" -eq 97 ]]
find "$TMP/stale-state" -name prior-active.json -type f -print -quit | grep -q .
[[ "$(node -p "require('$TMP/stale-state/active.json').status")" == rolled-back ]]
echo "[test] installer next lane tests passed"