Skip to content

fix(shields): write an absent config hash before locking a config - #7995

Merged
senthilr-nv merged 10 commits into
mainfrom
fix/deepagents-shields-config-hash
Aug 2, 2026
Merged

fix(shields): write an absent config hash before locking a config#7995
senthilr-nv merged 10 commits into
mainfrom
fix/deepagents-shields-config-hash

Conversation

@laitingsheng

@laitingsheng laitingsheng commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

shields up failed on a Deep Agents sandbox because the lock and the verifier both treat <config dir>/.config-hash as a protected file, while the Deep Agents image never writes one. The lock now writes an absent hash record before it applies the locked permissions, so agents whose image ships no record reach the same locked posture as OpenClaw and Hermes.

Related Issue

Fixes #7977

Changes

  • src/lib/shields/seal.ts adds CONFIG_HASH_REPAIR_NOFOLLOW_SCRIPT and buildConfigHashRepairCommand. The helper opens the config directory with O_NOFOLLOW and O_DIRECTORY, inspects the record name with lstat, and creates it with O_CREAT | O_EXCL at mode 0444 and the sha256sum record shape. A non-regular file at the record name, a symlinked config file, and a config path outside the config directory each fail the lock instead of redirecting a privileged write. The helper lives here because this module already owns the seal's on-disk contract, and a separate module would raise the src/lib/shields/index.ts fan-out past its ci/source-architecture-budget.json limit.
  • src/lib/shields/index.ts calls the helper from the lock path used by agents other than OpenClaw and Hermes, which run their own root-only config guards. Those guards already synthesize an absent record; this path had no equivalent step, so the following chmod 444 and chown root:root failed and the verifier reported Config not locked: … .config-hash stat failed.
  • src/lib/shields/seal.test.ts runs the helper against real directories for the absent, stale, planted-symlink, planted-directory, symlinked-config, and outside-the-directory cases.
  • src/lib/shields/policy-transition.test.ts covers the lock wiring for a Deep Agents target: the record is repaired before the protected files are locked, and a repair failure leaves the config unlocked.

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: docs/reference/commands.mdx already documents shields up as an agent-independent command with no Deep Agents exception. The command now behaves as documented, so no documented contract changes.
  • 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: Maintainer nine-category review PASS at exact current-main head 0146c7b450b9650e0fa540e10ba6638f951cf029; exact diff fingerprint 7b2bcd4a56f8ea1ee0d49412af4cc84bc8499d92ca5bcf65754ca78383471868. The current-main sync leaves the feature diff unchanged.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer reviewed the completed changes
  • Result: no-docs-needed
  • Evidence: No documentation paths changed. An independent Codex Desktop documentation writer reviewed the completed behavior at the exact current head; the existing agent-independent shields-up documentation remains accurate. The current-main sync did not alter the feature diff.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result:
  • Supporting evidence:

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 — At exact current-main head 0146c7b45, focused repair/transition/verifier coverage passed 50/50 and the complete CLI shields suite passed 272/272; npm run build:cli, npm run validate:pr, and normal pre-push CLI/type/version gates passed.
  • 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 sandbox configuration locking when a configuration hash is missing.
    • Added safe hash recovery that rejects symlinks, invalid files, and unsafe paths.
    • Ensured configurations remain unlocked if hash recovery fails.
    • Created hash records atomically with appropriate permissions while preserving valid existing records.
    • Expanded protection checks to additional supported sandbox configurations.
    • Restored protected parent ownership and permissions when unlocking configurations.

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

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds secure repair for missing configuration hashes before non-Hermes locking. Extends protected-parent handling to OpenClaw, Hermes, and LangChain Deep Agents Code. Adds lock, unlock, filesystem, race, and failure tests.

Changes

Sandbox shielding

Layer / File(s) Summary
No-follow hash repair
src/lib/shields/seal.ts, src/lib/shields/seal.test.ts
The repair script validates paths, rejects unsafe filesystem objects, creates read-only SHA-256 records, handles races, and restores metadata after failures.
Hash repair during locking
src/lib/shields/index.ts, src/lib/shields/policy-transition.test.ts
Non-Hermes locking repairs missing hashes before applying restrictive permissions. Tests cover successful repair and failure propagation.
Protected parent lifecycle and verification
src/lib/shields/index.ts, src/lib/shields/verify-lock.ts, src/lib/shields/verify-lock.test.ts, src/lib/shields/policy-transition.test.ts
Lock and unlock flows detect, restore, and verify protected parent metadata for supported sandbox configurations.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant ShieldLock
  participant HashRepair
  participant ConfigFilesystem
  participant LockVerification
  ShieldLock->>HashRepair: repair missing configuration hash
  HashRepair->>ConfigFilesystem: validate and hash configuration
  HashRepair->>ConfigFilesystem: create read-only .config-hash
  ShieldLock->>ConfigFilesystem: lock configuration and protected parent
  LockVerification->>ConfigFilesystem: verify ownership and permissions
Loading

Suggested reviewers: prekshivyas

🚥 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
Linked Issues check ✅ Passed The changes address issue #7977 by repairing absent config hashes and wiring successful locking for Deep Agents sandboxes.
Out of Scope Changes check ✅ Passed The changes remain within scope by hardening config locking, parent protection, unlock restoration, and related test coverage.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: creating an absent config hash before locking a configuration.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deepagents-shields-config-hash

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

@github-code-quality

github-code-quality Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 2b0beb2 in the fix/deepagents-shiel... branch remains at 96%, unchanged from commit 4367d71 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit 2b0beb2 in the fix/deepagents-shiel... branch remains at 81%, unchanged from commit 4367d71 in the main branch.

Show a code coverage summary of the most impacted files.
File main 4367d71 fix/deepagents-shiel... 2b0beb2 +/-
src/lib/onboard...ndbox-create.ts 83% 33% -50%
src/lib/onboard...-create-plan.ts 88% 75% -13%
src/lib/onboard...ndbox-create.ts 91% 83% -8%
src/lib/platform.ts 89% 84% -5%
src/lib/shields/index.ts 69% 68% -1%
src/lib/messagi...nnels/policy.ts 100% 100% 0%
src/lib/sandbox...rce-identity.ts 88% 88% 0%
src/lib/shields/seal.ts 100% 100% 0%
src/lib/state/config-io.ts 93% 93% 0%
src/lib/credentials/store.ts 55% 56% +1%

Updated August 02, 2026 07:26 UTC

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / low confidence
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions
Status: PR review advisor failed: PR review advisor SDK execution failed: session: scope-risk-map-analysis omitted required analysis; turn: scope-risk-map-analysis: scope-risk-map-analysis omitted required analysis

Model lanes

  • GPT-5.6 Terra (primary): Failed
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 3 warnings · 0 suggestions

Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-inference, security-posture

Workflow run details

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

@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: 2

🧹 Nitpick comments (2)
src/lib/shields/seal.test.ts (1)

38-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Surface the spawn error so a missing python3 is diagnosable.

spawnSync reports ENOENT through result.error, not through status or stderr. If the interpreter is absent, every assertion fails with an unclear message.

♻️ Proposed change to fail with the spawn error
   const result = spawnSync(binary, args, { encoding: "utf-8" });
+  if (result.error) throw result.error;
   return { status: result.status, stderr: (result.stderr ?? "").trim() };
🤖 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 `@src/lib/shields/seal.test.ts` around lines 38 - 39, Update the helper
wrapping spawnSync to inspect result.error and surface its details when the
Python process cannot be started, including the missing python3/ENOENT case.
Preserve the existing status and trimmed stderr return behavior for successfully
spawned processes.
src/lib/shields/policy-transition.test.ts (1)

118-122: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Seed the emulated record so the lock steps stay observable.

The python3 branch inserts HASH_PATH already at mode 444 and owner root:root. The assertion at Line 204 then passes even if the lock never applied chmod 444 or chown root:root to the record. Create the record with a non-locked mode and owner so the assertion proves the lock steps ran.

♻️ Proposed change to the repair emulation
     if (head === "python3") {
       repairCalls.push(cmd);
-      entries.set(HASH_PATH, { mode: "444", owner: "root:root" });
+      entries.set(HASH_PATH, { mode: "600", owner: "sandbox:sandbox" });
       return "";
     }

Based on learnings about the path instruction "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim".

🤖 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 `@src/lib/shields/policy-transition.test.ts` around lines 118 - 122, Update the
python3 branch of the repair emulation so the HASH_PATH record starts with a
non-locked mode and owner, rather than mode 444 and root:root. Keep the existing
repairCalls tracking and record creation flow, allowing the assertion to verify
that the lock operations actually apply chmod 444 and chown root:root.

Source: Path instructions

🤖 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/shields/index.ts`:
- Around line 1582-1590: Validate custom BASE_IMAGE values used for python3
before proceeding with non-Hermes locking, ensuring the image provides the
python3 executable required by writeAbsentConfigHashNoSymlinkFollow. Add the
check in the existing Dockerfile/build validation flow for custom base images,
while preserving the standard-image behavior and rejecting invalid images with a
clear error.

In `@src/lib/shields/seal.ts`:
- Around line 52-56: Update the flag construction in the relevant seal path to
require O_NOFOLLOW from os and fail closed when it is unavailable, rather than
defaulting to zero; do this before any path open. Apply the same required-flag
guard to the creation flags constructed around the creation logic, while
preserving the existing directory and nonblocking flag behavior.

---

Nitpick comments:
In `@src/lib/shields/policy-transition.test.ts`:
- Around line 118-122: Update the python3 branch of the repair emulation so the
HASH_PATH record starts with a non-locked mode and owner, rather than mode 444
and root:root. Keep the existing repairCalls tracking and record creation flow,
allowing the assertion to verify that the lock operations actually apply chmod
444 and chown root:root.

In `@src/lib/shields/seal.test.ts`:
- Around line 38-39: Update the helper wrapping spawnSync to inspect
result.error and surface its details when the Python process cannot be started,
including the missing python3/ENOENT case. Preserve the existing status and
trimmed stderr return behavior for successfully spawned processes.
🪄 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: 4d14953c-6b4c-46a8-b6de-28acedecad9f

📥 Commits

Reviewing files that changed from the base of the PR and between f8fb820 and bfc6b2c.

📒 Files selected for processing (4)
  • src/lib/shields/index.ts
  • src/lib/shields/policy-transition.test.ts
  • src/lib/shields/seal.test.ts
  • src/lib/shields/seal.ts

Comment thread src/lib/shields/index.ts
Comment thread src/lib/shields/seal.ts Outdated
@laitingsheng laitingsheng added bug-fix PR fixes a bug or regression NV QA Bugs found by the NVIDIA QA Team area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery integration: dcode LangChain Deep Code integration behavior labels Jul 31, 2026
Comment thread src/lib/shields/seal.test.ts Fixed
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>

@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: 2

🧹 Nitpick comments (4)
src/lib/shields/policy-transition.test.ts (1)

136-198: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Key the fixture on the script, not only on python3.

The repair script and the unlock script are both invoked as python3. The fixture dispatches on argv[0], so one handler serves both. A future flow that runs repair and unlock in the same test would silently receive the wrong model. Match on the script argument, or on a distinguishing argv position, so each handler stays bound to one script.

Also applies to: 272-279

🤖 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 `@src/lib/shields/policy-transition.test.ts` around lines 136 - 198, The
commandHandlers fixture currently dispatches both repair and unlock invocations
through the same “python3” handler. Update the “python3” dispatch in
commandHandlers to distinguish the script argument or another stable argv
position, and bind repair-specific state updates only to the repair script while
preserving separate behavior for the unlock script.
src/lib/shields/verify-lock.test.ts (1)

205-228: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add the passing direction for the Deep Agents target.

This case proves only that a replaceable parent is reported. Add a case with /sandbox at 1775 root:sandbox and assert that no parent dir issue is produced. That pins both directions of the new allowlist entry.

🤖 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 `@src/lib/shields/verify-lock.test.ts` around lines 205 - 228, Extend the Deep
Agents coverage near deepAgentsTarget with a passing case using /sandbox mode
1775 and owner root:sandbox while retaining the existing target and
sensitive-file setup. Invoke verifyShieldsLockState with parent protection
enabled and assert that issues contains no entries matching “parent dir”,
covering the accepted allowlist configuration.
src/lib/shields/seal.ts (1)

185-231: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Confirm the intended behavior when an existing record holds a stale digest.

inspect_hash_record returns the existing record, and the flow then skips hashing and creation. The record content is never compared to the current configuration file. src/lib/shields/seal.test.ts Lines 222-232 assert this preservation, so the behavior looks deliberate. State the reason in a comment so a later reader does not treat this as a missing verification step.

🤖 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 `@src/lib/shields/seal.ts` around lines 185 - 231, Add a concise comment near
the existing-record branch in the hash repair flow, around inspect_hash_record
and the existing is None check, stating that an existing hash record is
intentionally preserved without recomputing or comparing the current
configuration digest, including when stale. Do not alter the control flow or
verification behavior covered by the tests.
src/lib/shields/seal.test.ts (1)

50-80: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prove that the injected race actually fired.

racePlantWrapper patches os.stat and os.open and keys on the literal name .config-hash and on flags & os.O_EXCL. If the repair script later opens the record by a different name or without O_EXCL, the patches never fire. The test then still passes, because the pre-planted symlink alone makes inspect_hash_record fail with "not a regular file".

Make the harness record that both hooks fired, and assert that signal in the test. For example, write a marker to stderr from raced_open and assert it in outcome.stderr.

As per path instructions: "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim."

Also applies to: 250-265

🤖 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 `@src/lib/shields/seal.test.ts` around lines 50 - 80, Update the raced_stat and
raced_open hook functions in racePlantWrapper to write distinguishing markers to
stderr when they fire the injected conditions. Then add assertions in the test
to verify both markers appear in outcome.stderr, ensuring the test exercises the
actual race condition hooks rather than just relying on the pre-planted symlink
to cause failure.

Source: Path instructions

🤖 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/shields/index.ts`:
- Around line 2131-2134: Replace the inline verifyParentProtection predicate
with the existing requiresProtectedSandboxParent helper, passing the relevant
target and sandbox path inputs so its protected-agent and /sandbox/ conditions
are reused. Apply the same helper to the duplicate predicate around the other
referenced logic, removing repeated agent-name checks while preserving the
current behavior.

In `@src/lib/shields/seal.ts`:
- Around line 141-158: The production protected-parent decision in
src/lib/shields/seal.ts lines 141-158 must no longer depend on
NEMOCLAW_TEST_PROTECT_CONFIG_PARENT; retain the ownership and
writable-without-sticky checks for all non-production-condition parents while
preserving fail-closed behavior. Update src/lib/shields/seal.test.ts lines
184-220 to exercise the protected-parent path using a fixture matching the
production condition or an explicit test-only argv flag that production callers
never pass, rather than the environment variable.

---

Nitpick comments:
In `@src/lib/shields/policy-transition.test.ts`:
- Around line 136-198: The commandHandlers fixture currently dispatches both
repair and unlock invocations through the same “python3” handler. Update the
“python3” dispatch in commandHandlers to distinguish the script argument or
another stable argv position, and bind repair-specific state updates only to the
repair script while preserving separate behavior for the unlock script.

In `@src/lib/shields/seal.test.ts`:
- Around line 50-80: Update the raced_stat and raced_open hook functions in
racePlantWrapper to write distinguishing markers to stderr when they fire the
injected conditions. Then add assertions in the test to verify both markers
appear in outcome.stderr, ensuring the test exercises the actual race condition
hooks rather than just relying on the pre-planted symlink to cause failure.

In `@src/lib/shields/seal.ts`:
- Around line 185-231: Add a concise comment near the existing-record branch in
the hash repair flow, around inspect_hash_record and the existing is None check,
stating that an existing hash record is intentionally preserved without
recomputing or comparing the current configuration digest, including when stale.
Do not alter the control flow or verification behavior covered by the tests.

In `@src/lib/shields/verify-lock.test.ts`:
- Around line 205-228: Extend the Deep Agents coverage near deepAgentsTarget
with a passing case using /sandbox mode 1775 and owner root:sandbox while
retaining the existing target and sensitive-file setup. Invoke
verifyShieldsLockState with parent protection enabled and assert that issues
contains no entries matching “parent dir”, covering the accepted allowlist
configuration.
🪄 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: df9a27f0-8854-4e95-887e-31df9df30624

📥 Commits

Reviewing files that changed from the base of the PR and between bfc6b2c and 65498f3.

📒 Files selected for processing (6)
  • src/lib/shields/index.ts
  • src/lib/shields/policy-transition.test.ts
  • src/lib/shields/seal.test.ts
  • src/lib/shields/seal.ts
  • src/lib/shields/verify-lock.test.ts
  • src/lib/shields/verify-lock.ts

Comment thread src/lib/shields/index.ts Outdated
Comment thread src/lib/shields/seal.ts Outdated
apurvvkumaria and others added 5 commits July 31, 2026 03:38
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>

@senthilr-nv senthilr-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed exact head 0146c7b against current main 5cd29cc. Product scope PASS: fixes accepted issue #7977 for the existing Deep Agents shields-up surface. Security review PASS across secrets, input/path validation, authorization, dependencies, error handling, cryptography, configuration, security tests, and system/TOCTOU controls; no actionable findings. Focused tests 50/50, complete Shields suite 272/272, CLI typecheck, and repository checks pass locally. Cross-issue sweep found no adjacent fixes or contradictions; all CodeRabbit threads are resolved; independent documentation review passed no-docs-needed. Approval is based on the reviewed PR code per maintainer direction; GitHub remains separately blocked by an unrelated repeated timeout in mcp-bridge-status-state.test.ts.

@senthilr-nv
senthilr-nv enabled auto-merge (squash) August 1, 2026 18:25
@senthilr-nv
senthilr-nv merged commit c8da335 into main Aug 2, 2026
50 of 51 checks passed
@senthilr-nv
senthilr-nv deleted the fix/deepagents-shields-config-hash branch August 2, 2026 07:34
cv added a commit that referenced this pull request Aug 3, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Follow-up review of merged #7995 and #7847 found two independent
state-handling gaps. Shields recovery now remains bound to its original
configuration target. Migration preparation now installs only verified,
credential-filtered configuration bytes through a pinned directory
descriptor.

## Changes

- Follow-up to #7995:
- Persist the agent name, config path, and config directory in each
Shields timer marker.
- Use that persisted target for detached-timer and expired-marker
recovery when registry state is unavailable or resolves to a different
target.
- Give Deep Agents a canonical protected-file set and a
descriptor-sealed config-lock transaction.
- Fail closed when the transaction cannot restore or confirm a protected
posture.
  - Document recovery from a critical Deep Agents config-lock failure.
- Follow-up to #7847:
  - Exclude the copied `openclaw.json` from the general recursive copy.
- Read the copied config through the descriptor-bound snapshot scanner.
  - Strip credential fields and contextual secret assignments in memory.
- Install the sanitized config with exclusive, no-follow creation at
mode `0600`.
- Verify the installed inode, link count, size, and digest before
accepting it.
- Reject unsafe config path segments that could modify object
prototypes.
- Pin the plugin contextual secret patterns to the canonical CLI
patterns with a parity test.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: Independent
nine-category security review passed for commit SHA
`662d4ad020369dfcad3a21da225090cce507b111` against base SHA
`d6ac4027b75b15b8acd1456984acbbfb623cb231`. No findings in secrets and
credentials; input validation and data sanitization; authentication and
authorization; dependencies and third-party libraries; error handling
and logging; cryptography and data protection; configuration and
security headers; security testing; or system security. The three
addressed review threads are resolved.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: Independent review passed for commit SHA
`662d4ad020369dfcad3a21da225090cce507b111` against base SHA
`d6ac4027b75b15b8acd1456984acbbfb623cb231`. Reviewed
`docs/reference/commands.mdx`, `docs/reference/troubleshooting.mdx`, and
changed explanatory text against the NemoClaw Writing Guide, Controlled
Word List, documentation guidance, implementation, tests, and Deep
Agents variant routing. Required checks `docs-review-receipt`,
`cli-parity`, and `preview` pass for this commit. No blocking finding
remains.
- Agent: Codex Desktop
<!-- docs-review-head-sha: 662d4ad -->
<!-- docs-review-agents-blob-sha: 3dd7c24 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] 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
- [x] Targeted behavior tests pass for the current change set — Required
check `checks` concluded `SUCCESS` for commit SHA
`662d4ad020369dfcad3a21da225090cce507b111`.
- [ ] Applicable broad gate passed — Required check `E2E / PR Gate` is
running for commit SHA `662d4ad020369dfcad3a21da225090cce507b111`.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [x] `npm run docs` builds without warnings (documentation changes
only) — Required documentation checks pass for commit SHA
`662d4ad020369dfcad3a21da225090cce507b111`.
- [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: Carlos Villela <cvillela@nvidia.com>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added fail-closed protection for Deep Agents configuration-lock
failures.
* Improved automatic recovery by preserving agent and configuration
details.
  * Added secure snapshot-based configuration recovery and verification.
  * Expanded detection of embedded credential patterns.

* **Bug Fixes**
* Prevented unsafe repairs, symlink swaps, hard-link mutations, and
incomplete rollbacks.
  * Improved handling of invalid or empty configuration files.

* **Documentation**
* Added guidance for diagnosing, recovering from, and verifying critical
configuration-lock failures.

* **Tests**
* Expanded coverage for security, recovery, locking, rollback, and timer
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
senthilr-nv added a commit that referenced this pull request Aug 4, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Adds the canonical dated `v0.0.101` changelog entry that was missing
when the release tag was cut. This post-release recovery records the
shipped behavior on current `main` without changing or replacing the
existing tag.

## Changes

- Add `docs/changelog/2026-08-03.mdx` with the exact `## v0.0.101`
heading, release summary, detailed behavior changes, support boundaries,
and links to durable documentation.
- [#7317](#7317) ->
`docs/changelog/2026-08-03.mdx`: Records experimental OpenClaw Google
Chat support and its restricted credential and webhook boundary.
- [#7715](#7715) ->
`docs/changelog/2026-08-03.mdx`: Records strict onboarding recovery
state and authoritative resume identity.
- [#7749](#7749) ->
`docs/changelog/2026-08-03.mdx`: Records the provider-neutral policy
seam and unchanged runtime support boundary.
- [#7817](#7817) ->
`docs/changelog/2026-08-03.mdx`: Records preserved Hermes home-channel
assignments across rebuilds.
- [#7820](#7820) ->
`docs/changelog/2026-08-03.mdx`: Records the SSH-session status field
correction.
- [#7847](#7847) ->
`docs/changelog/2026-08-03.mdx`: Records fail-closed credential
filtering for migration and rebuild backups.
- [#7870](#7870) ->
`docs/changelog/2026-08-03.mdx`: Records sandbox-qualified in-sandbox
host command hints.
- [#7875](#7875) ->
`docs/changelog/2026-08-03.mdx`: Records Microsoft Teams stop and start
E2E coverage.
- [#7885](#7885) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes managed gateway
detection in status.
- [#7889](#7889) ->
`docs/changelog/2026-08-03.mdx`: Records policy-authenticated HTTPS Pin
Runtime route revocation.
- [#7891](#7891) ->
`docs/changelog/2026-08-03.mdx`: Records default fallback for negative
timeout and polling overrides.
- [#7993](#7993) ->
`docs/changelog/2026-08-03.mdx`: Records correct sibling detection
during uninstall.
- [#7995](#7995) ->
`docs/changelog/2026-08-03.mdx`: Records absent configuration-hash
handling before shields lock.
- [#8001](#8001) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant atomic managed
workload replacement foundation.
- [#8029](#8029) ->
`docs/changelog/2026-08-03.mdx`: Records repository terminology review
in PR Review Advisor.
- [#8031](#8031) ->
`docs/changelog/2026-08-03.mdx`: Records provider-neutral managed
snapshot authority.
- [#8032](#8032) ->
`docs/changelog/2026-08-03.mdx`: Records immutable managed clone handoff
contracts.
- [#8034](#8034) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant provider-owned
clone transaction surface.
- [#8035](#8035) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant Hermes managed
clone broker boundary.
- [#8036](#8036) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant transactional
managed bootstrap boundary.
- [#8037](#8037) ->
`docs/changelog/2026-08-03.mdx`: Records dormant Docker bootstrap
primitives and the unchanged provider support boundary.
- [#8070](#8070) ->
`docs/changelog/2026-08-03.mdx`: Records consolidated sandbox
resource-limit E2E coverage.
- [#8071](#8071) ->
`docs/changelog/2026-08-03.mdx`: Records escaped and bounded CLI
validation diagnostics.
- [#8081](#8081) ->
`docs/changelog/2026-08-03.mdx`: Records bounded linear snapshot Base64
validation.
- [#8085](#8085) ->
`docs/changelog/2026-08-03.mdx`: Records commit-bound workflow approval
for eligible same-repository maintainers.
- [#8088](#8088) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes managed-policy E2E
selection.
- [#8090](#8090) ->
`docs/changelog/2026-08-03.mdx`: Records pinned CI search-tool
provisioning.
- [#8106](#8106) ->
`docs/changelog/2026-08-03.mdx`: Records fallback from failed managed
OpenShell gateway startup.
- [#8107](#8107) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes adapter lifecycle E2E
selection.
- [#8128](#8128) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant transactional
Docker bootstrap adapter and rollback authority.
- [#8140](#8140) ->
`docs/changelog/2026-08-03.mdx`: Records Slack conflict scope across
independent OpenShell gateways.
- [#8147](#8147) ->
`docs/changelog/2026-08-03.mdx`: Records completion of durable v0.0.100
documentation audit follow-ups.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [x] 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:
- [x] Tests not applicable — justification: This documentation-only
recovery does not change executable behavior.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] 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

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: Independently reviewed `docs/changelog/2026-08-03.mdx` at
commit `0bebe1f568e3dc85cf410aac1dfb8f8830070b85`. Its blob is
`82887920f9720eafd75db6b2271c35f7477edb9b`. The entry follows the
writing guide, controlled terminology, changelog structure, MDX SPDX
format, literal CLI-name rule, and root-absolute route requirements. It
accurately records the `v0.0.100...v0.0.101` release range, Announcement
#8162, accepted scope boundaries, and shipped security behavior. There
are no code samples. Focused changelog tests and the documentation build
pass for this commit.
- Agent: Codex Desktop independent documentation writer
<!-- docs-review-head-sha: 0bebe1f -->
<!-- docs-review-agents-blob-sha:
3dd7c24 -->

## Security Review

- Result: `PASS`
- Reviewed commit: `0bebe1f568e3dc85cf410aac1dfb8f8830070b85`
- Base commit: `643a4ab8b5f583d8555192a37927268b26022c51`
- Findings: None.
- Secrets and credentials: `PASS`. No credential values or secret files
are present.
- Input validation and data sanitization: `PASS`. No executable input
path changes.
- Authentication and authorization: `PASS`. No identity or permission
logic changes.
- Dependencies and third-party libraries: `PASS`. No dependency changes.
- Error handling and logging: `PASS`. No runtime path changes;
diagnostic-security claims are precise.
- Cryptography and data protection: `PASS`. No implementation changes.
- Configuration and security controls: `PASS`. No configuration,
container, port, or HTTP changes.
- Security testing: `PASS`. No coverage is removed; the entry records
shipped test and security behavior.
- System security: `PASS`. No runtime control changes; dormant and
non-activation boundaries are explicit.
- Agent: Codex Desktop independent security reviewer

## Verification

- [ ] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub — verification is pending after commit
`0bebe1f568e3dc85cf410aac1dfb8f8830070b85` is pushed.
- [ ] 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 — commit hooks passed; pre-push is pending.
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — tests are not applicable to this
documentation-only recovery.
- [x] Applicable broad gate passed — not applicable to this
documentation-only recovery.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, credentials, or private keys are added by
this diff.
- [ ] `npm run docs` builds without warnings (doc changes only) — GitHub
documentation checks are pending.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only) — independent documentation review passed.
- [x] New doc pages include SPDX header and frontmatter (new pages only)
— the native changelog entry uses the required parser-safe MDX SPDX
comment and intentionally has no frontmatter.

GitHub CI is authoritative.
Focused changelog tests and `npm run docs` passed after the merge
refresh.

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added experimental Google Chat support.
  * Improved runtime and session status visibility.
  * Added onboarding recovery and persistence safeguards.
  * Added snapshot validation and dormant managed-workload support.

* **Bug Fixes**
* Improved backup sanitization, route handling, and gateway reliability.

* **Documentation**
  * Added the v0.0.101 changelog and related updates.

* **Tests**
  * Expanded end-to-end coverage and strengthened trusted CI validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Senthil Ravichandran <senthilr@nvidia.com>
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: dcode LangChain Deep Code integration behavior NV QA Bugs found by the NVIDIA QA Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] nemoclaw shields up cannot lock a Deep Agents sandbox — /sandbox/.deepagents/.config-hash does not exist

5 participants