Skip to content

fix(sandbox): reject managed startup env wrapper without nemoclaw-start terminator - #8609

Open
laitingsheng wants to merge 2 commits into
mainfrom
fix/entrypoint-env-wrapper-terminator
Open

fix(sandbox): reject managed startup env wrapper without nemoclaw-start terminator#8609
laitingsheng wants to merge 2 commits into
mainfrom
fix/entrypoint-env-wrapper-terminator

Conversation

@laitingsheng

@laitingsheng laitingsheng commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

The managed startup env wrapper only rejected a missing nemoclaw-start terminator when the argument sequence carried NEMOCLAW_STARTUP_PROFILE_B64 or NEMOCLAW_CORPORATE_CA_B64, so env NEMOCLAW_AUTO_PAIR_FAST_REENTRY_INTERVAL_SECS=5 /bin/sh returned success and kept the unnormalized arguments. It now rejects any supported managed variable name that appears in the leading assignment run without the terminator, while a user command tail that only looks like an assignment still passes through unchanged.

Related Issue

Fixes #8595

Changes

  • Lift the supported-variable set in scripts/lib/entrypoint-env-wrapper.sh out of the inline case into one _nemoclaw_supported_names value, so the terminator-missing branch and the assignment validation loop read the same list instead of drifting apart.
  • Reject a terminator-less sequence when any supported managed name appears in the leading assignment run. The existing rejection of NEMOCLAW_STARTUP_PROFILE_B64 and NEMOCLAW_CORPORATE_CA_B64 in any argument position is unchanged, so no current guarantee is relaxed.
  • Scope the wider check to the leading assignment run so env FOO=bar /bin/sh -c NEMOCLAW_SANDBOX_NAME=probe stays a user command. test/entrypoint-env-wrapper.test.ts pins that boundary.
  • Add three fail-closed cases to test/entrypoint-env-wrapper.test.ts covering the reported sequence, a two-assignment variant, and a trust payload in the command tail, and give every case in that table a distinct name so a failure identifies the broken contract.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: the wrapper is an in-container root entrypoint contract with no page in docs/, and the only producer of this argument sequence is the launch renderer, which always emits the terminator. The newly rejected shape is reachable only by a hand-built container command.
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification:
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: no-docs-needed
  • Evidence: no documentation path changed. The reviewer searched docs/ and .agents/ for the wrapper filename, the argument grammar, and each of its [SECURITY] strings and found no reference, checked the docs/CONTRIBUTING.md "When to Update Docs" conditions and matched none, and confirmed that no documented docker run or docker exec example passes a command of the affected shape. Its two substantive prose findings were applied in 4ad4655: a comment claim that overstated the rejection rule and contradicted the pass-through test, and a templated test title that rendered identically for five of seven cases.
  • Agent: Claude Code

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: npx vitest run test/entrypoint-env-wrapper.test.ts — 12/12 pass. npx vitest run test/pr-risk-plan.test.ts test/sandbox-provisioning-helper-permissions.test.ts test/sandbox-rlimit-hooks.test.ts test/hermes-doctor-config-hash.test.ts — 128/128 pass. test/hermes-start.test.ts, test/service-env.test.ts, test/sandbox-provisioning.test.ts, test/sandbox-build-context.test.ts, test/openclaw-final-image-layout.test.ts, and test/hermes-final-image-layout.test.ts also pass.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Tinson Lai tinsonl@nvidia.com

Summary by CodeRabbit

  • Bug Fixes
    • Improved validation of environment variable assignments during application startup.
    • Preserved valid command arguments that resemble environment assignments.
    • Continued blocking unsafe startup and profile variables in both leading assignments and command arguments.
    • Added support for validating multiple managed variables and handling invalid assignment sequences correctly.

…rt terminator

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
…cases

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The entrypoint wrapper now uses a centralized managed-variable allowlist, tracks leading assignments, rejects malformed startup handoffs, and preserves command-tail arguments. Tests cover valid command tails and unsafe or malformed assignment sequences.

Changes

Managed environment validation

Layer / File(s) Summary
Wrapper parsing and validation
scripts/lib/entrypoint-env-wrapper.sh
The wrapper centralizes supported environment names, tracks the leading assignment sequence, rejects managed variables when the nemoclaw-start handoff is missing or malformed, and uses the allowlist for assignment validation.
Regression coverage
test/entrypoint-env-wrapper.test.ts
Tests verify command-tail preservation and rejection of unsafe managed variables, malformed assignment sequences, unrelated commands, and missing startup terminators.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: brandonpelfrey

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the sandbox wrapper fix and the missing nemoclaw-start terminator.
Linked Issues check ✅ Passed The changes reject missing nemoclaw-start terminators, centralize managed variables, and add tests for issue #8595 requirements.
Out of Scope Changes check ✅ Passed The implementation and tests remain focused on managed startup environment-wrapper validation and issue #8595.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/entrypoint-env-wrapper-terminator

Comment @coderabbitai help to get the list of available commands.

@laitingsheng laitingsheng added area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression labels Aug 8, 2026
@github-code-quality

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 4ad4655 in the fix/entrypoint-env-w... branch remains at 96%, unchanged from commit aeaaf1a in the main branch.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/entrypoint-env-wrapper.test.ts`:
- Around line 87-100: Update the two affected test titles in the enclosing
describe block, including “leaves a user command tail that only looks like a
managed assignment,” by appending the exact suffix “(`#8595`)” to each title while
preserving their existing wording.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4c49839e-841c-4474-9014-9a9e4f262e5d

📥 Commits

Reviewing files that changed from the base of the PR and between aeaaf1a and 4ad4655.

📒 Files selected for processing (2)
  • scripts/lib/entrypoint-env-wrapper.sh
  • test/entrypoint-env-wrapper.test.ts

Comment on lines +87 to +100
it("leaves a user command tail that only looks like a managed assignment", () => {
const result = runNormalizer([
"env",
"FOO=bar",
"/bin/sh",
"-c",
"NEMOCLAW_SANDBOX_NAME=probe",
]);

expect(result.status).toBe(0);
expect(result.stdout).toContain(
"ARG=env\nARG=FOO=bar\nARG=/bin/sh\nARG=-c\nARG=NEMOCLAW_SANDBOX_NAME=probe\n",
);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline test/entrypoint-env-wrapper.test.ts --items all
sed -n '1,155p' test/entrypoint-env-wrapper.test.ts

Repository: NVIDIA/NemoClaw

Length of output: 6925


Append (#8595) to both test titles. The enclosing describe title has no issue suffix.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/entrypoint-env-wrapper.test.ts` around lines 87 - 100, Update the two
affected test titles in the enclosing describe block, including “leaves a user
command tail that only looks like a managed assignment,” by appending the exact
suffix “(`#8595`)” to each title while preserving their existing wording.

Sources: Coding guidelines, Learnings

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · medium confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings match; normalized terminology decisions differ; normalized E2E selections differ; severity counts match.
1 terminology difference from the second opinion

Advisory only. These are normalized differences from the primary terminology receipt.

  • user command tail at scripts/lib/entrypoint-env-wrapper.sh:85: selected only by the second-opinion lane as justified.
5 additional E2E selections from the second opinion

Advisory only. The primary lane did not select these E2E jobs or targets.

  • managed-image-protected-runtime: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • onboard-managed-image-buildless-e2e: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • security-posture: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • sandbox-operations: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • sandbox-survival: The completed second-opinion lane identified E2E coverage that the primary lane omitted.

Second-opinion terminology and E2E selections are advisory. Live E2E does not run automatically for pull requests.

2 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • justified — leading assignment run at scripts/lib/entrypoint-env-wrapper.sh:85: Keep this term. It names the argv boundary that determines whether the normalizer rejects a missing nemoclaw-start terminator.
  • justified — user command tail at test/entrypoint-env-wrapper.test.ts:87: Keep this term. It distinguishes preserved user-command arguments from the managed assignment prefix.

E2E guidance

Advisory only. A maintainer can dispatch the default E2E suite against this exact revision.

Recommended E2E: managed-image-multiarch-startup, device-auth-health, issue-4462-scope-upgrade-approval, openclaw-inference-switch

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu 24.04][Security] managed startup env wrapper accepts a missing nemoclaw-start terminator

1 participant