You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(sandbox/recover): enforce Hermes env-file secret boundary on probe path (#5530)
## Summary
`nemohermes <name> recover` did not re-evaluate the documented Hermes
secret boundary when the gateway was already running. `recover` →
`connect --probe-only` → `checkAndRecoverSandboxProcesses` 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
- [x] 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
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [x] Targeted tests pass for changed behavior
- [ ] Full `npm test` passes (broad runtime changes only)
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [x] Docs updated for user-facing behavior changes
- [ ] `npm run docs` builds without warnings (doc changes only)
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
---
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## 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.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Copy file name to clipboardExpand all lines: docs/reference/commands-nemohermes.mdx
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -501,6 +501,11 @@ If the gateway is already running, the command exits zero with a probe message a
501
501
nemohermes my-assistant recover
502
502
```
503
503
504
+
`recover` re-evaluates the documented Hermes secret boundary against `/sandbox/.hermes/.env` on every run, including when the gateway is already healthy.
505
+
If the file contains raw secret-shaped values (for example a pasted Telegram, Discord, or Slack bot token in place of the expected `openshell:resolve:env:<name>` placeholder), the command stops the running gateway, exits non-zero, and prints the offending key.
506
+
Replace each flagged value with the `openshell:resolve:env:<name>` placeholder and re-run.
507
+
Older Hermes sandbox images that predate the standalone validator are detected and left untouched: `recover` prints a `[boundary]` warning naming the sandbox and noting that `/sandbox/.hermes/.env` was not re-evaluated, then proceeds with the rest of the recovery path rather than blocking the gateway. Re-image the sandbox to a current Hermes build to enable the per-run boundary re-evaluation described above.
508
+
504
509
### `nemohermes <name> status`
505
510
506
511
Show sandbox status, health, and inference configuration.
Copy file name to clipboardExpand all lines: docs/reference/commands.mdx
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -630,6 +630,15 @@ If the gateway is already running, the command exits zero with a probe message a
630
630
$$nemoclaw my-assistant recover
631
631
```
632
632
633
+
<AgentOnlyvariant="hermes">
634
+
635
+
`recover` re-evaluates the documented Hermes secret boundary against `/sandbox/.hermes/.env` on every run, including when the gateway is already healthy.
636
+
If the file contains raw secret-shaped values (for example a pasted Telegram, Discord, or Slack bot token in place of the expected `openshell:resolve:env:<name>` placeholder), the command stops the running gateway, exits non-zero, and prints the offending key.
637
+
Replace each flagged value with the `openshell:resolve:env:<name>` placeholder and re-run.
638
+
Older Hermes sandbox images that predate the standalone validator are detected and left untouched: `recover` prints a `[boundary]` warning naming the sandbox and noting that `/sandbox/.hermes/.env` was not re-evaluated, then proceeds with the rest of the recovery path rather than blocking the gateway. Re-image the sandbox to a current Hermes build to enable the per-run boundary re-evaluation described above.
639
+
640
+
</AgentOnly>
641
+
633
642
### `$$nemoclaw <name> status`
634
643
635
644
Show sandbox status, health, and inference configuration.
0 commit comments