From 932a4cb9cc630f42c8a4055c0cd5fc3efaf39606 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Thu, 16 Jul 2026 10:41:46 -0700 Subject: [PATCH 1/5] fix(dcode): close legacy probe descriptor Signed-off-by: Apurv Kumaria --- .../dcode-launcher.sh | 5 ++++ test/dcode-managed-exec.test.ts | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/agents/langchain-deepagents-code/dcode-launcher.sh b/agents/langchain-deepagents-code/dcode-launcher.sh index 85c87aa3ed4..ed16b26b3b4 100755 --- a/agents/langchain-deepagents-code/dcode-launcher.sh +++ b/agents/langchain-deepagents-code/dcode-launcher.sh @@ -201,6 +201,11 @@ if [ "$0" = "$MANAGED_EXEC_LAUNCHER" ]; then printf '%s\n' 'dcode-managed-exec requires a command.' >&2 exit 64 fi + # Invalid state: OpenShell can preserve auxiliary descriptors from its + # transport, but route-probe evidence must travel only on stdout/stderr. + # Close the legacy descriptor before the managed command starts so sandbox + # startup code cannot reuse the former fd 3 probe channel (#7031). + exec 3>&- exec "$@" fi diff --git a/test/dcode-managed-exec.test.ts b/test/dcode-managed-exec.test.ts index a45e1116ee7..e052087cf2e 100644 --- a/test/dcode-managed-exec.test.ts +++ b/test/dcode-managed-exec.test.ts @@ -161,6 +161,36 @@ describe("Deep Agents Code side-effect-free managed exec", () => { } }); + it("closes the legacy inference-probe descriptor before managed exec (#7031)", () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); + try { + const { launcherPath, rlimitMarkerPath, wrapperMarkerPath } = + makeLauncherFixture(tempDir); + + const result = spawnSync( + launcherPath, + [ + "/bin/sh", + "-c", + 'if printf FORGED 2>/dev/null >&3; then printf FD3_OPEN; else printf FD3_CLOSED; fi', + ], + { + env: { PATH: process.env.PATH ?? "/usr/bin:/bin" }, + encoding: "utf8", + stdio: ["ignore", "pipe", "pipe", "pipe"], + }, + ); + + expect(result.status, result.stderr).toBe(0); + expect(result.stdout).toBe("FD3_CLOSED"); + expect(result.output[3]).toBe(""); + expect(fs.readFileSync(rlimitMarkerPath, "utf8")).toBe("hardened\nverified\n"); + expect(fs.existsSync(wrapperMarkerPath)).toBe(false); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + it("fails closed without a managed command and preserves the marker (#6504)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { From bf7f14433f16649ce166e7cbf24402fe7829cf76 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Thu, 16 Jul 2026 10:43:38 -0700 Subject: [PATCH 2/5] chore(dcode): apply probe test formatting Signed-off-by: Apurv Kumaria --- test/dcode-managed-exec.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/dcode-managed-exec.test.ts b/test/dcode-managed-exec.test.ts index e052087cf2e..4beaefd17de 100644 --- a/test/dcode-managed-exec.test.ts +++ b/test/dcode-managed-exec.test.ts @@ -164,15 +164,14 @@ describe("Deep Agents Code side-effect-free managed exec", () => { it("closes the legacy inference-probe descriptor before managed exec (#7031)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, rlimitMarkerPath, wrapperMarkerPath } = - makeLauncherFixture(tempDir); + const { launcherPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir); const result = spawnSync( launcherPath, [ "/bin/sh", "-c", - 'if printf FORGED 2>/dev/null >&3; then printf FD3_OPEN; else printf FD3_CLOSED; fi', + "if printf FORGED 2>/dev/null >&3; then printf FD3_OPEN; else printf FD3_CLOSED; fi", ], { env: { PATH: process.env.PATH ?? "/usr/bin:/bin" }, From 11382f8490be2cb501db661f4b1fb924a9878c87 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Thu, 16 Jul 2026 10:51:56 -0700 Subject: [PATCH 3/5] test(dcode): exercise installed managed helper Signed-off-by: Apurv Kumaria --- test/dcode-managed-exec.test.ts | 63 ++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/test/dcode-managed-exec.test.ts b/test/dcode-managed-exec.test.ts index 4beaefd17de..c10f108d62b 100644 --- a/test/dcode-managed-exec.test.ts +++ b/test/dcode-managed-exec.test.ts @@ -44,13 +44,21 @@ function makeLauncherFixture( tempDir: string, options: { installRlimitHelper?: RlimitHelperInstaller } = {}, ): { - launcherPath: string; + managedExecPath: string; markerPath: string; rlimitMarkerPath: string; wrapperMarkerPath: string; } { const installRlimitHelper = options.installRlimitHelper ?? installDefaultRlimitHelper; - const launcherPath = path.join(tempDir, "dcode-launcher.sh"); + const launcherSourcePath = path.join(tempDir, "dcode-launcher.sh"); + const managedExecPath = path.join( + tempDir, + "usr", + "local", + "lib", + "nemoclaw", + "dcode-managed-exec", + ); const markerPath = path.join(tempDir, "observability-enabled"); const hostPath = path.join(tempDir, "trusted-proxy-host"); const portPath = path.join(tempDir, "trusted-proxy-port"); @@ -67,7 +75,7 @@ function makeLauncherFixture( ) .replace( 'readonly MANAGED_EXEC_LAUNCHER="/usr/local/lib/nemoclaw/dcode-managed-exec"', - `readonly MANAGED_EXEC_LAUNCHER="${launcherPath}"`, + `readonly MANAGED_EXEC_LAUNCHER="${managedExecPath}"`, ) .replace( 'readonly MANAGED_OBSERVABILITY_MARKER="/sandbox/.deepagents/.nemoclaw-observability-enabled"', @@ -94,20 +102,25 @@ function makeLauncherFixture( `#!/bin/sh\nprintf ran > ${JSON.stringify(wrapperMarkerPath)}\nexit 99\n`, { mode: 0o755 }, ); - fs.writeFileSync(launcherPath, source, { mode: 0o755 }); - return { launcherPath, markerPath, rlimitMarkerPath, wrapperMarkerPath }; + fs.writeFileSync(launcherSourcePath, source, { mode: 0o755 }); + // Mirror the Dockerfile's separate regular-file install instead of invoking + // the launcher source fixture directly. + fs.mkdirSync(path.dirname(managedExecPath), { recursive: true }); + fs.copyFileSync(launcherSourcePath, managedExecPath); + fs.chmodSync(managedExecPath, 0o755); + return { managedExecPath, markerPath, rlimitMarkerPath, wrapperMarkerPath }; } describe("Deep Agents Code side-effect-free managed exec", () => { it("preserves enabled observability during route diagnostics (#6504)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, markerPath, rlimitMarkerPath, wrapperMarkerPath } = + const { managedExecPath, markerPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir); fs.writeFileSync(markerPath, "1\n", { mode: 0o444 }); const result = spawnSync( - launcherPath, + managedExecPath, [ "/bin/sh", "-c", @@ -132,11 +145,11 @@ describe("Deep Agents Code side-effect-free managed exec", () => { it("preserves disabled observability during route diagnostics (#6504)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, markerPath, rlimitMarkerPath, wrapperMarkerPath } = + const { managedExecPath, markerPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir); const result = spawnSync( - launcherPath, + managedExecPath, [ "/bin/sh", "-c", @@ -164,10 +177,12 @@ describe("Deep Agents Code side-effect-free managed exec", () => { it("closes the legacy inference-probe descriptor before managed exec (#7031)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir); + const { managedExecPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir); + expect(managedExecPath).toMatch(/\/usr\/local\/lib\/nemoclaw\/dcode-managed-exec$/); + expect(fs.lstatSync(managedExecPath).isSymbolicLink()).toBe(false); const result = spawnSync( - launcherPath, + managedExecPath, [ "/bin/sh", "-c", @@ -193,11 +208,11 @@ describe("Deep Agents Code side-effect-free managed exec", () => { it("fails closed without a managed command and preserves the marker (#6504)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, markerPath, rlimitMarkerPath, wrapperMarkerPath } = + const { managedExecPath, markerPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir); fs.writeFileSync(markerPath, "1\n", { mode: 0o444 }); - const result = spawnSync(launcherPath, [], { + const result = spawnSync(managedExecPath, [], { env: { PATH: process.env.PATH ?? "/usr/bin:/bin" }, encoding: "utf8", }); @@ -216,11 +231,14 @@ describe("Deep Agents Code side-effect-free managed exec", () => { it("refuses a direct managed launch when the rlimit helper is missing (#6545)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir, { - installRlimitHelper: () => undefined, - }); + const { managedExecPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture( + tempDir, + { + installRlimitHelper: () => undefined, + }, + ); - const result = spawnSync(launcherPath, ["/bin/sh", "-c", "printf SHOULD_NOT_RUN"], { + const result = spawnSync(managedExecPath, ["/bin/sh", "-c", "printf SHOULD_NOT_RUN"], { env: { PATH: process.env.PATH ?? "/usr/bin:/bin" }, encoding: "utf8", }); @@ -240,11 +258,14 @@ describe("Deep Agents Code side-effect-free managed exec", () => { it("refuses a direct managed launch when effective rlimits fail verification (#6545)", () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-managed-exec-")); try { - const { launcherPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture(tempDir, { - installRlimitHelper: installFailingVerificationRlimitHelper, - }); + const { managedExecPath, rlimitMarkerPath, wrapperMarkerPath } = makeLauncherFixture( + tempDir, + { + installRlimitHelper: installFailingVerificationRlimitHelper, + }, + ); - const result = spawnSync(launcherPath, ["/bin/sh", "-c", "printf SHOULD_NOT_RUN"], { + const result = spawnSync(managedExecPath, ["/bin/sh", "-c", "printf SHOULD_NOT_RUN"], { env: { PATH: process.env.PATH ?? "/usr/bin:/bin" }, encoding: "utf8", }); From 2ba2b9ee3f92e0fafe3e94a1f47b5cbac1eb0adf Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Thu, 16 Jul 2026 11:18:03 -0700 Subject: [PATCH 4/5] test(dcode): prove broken probe blocks attach Signed-off-by: Apurv Kumaria --- .../07-deepagents-code-headless-inference.sh | 87 ++++++++++++++++++- test/langchain-deepagents-code-image.test.ts | 8 ++ 2 files changed, 91 insertions(+), 4 deletions(-) diff --git a/test/e2e/e2e-cloud-experimental/checks/07-deepagents-code-headless-inference.sh b/test/e2e/e2e-cloud-experimental/checks/07-deepagents-code-headless-inference.sh index 0e34f9887c4..b4ec126d9f2 100755 --- a/test/e2e/e2e-cloud-experimental/checks/07-deepagents-code-headless-inference.sh +++ b/test/e2e/e2e-cloud-experimental/checks/07-deepagents-code-headless-inference.sh @@ -17,8 +17,10 @@ # proxy routes inference.local when the request follows the normalized path. # Keep these phases in one ordered acceptance check: the absent-DNS observation # must describe the same sandbox used by login, direct-exec, and connect, and the -# final credential scan must cover every captured output. Per-phase diagnostics -# retain failure attribution without splitting that shared evidence boundary. +# final credential scan must cover every captured output. A second connect run +# sends untrusted evidence through the image-installed route-probe helper and +# must stop before session attach. Per-phase diagnostics retain failure +# attribution without splitting that shared evidence boundary. set -euo pipefail @@ -79,6 +81,67 @@ nemoclaw_connect_probe() { "${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" "$SANDBOX_NAME" connect --probe-only 2>&1 } +dcode_connect_fail_closed_contract() ( + local fixture_dir real_openshell openshell_shim probe_marker attach_marker + local connect_output connect_exit + fixture_dir="$(mktemp -d "${TMPDIR:-/tmp}/${PREFIX}.XXXXXX")" + trap 'rm -rf "$fixture_dir"' EXIT + real_openshell="$(command -v openshell)" + openshell_shim="${fixture_dir}/openshell" + probe_marker="${fixture_dir}/managed-probe-used" + attach_marker="${fixture_dir}/session-attach-invoked" + + cat >"$openshell_shim" <<'SHIM' +#!/bin/bash +set -euo pipefail + +readonly REAL_OPENSHELL="${OPENSHELL_NEMOCLAW_E2E_REAL_BIN:?}" +readonly PROBE_MARKER="${OPENSHELL_NEMOCLAW_E2E_PROBE_MARKER:?}" +readonly ATTACH_MARKER="${OPENSHELL_NEMOCLAW_E2E_ATTACH_MARKER:?}" + +if [ "${1:-}" = "sandbox" ] && [ "${2:-}" = "connect" ]; then + : >"$ATTACH_MARKER" + exit 97 +fi + +args=("$@") +for ((index = 0; index + 3 < ${#args[@]}; index += 1)); do + if [ "${args[index]}" = "/usr/local/lib/nemoclaw/dcode-managed-exec" ] \ + && [ "${args[index + 1]}" = "/bin/sh" ] \ + && [ "${args[index + 2]}" = "-c" ]; then + : >"$PROBE_MARKER" + args[index + 3]='printf "%s\n" "UNTRUSTED PREAMBLE" "BROKEN 000"' + exec "$REAL_OPENSHELL" "${args[@]}" + fi +done + +exec "$REAL_OPENSHELL" "$@" +SHIM + chmod 700 "$openshell_shim" + + if connect_output="$(env \ + NEMOCLAW_OPENSHELL_BIN="$openshell_shim" \ + OPENSHELL_NEMOCLAW_E2E_REAL_BIN="$real_openshell" \ + OPENSHELL_NEMOCLAW_E2E_PROBE_MARKER="$probe_marker" \ + OPENSHELL_NEMOCLAW_E2E_ATTACH_MARKER="$attach_marker" \ + "${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}" "$SANDBOX_NAME" connect 2>&1)"; then + connect_exit=0 + else + connect_exit=$? + fi + + printf '%s\n' "$connect_output" + printf 'NEMOCLAW_DCODE_UNTRUSTED_CONNECT_EXIT:%s\n' "$connect_exit" + if [ -f "$probe_marker" ]; then + printf '%s\n' NEMOCLAW_DCODE_IMAGE_PROBE_USED + fi + if [ -e "$attach_marker" ]; then + printf '%s\n' NEMOCLAW_DCODE_SESSION_ATTACH_INVOKED + else + printf '%s\n' NEMOCLAW_DCODE_SESSION_ATTACH_NOT_INVOKED + fi +) + sandbox_login_proxy_contract() { # OpenShell rejects CR/LF in any exec argv element, so keep this remote login # command on one physical line. inference.local is intentionally absent from @@ -408,7 +471,22 @@ DCODE_EXIT:${direct_exit}" fail_test "nemoclaw connect --probe-only rejected the managed inference route (exit ${connect_exit})" fi - # 8. No real secrets in managed config, runtime env files, artifacts, logs, or captured output. + # 8. Untrusted evidence from the image-installed helper must fail closed + # before the user-facing connect path can invoke interactive session attach. + fail_closed_connect_output="$(dcode_connect_fail_closed_contract || true)" + fail_closed_connect_exit="$(printf '%s\n' "$fail_closed_connect_output" | sed -n 's/^NEMOCLAW_DCODE_UNTRUSTED_CONNECT_EXIT:\([0-9][0-9]*\)$/\1/p' | tail -n1)" + if [ -n "$fail_closed_connect_exit" ] \ + && [ "$fail_closed_connect_exit" -ne 0 ] \ + && grep -Fq NEMOCLAW_DCODE_IMAGE_PROBE_USED <<<"$fail_closed_connect_output" \ + && grep -Fq NEMOCLAW_DCODE_SESSION_ATTACH_NOT_INVOKED <<<"$fail_closed_connect_output" \ + && grep -Fq "UNTRUSTED PREAMBLE" <<<"$fail_closed_connect_output" \ + && grep -Fq "did not return a trusted result" <<<"$fail_closed_connect_output"; then + pass "connect rejects untrusted image-backed route evidence before session attach" + else + fail_test "connect did not fail closed before session attach for untrusted image-backed route evidence" + fi + + # 9. No real secrets in managed config, runtime env files, artifacts, logs, or captured output. leak_scan="$(sandbox_exec "$(sandbox_artifact_scan_command)" || true)" combined="${config_output} ${openrouter_identity_output} @@ -424,7 +502,8 @@ ${proxy_contract_output} ${route_output} ${headless_output} ${direct_headless_output} -${connect_output}" +${connect_output} +${fail_closed_connect_output}" if printf '%s' "$combined" | contains_secret; then fail_test "secret-shaped value found in config/env/output (redacted from log)" else diff --git a/test/langchain-deepagents-code-image.test.ts b/test/langchain-deepagents-code-image.test.ts index add08030630..91b79df1190 100644 --- a/test/langchain-deepagents-code-image.test.ts +++ b/test/langchain-deepagents-code-image.test.ts @@ -802,6 +802,14 @@ describe("LangChain Deep Agents Code image contracts", () => { "nemoclaw_connect_probe", "${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}", "connect --probe-only 2>&1", + "dcode_connect_fail_closed_contract", + 'NEMOCLAW_OPENSHELL_BIN="$openshell_shim"', + '"$SANDBOX_NAME" connect 2>&1', + 'exec "$REAL_OPENSHELL" "$@"', + "UNTRUSTED PREAMBLE", + "NEMOCLAW_DCODE_IMAGE_PROBE_USED", + "NEMOCLAW_DCODE_SESSION_ATTACH_NOT_INVOKED", + "connect rejects untrusted image-backed route evidence before session attach", "direct-exec dcode -n reached managed inference", "connect --probe-only accepted the managed inference route", 'sandbox_login_exec "cd /sandbox', From ead40e5e7b4cbfbb8dcf4e48622557f3aede0681 Mon Sep 17 00:00:00 2001 From: Apurv Kumaria Date: Thu, 16 Jul 2026 14:00:53 -0700 Subject: [PATCH 5/5] test(dcode): keep image contract behavior-focused Signed-off-by: Apurv Kumaria --- test/langchain-deepagents-code-image.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/langchain-deepagents-code-image.test.ts b/test/langchain-deepagents-code-image.test.ts index 91b79df1190..663a49f3526 100644 --- a/test/langchain-deepagents-code-image.test.ts +++ b/test/langchain-deepagents-code-image.test.ts @@ -803,12 +803,6 @@ describe("LangChain Deep Agents Code image contracts", () => { "${NEMOCLAW_CLI_BIN:-${REPO:-.}/bin/nemoclaw.js}", "connect --probe-only 2>&1", "dcode_connect_fail_closed_contract", - 'NEMOCLAW_OPENSHELL_BIN="$openshell_shim"', - '"$SANDBOX_NAME" connect 2>&1', - 'exec "$REAL_OPENSHELL" "$@"', - "UNTRUSTED PREAMBLE", - "NEMOCLAW_DCODE_IMAGE_PROBE_USED", - "NEMOCLAW_DCODE_SESSION_ATTACH_NOT_INVOKED", "connect rejects untrusted image-backed route evidence before session attach", "direct-exec dcode -n reached managed inference", "connect --probe-only accepted the managed inference route",