Skip to content

fix(sandbox/recover): enforce Hermes env-file secret boundary on probe path#5530

Open
laitingsheng wants to merge 4 commits into
mainfrom
fix/hermes-secret-boundary-on-recover-probe
Open

fix(sandbox/recover): enforce Hermes env-file secret boundary on probe path#5530
laitingsheng wants to merge 4 commits into
mainfrom
fix/hermes-secret-boundary-on-recover-probe

Conversation

@laitingsheng

@laitingsheng laitingsheng commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

nemohermes <name> recover did not re-evaluate the documented Hermes secret boundary when the gateway was already running. recoverconnect --probe-onlycheckAndRecoverSandboxProcesses took the if (running) branch and returned after refreshing the port-forward, never invoking buildHermesEnvFileBoundaryGuard() (only the relaunch path embeds it). A raw TELEGRAM_BOT_TOKEN injected into /sandbox/.hermes/.env survived recovery and the gateway kept serving. The probe path now executes a standalone secret-boundary check via the root openshell sandbox exec channel (so the kill snippet has authority over the gateway-user process), brings the gateway down on refusal, and surfaces a non-zero exit on recover.

Related Issue

Fixes #5525

Changes

  • hermes-recovery-boundary.ts exports buildHermesEnvFileBoundaryStandaloneCheck() plus SECRET_BOUNDARY_{OK,REFUSED,VALIDATOR_MISSING}_MARKER constants. The standalone snippet runs the existing validator on /sandbox/.hermes/.env, kills any running Hermes gateway/dashboard on refusal, and emits a single stdout marker.
  • process-recovery.ts adds enforceHermesSecretBoundaryOnRunningGateway, invoked from checkAndRecoverSandboxProcesses before the if (running) early-return when the active agent is Hermes. Refusal short-circuits the function with secretBoundaryRefused: true and skips the forward-refresh path.
  • connect.ts runSandboxConnectProbe surfaces a refusal as exit 1 with a clear remediation line pointing at the openshell:resolve:env:<name> placeholder.
  • docs/reference/commands.mdx documents the Hermes-only secret-boundary re-evaluation on recover; the nemohermes variant is regenerated.
  • New tests: 4 in process-recovery.test.ts (refused / passed / validator-missing / OpenClaw no-op); 3 in runtime-hermes-secret-boundary-behavioural.test.ts exercising the standalone snippet against real bash with stubbed python3/pkill.

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)

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push, or npx prek run --from-ref main --to-ref HEAD passes
  • Targeted tests pass for changed behavior
  • Full npm test passes (broad runtime changes only)
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • 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

  • Documentation

    • Updated recover command documentation to describe secret boundary re-evaluation behavior.
  • New Features

    • Added Hermes secret boundary validation during the recovery process that checks for improperly configured raw secrets in environment files.
  • Bug Fixes

    • Improved error detection with clearer guidance to replace raw secret values with proper placeholders before recovery proceeds.
  • Tests

    • Added test coverage for secret boundary validation scenarios.

…e path

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

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Fixes a security regression where nemohermes recover did not enforce the Hermes secret-boundary check when the gateway was already running. Adds marker constants and a standalone shell snippet builder, wires an enforcement helper into checkAndRecoverSandboxProcesses to return secretBoundaryRefused: true early, adds a matching error branch in the connect probe, and updates documentation and tests.

Changes

Hermes Secret-Boundary Enforcement on Recover

Layer / File(s) Summary
Marker constants and standalone shell check builder
src/lib/agent/hermes-recovery-boundary.ts
Defines three SECRET_BOUNDARY_* marker constants and adds buildHermesEnvFileBoundaryStandaloneCheck(), which generates a shell snippet that runs the Python validator against /sandbox/.hermes/.env, emits the appropriate marker, kills gateway/dashboard processes on refusal, and exits non-zero.
Process recovery secret-boundary enforcement
src/lib/actions/sandbox/process-recovery.ts
Imports the marker constants, adds enforceHermesSecretBoundaryOnRunningGateway (runs the snippet via openshell sandbox exec and parses the last SECRET_BOUNDARY_* marker), and gates checkAndRecoverSandboxProcesses to return { secretBoundaryRefused: true } immediately before any port-forward or recovery logic when the validator refuses.
Connect probe early exit
src/lib/actions/sandbox/connect.ts
Adds a branch in runSandboxConnectProbe that detects processCheck.secretBoundaryRefused, prints a remediation error, and exits with code 1. Also repositions the getSandboxTargetGatewayName import with no behavioral change.
Behavioural and integration tests
src/lib/agent/runtime-hermes-secret-boundary-behavioural.test.ts, test/process-recovery.test.ts
Adds three behavioural tests for the standalone snippet (refused/accepted/missing-validator) and four integration tests for checkAndRecoverSandboxProcesses covering Hermes refusal, validator success, missing validator on older images, and OpenClaw sandbox (zero validator invocations).
Documentation
docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx
Documents the per-run secret-boundary re-validation in recover, the failure behavior (stop gateway, non-zero exit, report offending key), and the placeholder replacement workflow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#5321: Touches the same runtime-hermes-secret-boundary-behavioural.test.ts file with test-harness changes for Hermes recovery boundary checks that this PR extends.
  • NVIDIA/NemoClaw#5342: Modifies the same SECRET_BOUNDARY_* marker expectations and Hermes boundary behavioral tests that this PR builds upon.
  • NVIDIA/NemoClaw#5389: Also modifies checkAndRecoverSandboxProcesses in process-recovery.ts for port-forward recovery, overlapping with the same control flow this PR gates on the boundary check.

Suggested labels

security, integration: hermes, bug-fix, area: sandbox

Suggested reviewers

  • cv

Poem

🐰 Hopping through the .env with care,
Raw secrets found? The gateway won't dare!
A marker is printed, a process is slain,
openshell:resolve keeps the secrets sane.
🔐 No plaintext tokens shall pass this gate —
The bunny enforces, on every recover run, fate!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: enforcing Hermes env-file secret boundary validation on the probe/recover path.
Linked Issues check ✅ Passed The PR fully addresses issue #5525 by implementing secret-boundary enforcement during the recover command path via standalone validation, resulting in proper refusal and messaging.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing the security regression: new boundary validation, process recovery integration, probe handling, documentation, and comprehensive test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/hermes-secret-boundary-on-recover-probe

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

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: hermes-secret-boundary-e2e, issue-2478-crash-loop-recovery-e2e
Optional E2E: hermes-e2e, sandbox-survival-e2e

Dispatch hint: hermes-secret-boundary-e2e,issue-2478-crash-loop-recovery-e2e

Auto-dispatched E2E: hermes-secret-boundary-e2e, issue-2478-crash-loop-recovery-e2e via nightly-e2e.yaml at fd13c69793f1414d48eb09d454ddfc59c20868a8nightly run

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • hermes-secret-boundary-e2e (medium): Directly covers the Hermes sandbox secret-boundary contract for raw secret-shaped env/config values and validator refusal behavior. This is the closest existing E2E to the changed security boundary.
  • issue-2478-crash-loop-recovery-e2e (medium): Exercises the production connect --probe-only recovery path and gateway restart/recovery behavior that is modified by checkAndRecoverSandboxProcesses and connect.ts.

Optional E2E

  • hermes-e2e (high): Useful additional confidence that a real Hermes sandbox still onboards, becomes healthy, exposes the API port, and completes live inference after the Hermes recovery/security code changes.
  • sandbox-survival-e2e (medium): Adjacent coverage for sandbox and gateway survival across gateway restarts. It is not Hermes-secret-boundary-specific, but it can catch broad regressions in recovery and port-forward handling.

New E2E recommendations

  • Hermes recover-time secret-boundary enforcement (high): Existing E2E coverage validates Hermes image/startup secret hygiene and generic recovery, but does not appear to exercise the new exact live behavior: inject a raw secret-shaped value into /sandbox/.hermes/.env in an already-running Hermes sandbox, run nemohermes <name> recover or connect --probe-only, assert non-zero exit, offending key in stderr, and gateway health becomes unavailable.
    • Suggested test: Add a Hermes recovery secret-boundary E2E scenario for running-gateway refusal and gateway stop-on-refusal.
  • Older Hermes image compatibility warning (medium): The PR intentionally keeps older Hermes images fail-open when the standalone validator is missing and promises a [boundary] warning. Existing E2E coverage may not validate this mixed-version compatibility path.
    • Suggested test: Add a compatibility E2E or image-fixture smoke that runs recover against a Hermes sandbox image without the standalone validator and asserts the warning plus successful recovery continuation.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: hermes-secret-boundary-e2e,issue-2478-crash-loop-recovery-e2e

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: issue-2478-crash-loop-recovery-vitest
Optional Vitest E2E scenarios: None

Dispatch required Vitest E2E scenarios:

  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=issue-2478-crash-loop-recovery-vitest

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: medium

Required Vitest E2E scenarios

  • issue-2478-crash-loop-recovery-vitest: The PR changes shared sandbox process recovery and connect --probe-only control flow. This live Vitest job directly exercises the production checkAndRecoverSandboxProcesses/connect --probe-only recovery path after gateway disruption, providing coverage for regressions in the shared recovery machinery.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=issue-2478-crash-loop-recovery-vitest

Optional Vitest E2E scenarios

  • None.

Relevant changed files

  • src/lib/actions/sandbox/connect.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/agent/hermes-recovery-boundary.ts

@github-code-quality

github-code-quality Bot commented Jun 17, 2026

Copy link
Copy Markdown

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the branch is 96%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File fd13c69 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the branch is 46%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File fd13c69 +/-
src/lib/state/o...oard-session.ts 90%
src/lib/inference/local.ts 76%
src/lib/sandbox/config.ts 72%
src/lib/actions...dbox/rebuild.ts 67%
src/lib/onboard/preflight.ts 64%
src/lib/actions...licy-channel.ts 56%
src/lib/state/sandbox.ts 55%
src/lib/policy/index.ts 49%
src/lib/onboard...er-gpu-patch.ts 44%
src/lib/onboard.ts 18%

Updated June 17, 2026 10:03 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 0 needs attention, 3 worth checking, 1 nice ideas
Since last review: 4 prior items resolved, 1 still applies, 2 new items found

Review findings

🛠️ Needs attention

  • None.

🔎 Worth checking

  • Source-of-truth review needed: Trusted interpreter for root-exec standalone validator: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `hermes-wrapper.sh` documents PATH as untrusted for this guard, while the new standalone snippet invokes `python3` by name.
  • Standalone root-exec boundary uses PATH-resolved python3 (src/lib/agent/hermes-recovery-boundary.ts:158): The new standalone check is intended to run through the root `openshell sandbox exec` path and enforce a security boundary before the host reports recover/connect success. Its shell snippet invokes `python3` by name. Nearby Hermes runtime code treats PATH as untrusted for this same validator boundary: `agents/hermes/hermes-wrapper.sh` resolves python from fixed absolute paths and fails closed so a PATH-shadowed interpreter cannot no-op the guard. If the sandbox exec environment or writable paths can influence PATH, this becomes a weak link in the validator trust chain.
    • Recommendation: Mirror the trusted-interpreter resolution used by `hermes-wrapper.sh`: choose from known absolute python paths such as `/usr/bin/python3`, `/usr/local/bin/python3`, or `/opt/hermes/.venv/bin/python3`, and fail closed with an inconclusive marker/diagnostic when none is available. Add a shell-snippet test that a PATH-shadowed `python3` is not used.
    • Evidence: `buildHermesEnvFileBoundaryStandaloneCheck()` builds `if ${invocation}; then ...` where `invocation` is `python3 ${shellQuote(validator)} env-file /sandbox/.hermes/.env`; `hermes-wrapper.sh` explicitly avoids PATH for the same validator because PATH is part of the untrusted runtime environment.
  • Standalone refusal diagnostics are not persisted to the documented log inspection path (src/lib/agent/hermes-recovery-boundary.ts:139): The linked issue's repro checks gateway/container logs for `[SECURITY]` refusal lines. This PR surfaces the validator stderr to the CLI through `printValidatorStderr()`, and tests assert the CLI receives the key/line diagnostics, but the standalone root-exec path deliberately leaves stderr on the exec command and is independent of `/tmp/gateway-recovery.log`. That may satisfy interactive stderr, but it does not demonstrate the issue's log-inspection acceptance path.
    • Recommendation: Either persist the standalone root-exec validator stderr to an operator-documented sandbox log location, such as the recovery log used by the relaunch guard, or update the public docs/acceptance expectation to clearly state that recover prints these diagnostics on CLI stderr. Add a regression test for the chosen contract.
    • Evidence: The standalone check comment says validator stderr is left on the exec command's stderr and is independent of `/tmp/gateway-recovery.log`; `process-recovery.ts` prints `result.stderr` to `console.error`, while issue [All Platforms][Security] NemoHermes still starts and serves after raw secret-shaped TELEGRAM_BOT_TOKEN in .env, no [SECURITY] refusal #5525 expects logs containing `[SECURITY] Refusing Hermes startup...` and `[SECURITY] TELEGRAM_BOT_TOKEN (line N)`.

🌱 Nice ideas

  • Consider extracting the running-gateway boundary classifier (src/lib/actions/sandbox/process-recovery.ts:532): The shell generation moved into `hermes-recovery-boundary.ts`, but the root exec invocation, marker classification, stderr surfacing, fail-safe decisions, registry gating, and return-contract shaping still live inside the large recovery module. This is security-sensitive code in a high-churn file that grew substantially in this PR.
    • Recommendation: Consider moving `enforceHermesSecretBoundaryOnRunningGateway()` into a small helper near `hermes-recovery-boundary.ts`, with dependency injection for the sandbox exec function, so the trusted boundary contract can be reviewed and tested independently from general recovery flow.
    • Evidence: `process-recovery.ts` grew by more than 100 lines and now handles the standalone Hermes security boundary classification inline.
Consider writing more tests for
  • **Runtime validation** — Add a command-level `nemohermes <sandbox> recover` test where a running Hermes `.env` contains raw `TELEGRAM_BOT_TOKEN`, asserting exit 1, stderr includes `[SECURITY] TELEGRAM_BOT_TOKEN (line N)`, and stdout does not contain `Probe complete`.. The changed behavior depends on OpenShell root exec semantics, sandbox process ownership, shell marker parsing, and a live Hermes health listener. Unit and behavioral shell tests cover much of the local logic, but runtime validation would improve confidence in the actual public recover path.
  • **Runtime validation** — Add runtime validation that after the same recover refusal, `curl http://127.0.0.1:8642/health\` fails or reports `HEALTH_DOWN`.. The changed behavior depends on OpenShell root exec semantics, sandbox process ownership, shell marker parsing, and a live Hermes health listener. Unit and behavioral shell tests cover much of the local logic, but runtime validation would improve confidence in the actual public recover path.
  • **Runtime validation** — Add a test proving the standalone root-exec refusal persists `[SECURITY]` key/line diagnostics to the operator-documented log location, if that remains part of the contract.. The changed behavior depends on OpenShell root exec semantics, sandbox process ownership, shell marker parsing, and a live Hermes health listener. Unit and behavioral shell tests cover much of the local logic, but runtime validation would improve confidence in the actual public recover path.
  • **Runtime validation** — Add a shell-snippet test where PATH contains a malicious or failing `python3`, asserting the standalone boundary uses only trusted absolute interpreters or fails closed as inconclusive.. The changed behavior depends on OpenShell root exec semantics, sandbox process ownership, shell marker parsing, and a live Hermes health listener. Unit and behavioral shell tests cover much of the local logic, but runtime validation would improve confidence in the actual public recover path.
  • **Acceptance clause:** On NemoHermes v0.0.65, the documented secret-boundary protection for `.hermes/.env` is not enforced on `nemohermes <sandbox> recover`. — add test evidence or identify existing coverage. `checkAndRecoverSandboxProcesses()` now calls `enforceHermesSecretBoundaryOnRunningGateway()` before the healthy running-gateway return path, and `runSandboxConnectProbe()` exits on `secretBoundaryRefused`. Coverage is partial because older images without the standalone validator intentionally warn and proceed rather than enforcing.
  • **Acceptance clause:** Injecting a plaintext Telegram bot token (`TELEGRAM_BOT_TOKEN=1234567890:AAExample-RawSecretValueHere`) into `/sandbox/.hermes/.env` and running `nemohermes hermes-sbox recover` allows the gateway to keep running and serving traffic with no `[SECURITY]` log line and no startup refusal. — add test evidence or identify existing coverage. The standalone snippet runs the validator on `/sandbox/.hermes/.env`, emits `SECRET_BOUNDARY_REFUSED`, kills Hermes gateway/dashboard process patterns, and returns `secretBoundaryRefused: true`; tests assert refusal and skipped forward refresh. No changed runtime test proves the live `/health` listener is unreachable afterward.
  • **Acceptance clause:** Logs should contain: ``` [SECURITY] Refusing Hermes startup because /sandbox/.hermes/.env contains raw secret-shaped values [SECURITY] TELEGRAM_BOT_TOKEN (line N) ``` — add test evidence or identify existing coverage. `printValidatorStderr(result.stderr)` surfaces the validator lines to CLI stderr and tests assert the required `[SECURITY]` text with `TELEGRAM_BOT_TOKEN (line 3)`. The standalone path does not prove persistence to the issue's gateway/container log inspection path.
  • **Acceptance clause:** `/health` should not be reachable (curl fails / `HEALTH_DOWN`). — add test evidence or identify existing coverage. The shell snippet sends TERM and KILL to Hermes gateway/dashboard process patterns, and behavioral tests assert pkill calls. No changed test runs a live Hermes health listener and verifies `curl /health` fails after refusal.
Since last review details

Current findings:

  • Source-of-truth review needed: Trusted interpreter for root-exec standalone validator: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `hermes-wrapper.sh` documents PATH as untrusted for this guard, while the new standalone snippet invokes `python3` by name.
  • Standalone root-exec boundary uses PATH-resolved python3 (src/lib/agent/hermes-recovery-boundary.ts:158): The new standalone check is intended to run through the root `openshell sandbox exec` path and enforce a security boundary before the host reports recover/connect success. Its shell snippet invokes `python3` by name. Nearby Hermes runtime code treats PATH as untrusted for this same validator boundary: `agents/hermes/hermes-wrapper.sh` resolves python from fixed absolute paths and fails closed so a PATH-shadowed interpreter cannot no-op the guard. If the sandbox exec environment or writable paths can influence PATH, this becomes a weak link in the validator trust chain.
    • Recommendation: Mirror the trusted-interpreter resolution used by `hermes-wrapper.sh`: choose from known absolute python paths such as `/usr/bin/python3`, `/usr/local/bin/python3`, or `/opt/hermes/.venv/bin/python3`, and fail closed with an inconclusive marker/diagnostic when none is available. Add a shell-snippet test that a PATH-shadowed `python3` is not used.
    • Evidence: `buildHermesEnvFileBoundaryStandaloneCheck()` builds `if ${invocation}; then ...` where `invocation` is `python3 ${shellQuote(validator)} env-file /sandbox/.hermes/.env`; `hermes-wrapper.sh` explicitly avoids PATH for the same validator because PATH is part of the untrusted runtime environment.
  • Standalone refusal diagnostics are not persisted to the documented log inspection path (src/lib/agent/hermes-recovery-boundary.ts:139): The linked issue's repro checks gateway/container logs for `[SECURITY]` refusal lines. This PR surfaces the validator stderr to the CLI through `printValidatorStderr()`, and tests assert the CLI receives the key/line diagnostics, but the standalone root-exec path deliberately leaves stderr on the exec command and is independent of `/tmp/gateway-recovery.log`. That may satisfy interactive stderr, but it does not demonstrate the issue's log-inspection acceptance path.
    • Recommendation: Either persist the standalone root-exec validator stderr to an operator-documented sandbox log location, such as the recovery log used by the relaunch guard, or update the public docs/acceptance expectation to clearly state that recover prints these diagnostics on CLI stderr. Add a regression test for the chosen contract.
    • Evidence: The standalone check comment says validator stderr is left on the exec command's stderr and is independent of `/tmp/gateway-recovery.log`; `process-recovery.ts` prints `result.stderr` to `console.error`, while issue [All Platforms][Security] NemoHermes still starts and serves after raw secret-shaped TELEGRAM_BOT_TOKEN in .env, no [SECURITY] refusal #5525 expects logs containing `[SECURITY] Refusing Hermes startup...` and `[SECURITY] TELEGRAM_BOT_TOKEN (line N)`.
  • Consider extracting the running-gateway boundary classifier (src/lib/actions/sandbox/process-recovery.ts:532): The shell generation moved into `hermes-recovery-boundary.ts`, but the root exec invocation, marker classification, stderr surfacing, fail-safe decisions, registry gating, and return-contract shaping still live inside the large recovery module. This is security-sensitive code in a high-churn file that grew substantially in this PR.
    • Recommendation: Consider moving `enforceHermesSecretBoundaryOnRunningGateway()` into a small helper near `hermes-recovery-boundary.ts`, with dependency injection for the sandbox exec function, so the trusted boundary contract can be reviewed and tested independently from general recovery flow.
    • Evidence: `process-recovery.ts` grew by more than 100 lines and now handles the standalone Hermes security boundary classification inline.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@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 `@src/lib/actions/sandbox/process-recovery.ts`:
- Around line 523-538: The stderr output from the validator is being suppressed
when quiet mode is enabled, but security diagnostics should always be surfaced
regardless of the quiet flag. In the block checking for
SECRET_BOUNDARY_REFUSED_MARKER or non-zero status, move the stderr logging
section (which iterates through result.stderr and logs each line) outside of or
separate from the main if (!quiet) condition so that validator error diagnostics
are always displayed to help the caller understand which secret-shaped values
need to be replaced, even when called with quiet: true.
🪄 Autofix (Beta)

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: 0cda9f0a-deb4-4ed5-b935-03c51274c78d

📥 Commits

Reviewing files that changed from the base of the PR and between a6e664d and 8209b7b.

📒 Files selected for processing (7)
  • docs/reference/commands-nemohermes.mdx
  • docs/reference/commands.mdx
  • src/lib/actions/sandbox/connect.ts
  • src/lib/actions/sandbox/process-recovery.ts
  • src/lib/agent/hermes-recovery-boundary.ts
  • src/lib/agent/runtime-hermes-secret-boundary-behavioural.test.ts
  • test/process-recovery.test.ts

Comment thread src/lib/actions/sandbox/process-recovery.ts Outdated
@laitingsheng laitingsheng added area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression integration: hermes Hermes integration behavior labels Jun 17, 2026
…clusive secret-boundary check

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

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 27677577987
Target ref: 2e03367d32758628c1b0581525de5074cf484cc0
Workflow ref: main
Requested jobs: hermes-secret-boundary-e2e
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-secret-boundary-e2e ✅ success

…r probe refusal at the command boundary

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

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 27679202263
Target ref: bff177c823f77575505d9ad1a26eb256dff1631b
Workflow ref: main
Requested jobs: hermes-secret-boundary-e2e
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-secret-boundary-e2e ✅ success

…c and stop the non-probe connect path on refusal

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@laitingsheng laitingsheng added the v0.0.66 Release target label Jun 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 27681289046
Target ref: fd13c69793f1414d48eb09d454ddfc59c20868a8
Workflow ref: main
Requested jobs: hermes-secret-boundary-e2e,issue-2478-crash-loop-recovery-e2e
Summary: 2 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
hermes-secret-boundary-e2e ✅ success
issue-2478-crash-loop-recovery-e2e ✅ success

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

Labels

area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression integration: hermes Hermes integration behavior v0.0.66 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[All Platforms][Security] NemoHermes still starts and serves after raw secret-shaped TELEGRAM_BOT_TOKEN in .env, no [SECURITY] refusal

1 participant