From e1b790ae27b7d219568e0152c356298dd2ffc3f1 Mon Sep 17 00:00:00 2001 From: 13ernkastel Date: Wed, 1 Apr 2026 08:43:32 +0800 Subject: [PATCH] fix: disable unsupported OpenClaw update hints --- Dockerfile | 1 + docs/reference/troubleshooting.md | 12 +++++++++ test/e2e-gateway-isolation.sh | 42 +++++++++++++++++++------------ 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index d62ee0558..ac7bc4066 100644 --- a/Dockerfile +++ b/Dockerfile @@ -103,6 +103,7 @@ config = { \ 'agents': {'defaults': {'model': {'primary': primary_model_ref}}}, \ 'models': {'mode': 'merge', 'providers': providers}, \ 'channels': {'defaults': {'configWrites': False}}, \ + 'update': {'checkOnStart': False}, \ 'gateway': { \ 'mode': 'local', \ 'controlUi': { \ diff --git a/docs/reference/troubleshooting.md b/docs/reference/troubleshooting.md index 78d7861ec..0bc25405f 100644 --- a/docs/reference/troubleshooting.md +++ b/docs/reference/troubleshooting.md @@ -237,6 +237,18 @@ The status command detects the sandbox context and reports "active (inside sandb Run `openshell sandbox list` on the host to check the underlying sandbox state. +### `openclaw update` hangs or times out inside the sandbox + +This is expected for the current NemoClaw deployment model. +NemoClaw installs `openclaw` into the sandbox image at build time, so the CLI is image-pinned rather than updated in place inside a running sandbox. + +Do not run `openclaw update` inside the sandbox. +Instead: + +1. Upgrade to a NemoClaw release that includes the newer `openclaw` version. +2. If you build NemoClaw from source, bump the pinned `openclaw` version in `Dockerfile.base` and rebuild the sandbox base image. +3. Back up any workspace files you need, then recreate the sandbox so it uses the rebuilt image. + ### Inference requests time out Verify that the inference provider endpoint is reachable from the host. diff --git a/test/e2e-gateway-isolation.sh b/test/e2e-gateway-isolation.sh index cb4c8d698..c01bf021a 100755 --- a/test/e2e-gateway-isolation.sh +++ b/test/e2e-gateway-isolation.sh @@ -102,9 +102,19 @@ else fail "config hash mismatch: $OUT" fi -# ── Test 5: Config hash is not writable by sandbox ─────────────── +# ── Test 5: Update hints are disabled in sandbox config ────────── -info "5. Config hash not writable by sandbox user" +info "5. Sandbox config disables startup update hints" +OUT=$(run_as_root "python3 -c 'import json; cfg=json.load(open(\"/sandbox/.openclaw/openclaw.json\")); print(\"OK\" if cfg.get(\"update\", {}).get(\"checkOnStart\") is False else \"BAD\")'") +if echo "$OUT" | grep -q "OK"; then + pass "startup update hints disabled" +else + fail "startup update hints not disabled: $OUT" +fi + +# ── Test 6: Config hash is not writable by sandbox ─────────────── + +info "6. Config hash not writable by sandbox user" OUT=$(run_as_sandbox "echo fake > /sandbox/.openclaw/.config-hash 2>&1 || echo BLOCKED") if echo "$OUT" | grep -q "BLOCKED\|Permission denied"; then pass "sandbox cannot tamper with config hash" @@ -112,9 +122,9 @@ else fail "sandbox CAN write to config hash: $OUT" fi -# ── Test 6: gosu is installed ──────────────────────────────────── +# ── Test 7: gosu is installed ──────────────────────────────────── -info "6. gosu binary is available" +info "7. gosu binary is available" OUT=$(run_as_root "command -v gosu && gosu --version") if echo "$OUT" | grep -q "gosu"; then pass "gosu installed" @@ -122,9 +132,9 @@ else fail "gosu not found: $OUT" fi -# ── Test 7: Entrypoint PATH is locked to system dirs ───────────── +# ── Test 8: Entrypoint PATH is locked to system dirs ───────────── -info "7. Entrypoint locks PATH to system directories" +info "8. Entrypoint locks PATH to system directories" # Walk the entrypoint line-by-line, eval only export lines, stop after PATH. OUT=$(run_as_root "bash -c 'while IFS= read -r line; do case \"\$line\" in export\\ *) eval \"\$line\" 2>/dev/null;; esac; case \"\$line\" in \"export PATH=\"*) break;; esac; done < /usr/local/bin/nemoclaw-start; echo \$PATH'") if echo "$OUT" | grep -q "^/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin$"; then @@ -133,9 +143,9 @@ else fail "PATH not locked as expected: $OUT" fi -# ── Test 8: openclaw resolves to expected absolute path ────────── +# ── Test 9: openclaw resolves to expected absolute path ────────── -info "8. Gateway runs the expected openclaw binary" +info "9. Gateway runs the expected openclaw binary" OUT=$(run_as_root "gosu gateway which openclaw") if [ "$OUT" = "/usr/local/bin/openclaw" ]; then pass "openclaw resolves to /usr/local/bin/openclaw" @@ -143,9 +153,9 @@ else fail "openclaw resolves to unexpected path: $OUT" fi -# ── Test 9: Symlinks point to expected targets ─────────────────── +# ── Test 10: Symlinks point to expected targets ────────────────── -info "9. All .openclaw symlinks point to .openclaw-data" +info "10. All .openclaw symlinks point to .openclaw-data" FAILED_LINKS="" for link in agents extensions workspace skills hooks identity devices canvas cron; do OUT=$(run_as_root "readlink -f /sandbox/.openclaw/$link") @@ -159,9 +169,9 @@ else fail "symlink targets wrong:$FAILED_LINKS" fi -# ── Test 10: iptables is installed (required for network policy enforcement) ── +# ── Test 11: iptables is installed (required for network policy enforcement) ── -info "10. iptables is installed" +info "11. iptables is installed" OUT=$(run_as_root "iptables --version 2>&1") if echo "$OUT" | grep -q "iptables v"; then pass "iptables installed: $OUT" @@ -169,9 +179,9 @@ else fail "iptables not found — sandbox network policies will not be enforced: $OUT" fi -# ── Test 11: Sandbox user cannot kill gateway-user processes ───── +# ── Test 12: Sandbox user cannot kill gateway-user processes ───── -info "11. Sandbox user cannot kill gateway-user processes" +info "12. Sandbox user cannot kill gateway-user processes" # Start a dummy process as gateway, try to kill it as sandbox OUT=$(docker run --rm --entrypoint "" "$IMAGE" bash -c ' gosu gateway sleep 60 & @@ -187,9 +197,9 @@ else fail "sandbox CAN kill gateway processes: $OUT" fi -# ── Test 12: Dangerous capabilities are dropped by entrypoint ──── +# ── Test 13: Dangerous capabilities are dropped by entrypoint ──── -info "12. Entrypoint drops dangerous capabilities from bounding set" +info "13. Entrypoint drops dangerous capabilities from bounding set" # Run capsh directly with the same --drop flags as the entrypoint, then # check CapBnd. This avoids running the full entrypoint which starts # gateway services that fail in CI without a running OpenShell environment.