Skip to content

Commit 32687e3

Browse files
committed
fix: address CodeRabbit review — timeout, pipefail, fail-closed probes, shell injection in test
- Bump e2e-brev workflow timeout-minutes from 60 to 90 - Add fail-fast when launchable setup exceeds 40-min wait - Add pipefail to remote pipeline commands in runRemoteTest and npm ci - Fix backtick shell injection in validateName test loop (use process.argv) - Make sandbox_exec fail closed with __PROBE_FAILED__ sentinel - Add probe failure checks in C6/C7 sandbox assertions
1 parent 5308e74 commit 32687e3

File tree

4 files changed

+35
-10
lines changed

4 files changed

+35
-10
lines changed

.github/workflows/e2e-brev.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
e2e-brev:
9797
if: github.repository == 'NVIDIA/NemoClaw'
9898
runs-on: ubuntu-latest
99-
timeout-minutes: 60
99+
timeout-minutes: 90
100100
steps:
101101
- name: Checkout target branch
102102
uses: actions/checkout@v6

test/e2e/brev-e2e.test.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ function waitForSsh(maxAttempts = 60, intervalMs = 5_000) {
111111

112112
function runRemoteTest(scriptPath) {
113113
const cmd = [
114+
`set -o pipefail`,
114115
`source ~/.nvm/nvm.sh 2>/dev/null || true`,
115116
`cd ${remoteDir}`,
116117
`export npm_config_prefix=$HOME/.local`,
@@ -205,6 +206,14 @@ describe.runIf(hasRequiredVars)("Brev E2E", () => {
205206
execSync(`sleep ${setupPollInterval / 1000}`);
206207
}
207208

209+
// Fail fast if neither readiness marker appeared within the timeout
210+
if (Date.now() - setupStart >= setupMaxWait) {
211+
throw new Error(
212+
`Launchable setup did not complete within ${setupMaxWait / 60_000} minutes. ` +
213+
`Neither '=== Ready ===' in /tmp/launch-plugin.log nor install-ran marker found.`,
214+
);
215+
}
216+
208217
// The launch script installs Docker, OpenShell CLI, clones NemoClaw main,
209218
// and sets up code-server — but it does NOT run `nemoclaw onboard` (that's
210219
// deferred to an interactive code-server terminal). So at this point we have:
@@ -222,7 +231,7 @@ describe.runIf(hasRequiredVars)("Brev E2E", () => {
222231

223232
// Install deps for our branch
224233
console.log(`[${elapsed()}] Running npm ci to sync dependencies...`);
225-
sshWithSecrets(`source ~/.nvm/nvm.sh 2>/dev/null || true && cd ${remoteDir} && npm ci --ignore-scripts 2>&1 | tail -5`, { timeout: 300_000, stream: true });
234+
sshWithSecrets(`set -o pipefail && source ~/.nvm/nvm.sh 2>/dev/null || true && cd ${remoteDir} && npm ci --ignore-scripts 2>&1 | tail -5`, { timeout: 300_000, stream: true });
226235
console.log(`[${elapsed()}] Dependencies synced`);
227236

228237
// Run nemoclaw onboard (non-interactive) — this is the path real users take.

test/e2e/test-credential-sanitization.sh

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,35 @@ fi
6969

7070
SANDBOX_NAME="${NEMOCLAW_SANDBOX_NAME:-e2e-test}"
7171

72-
# Run a command inside the sandbox and capture output
72+
# Run a command inside the sandbox and capture output.
73+
# Returns __PROBE_FAILED__ and exit 1 if SSH setup or execution fails,
74+
# so callers can distinguish "no output" from "probe never ran".
7375
sandbox_exec() {
7476
local cmd="$1"
7577
local ssh_config
7678
ssh_config="$(mktemp)"
77-
openshell sandbox ssh-config "$SANDBOX_NAME" >"$ssh_config" 2>/dev/null
79+
if ! openshell sandbox ssh-config "$SANDBOX_NAME" >"$ssh_config" 2>/dev/null; then
80+
rm -f "$ssh_config"
81+
echo "__PROBE_FAILED__"
82+
return 1
83+
fi
7884

7985
local result
86+
local rc=0
8087
result=$(timeout 60 ssh -F "$ssh_config" \
8188
-o StrictHostKeyChecking=no \
8289
-o UserKnownHostsFile=/dev/null \
8390
-o ConnectTimeout=10 \
8491
-o LogLevel=ERROR \
8592
"openshell-${SANDBOX_NAME}" \
8693
"$cmd" \
87-
2>&1) || true
94+
2>&1) || rc=$?
8895

8996
rm -f "$ssh_config"
97+
if [ "$rc" -ne 0 ] && [ -z "$result" ]; then
98+
echo "__PROBE_FAILED__"
99+
return 1
100+
fi
90101
echo "$result"
91102
}
92103

@@ -396,7 +407,9 @@ section "Phase 2: Runtime Sandbox Credential Check"
396407
info "C6: Checking for auth-profiles.json inside sandbox..."
397408
c6_result=$(sandbox_exec "find /sandbox -name 'auth-profiles.json' 2>/dev/null | head -5")
398409

399-
if [ -z "$c6_result" ]; then
410+
if [ "$c6_result" = "__PROBE_FAILED__" ]; then
411+
fail "C6: Sandbox probe failed — SSH did not execute; cannot verify auth-profiles.json absence"
412+
elif [ -z "$c6_result" ]; then
400413
pass "C6: No auth-profiles.json found inside sandbox"
401414
else
402415
fail "C6: auth-profiles.json found inside sandbox: $c6_result"
@@ -411,7 +424,9 @@ c7_nvapi=$(sandbox_exec "grep -r 'nvapi-' /sandbox/.openclaw/ /sandbox/.nemoclaw
411424
c7_ghp=$(sandbox_exec "grep -r 'ghp_' /sandbox/.openclaw/ /sandbox/.nemoclaw/ 2>/dev/null | grep -v 'STRIPPED' | grep -v '/policies/' | head -5" || true)
412425
c7_npm=$(sandbox_exec "grep -r 'npm_' /sandbox/.openclaw/ /sandbox/.nemoclaw/ 2>/dev/null | grep -v 'STRIPPED' | grep -v '/policies/' | head -5" || true)
413426

414-
if [ -z "$c7_nvapi" ] && [ -z "$c7_ghp" ] && [ -z "$c7_npm" ]; then
427+
if [ "$c7_nvapi" = "__PROBE_FAILED__" ] || [ "$c7_ghp" = "__PROBE_FAILED__" ] || [ "$c7_npm" = "__PROBE_FAILED__" ]; then
428+
fail "C7: Sandbox probe failed — SSH did not execute; cannot verify secret absence"
429+
elif [ -z "$c7_nvapi" ] && [ -z "$c7_ghp" ] && [ -z "$c7_npm" ]; then
415430
pass "C7: No secret patterns (nvapi-, ghp_, npm_) found in sandbox config"
416431
else
417432
fail "C7: Secret patterns found in sandbox — nvapi: ${c7_nvapi:0:100}, ghp: ${c7_ghp:0:100}, npm: ${c7_npm:0:100}"

test/e2e/test-telegram-injection.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,17 +379,18 @@ else
379379
fail "T7: SANDBOX_NAME '--help' was ACCEPTED — option injection possible!"
380380
fi
381381

382-
# Additional invalid names
382+
# Additional invalid names — pass via process.argv to avoid shell expansion of
383+
# backticks and $() in double-quoted node -e strings.
383384
for invalid_name in '$(whoami)' '`id`' 'foo bar' '../etc/passwd' 'UPPERCASE'; do
384385
t_result=$(cd "$REPO" && node -e "
385386
const { validateName } = require('./bin/lib/runner');
386387
try {
387-
validateName('$invalid_name', 'SANDBOX_NAME');
388+
validateName(process.argv[1], 'SANDBOX_NAME');
388389
console.log('ACCEPTED');
389390
} catch (e) {
390391
console.log('REJECTED');
391392
}
392-
" 2>&1)
393+
" -- "$invalid_name" 2>&1)
393394

394395
if echo "$t_result" | grep -q "REJECTED"; then
395396
pass "T6/T7 extra: SANDBOX_NAME '${invalid_name}' correctly rejected"

0 commit comments

Comments
 (0)