Skip to content

fix(snapshot): stabilize pending pairing publication - #8021

Merged
senthilr-nv merged 17 commits into
mainfrom
codex/fix-snapshot-pending-publication-race
Aug 1, 2026
Merged

fix(snapshot): stabilize pending pairing publication#8021
senthilr-nv merged 17 commits into
mainfrom
codex/fix-snapshot-pending-publication-race

Conversation

@prekshivyas

@prekshivyas prekshivyas commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Snapshot restore now tolerates the brief interval while the restored gateway publishes its local pending pairing request. The approval pass retries only three publication-in-progress states with up to 10 read attempts separated by 100 ms, allowing at most 900 ms of polling delay: a missing file, invalid JSON during truncate/write, or an inode unlinked by atomic replacement. Unsafe filesystem shapes and persistently malformed state still fail closed.

The restored clone uses path-only descriptors for state-root ancestor traversal. Trusted E2E proved that the restored OpenShell policy permits traversal and metadata access while os.open("/", O_RDONLY|O_DIRECTORY|O_NOFOLLOW) returns EACCES, even though the execution identity and /sandbox/.openclaw ownership and modes are correct. Readable descriptors remain in use for the devices and identity directories where file access and fsync are required. O_DIRECTORY, O_NOFOLLOW, device/inode revalidation, link-count checks, and fail-closed receipts remain unchanged.

The restored/connect approval pass uses a 25-second outer execution cap, leaving at least 10 seconds beyond the longer bounded inner path. Host execution failures are categorized with fixed receipts that distinguish timeout, spawn, signal, nonzero-command, and invalid-receipt outcomes without exposing captured output, error text, signal values, or identifiers.

The generated approval program is streamed through stdin to sh -s instead of being placed in OpenShell command argv. This avoids the command-argument transport failure that caused the observed 33,016-byte restored-clone program to exit before Python could emit its receipt.

Restored-state read failures use fixed boundary receipts for the state path, platform support, state root, devices directory, pending descriptor safety, publication stability, and JSON shape. These diagnostics retain fail-closed behavior and do not expose paths, identifiers, tokens, exception text, or raw state.

Related Issue

Fixes #8019.

Changes

  • Use O_PATH only for restored-clone state-root ancestor traversal so OpenShell's root read restriction does not block safe descriptor-relative access.
  • Keep readable descriptors for child state directories and preserve O_DIRECTORY, O_NOFOLLOW, descriptor/inode revalidation, link-count checks, and fail-closed behavior.
  • Retry a missing pending.json, invalid JSON during truncate/write, or an opened inode unlinked by atomic replacement with up to 10 read attempts separated by 100 ms, allowing at most 900 ms of polling delay.
  • Validate the opened descriptor before and after parsing so a concurrent atomic replacement is detected rather than consumed as stale state.
  • Keep non-regular files, hard links, symlinks, changed directories, non-object documents, and persistent malformed state fail closed.
  • Keep at least 10 seconds beyond the bounded inner approval path within the 25-second outer execution cap, without adding authorization attempts.
  • Classify host-side approval execution failures with fixed, non-secret receipts while keeping raw process details private.
  • Stream the generated approval program through stdin so restored-clone script growth cannot exceed OpenShell command-argument transport.
  • Split restored-state read failures into fixed, non-secret boundary receipts without changing approval or filesystem behavior.
  • Add executable root-policy, partial-publication, atomic-replacement, hard-link, timing-budget, receipt-classification, and stdin-transport regression tests.
  • Keep the fresh-onboarding pairing target rejecting scope-upgrade-pending and approval=list-failed diagnostics so trusted E2E covers both pairing modes.

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: This repairs internal restored-clone pairing orchestration and secure descriptor traversal without changing a supported command, configuration, default, authorization rule, recovery procedure, or documented workflow. Existing guidance to retry connect remains accurate.
  • 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: Codex Desktop completed the exact-head nine-category security review with no findings: fix(snapshot): stabilize pending pairing publication #8021 (comment)
  • 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: Exact-head review confirmed this is an internal restored-clone filesystem traversal repair. It changes no user-facing command, flag, configuration, default, authorization rule, state contract, recovery procedure, or supported workflow. Existing restore and pairing recovery documentation remains accurate. Approval tests passed 13/13, restore pairing 20/20, integration 9/9, E2E support 19/19, changed tests 216/216, and typecheck, repository, test-size, and normal hooks passed.
  • Agent: Codex Desktop documentation writer subagent

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 — approval 13/13, restore pairing 20/20, integration 9/9, E2E support 19/19, and npm run test:changed 216/216; Biome, CLI typecheck, repository checks, test-size checks, and normal hooks passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: Required Linux CI and trusted live E2E are pending. The trusted plan must exercise both issue-4462-scope-upgrade-approval and snapshot-commands on exact head f02d990cd49a13469b280baf5379713bd890e6f6.
  • 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: Prekshi Vyas prekshiv@nvidia.com
Signed-off-by: Senthil Ravichandran senthilr@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved sandbox approval reliability when publication files are briefly unavailable, malformed, or replaced during processing.
    • Added safer handling for files with multiple links or files removed during processing.
    • Improved approval result handling to avoid exposing raw internal errors.
    • Improved gateway validation to reject additional invalid approval states.
  • Tests

    • Expanded coverage for timeouts, command failures, receipt classification, malformed output, transient publication conditions, and file replacement scenarios.

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The restored-clone approval script now retries bounded pending-state publication races, validates file descriptors, and uses shared timeout budgets. Tests cover transient and rotated files, hard links, receipt classification, malformed output, and gateway failure messages.

Changes

Sandbox approval robustness

Layer / File(s) Summary
Approval timing budgets
src/lib/actions/sandbox/connect-autopair-budget.ts, src/lib/actions/sandbox/connect-autopair-budget.test.ts
The flow adds pending-read and post-timeout observation budgets. The outer timeout increases to 25 seconds. Tests validate the runtime calculations and budget values.
Pending state handling
src/lib/actions/sandbox/auto-pair-approval.ts
The script retries transient absence, truncated JSON, and inode replacement. It rejects unsafe file states and invalid documents. It distinguishes multiply-linked files from entries rotated after opening.
Approval race and receipt validation
src/lib/actions/sandbox/auto-pair-approval.test.ts, src/lib/actions/sandbox/auto-pair-approval-receipt.test.ts, src/lib/actions/sandbox/auto-pair-approval-script.test.ts, test/e2e/live/issue-4462-scope-upgrade-approval.test.ts
Tests cover publication races, hard-linked files, receipt classifications, malformed output, and gateway output containing scope-upgrade-pending or approval=list-failed.

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

Sequence Diagram(s)

sequenceDiagram
  participant ApprovalScript
  participant PendingState
  participant OpenClaw
  ApprovalScript->>PendingState: poll pending.json within read budget
  PendingState-->>ApprovalScript: transient or valid pending state
  ApprovalScript->>OpenClaw: approve exact local request
  OpenClaw-->>ApprovalScript: sanitized receipt or list failure
Loading

Possibly related PRs

Suggested labels: bug-fix, area: sandbox

Suggested reviewers: cv

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #8019 with bounded publication retries, fail-closed validation, canonical approval, and regression coverage.
Out of Scope Changes check ✅ Passed All changes support issue #8019, including race handling, security validation, diagnostics, budgets, and regression tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the snapshot-related fix for the pending pairing publication race.
✨ 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 codex/fix-snapshot-pending-publication-race

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

@prekshivyas

Copy link
Copy Markdown
Collaborator Author

Verdict

PASS. I reviewed PR #8021 at exact head a0690bc23a087604cbfe79596e9aab329e0a1d78 against base 60b33abeca789b35aa8970d169948a279147376e. The bounded publication retry does not broaden request eligibility, authorization, filesystem trust, or approval count. Unsafe and persistently malformed state remains fail closed. The review found no blocking or non-blocking security findings.

Findings Table

No findings.

Detailed Analysis

  1. Secrets and Credentials — PASS. No secrets, tokens, keys, credential files, or new credential output were added. Test diagnostics continue to reject raw failure content.
  2. Input Validation and Data Sanitization — PASS. The code still accepts only an absolute clone state root, fixed directory names, and the fixed pending.json entry through descriptor-relative O_NOFOLLOW opens. It requires a JSON object before request selection.
  3. Authentication and Authorization — PASS. The retry occurs before the existing exact local identity, role, scope, paired-token, and single-request checks. It does not expand allowed scopes, identities, approval count, or canonical OpenClaw authorization.
  4. Dependencies and Third-Party Libraries — PASS. No dependency, version, registry, or license surface changed.
  5. Error Handling and Logging — PASS. Retryable parser and replacement observations are converted to existing sanitized receipts. Exceptions, state contents, paths, credentials, and raw child output are not emitted.
  6. Cryptography and Data Protection — PASS. No cryptographic algorithm, key handling, transport, or persisted sensitive-data format changed.
  7. Configuration and Security Headers — PASS. No endpoint, port, container privilege, policy, CORS, CSP, debug, or runtime configuration changed.
  8. Security Testing — PASS. The deterministic regression proves one transient partial publication stabilizes and approves only the exact local request. Script-contract assertions retain separate rejection of multiple hard links and classification of an already-unlinked opened inode; the existing malformed, ambiguous, symlink, identity, and scope tests remain in the focused 35/35 passing slice.
  9. System Security — PASS. Work is bounded to ten reads separated by 100 ms. Only FileNotFoundError, JSONDecodeError, and the explicit opened-but-unlinked inode condition are retried. Non-regular files, multiple hard links, symlinks, changed directories, other filesystem errors, non-object JSON, and persistent malformed state fail closed. Descriptor pinning and the existing post-read identity/request validation remain intact.

Files Reviewed

  • src/lib/actions/sandbox/auto-pair-approval.ts
  • src/lib/actions/sandbox/auto-pair-approval.test.ts
  • src/lib/actions/sandbox/auto-pair-approval-receipt.test.ts
  • src/lib/actions/sandbox/auto-pair-approval-script.test.ts

@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 f02d990 in the codex/fix-snapshot-p... branch remains at 96%, unchanged from commit 99d5b66 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit f02d990 in the codex/fix-snapshot-p... branch remains at 81%, unchanged from commit ffc1ae6 in the main branch.

Show a code coverage summary of the most impacted files.
File main ffc1ae6 codex/fix-snapshot-p... f02d990 +/-
src/lib/actions...opair-budget.ts 100% 100% 0%
src/lib/sandbox...rce-identity.ts 88% 88% 0%
src/lib/tunnel/services.ts 75% 75% 0%
src/lib/actions...air-approval.ts 66% 88% +22%

Updated August 01, 2026 00:54 UTC

@prekshivyas

Copy link
Copy Markdown
Collaborator Author

Cross-issue sweep progress:

  • Step 1: Extract fingerprint (files, symbols, error strings, primary issue)
  • Step 2: Search candidate issues (capped at 30, primary excluded)
  • Step 3: Classify each candidate (4-class with evidence)
  • Step 4: Apply reverse-link boost
  • Step 5: Filter (drop UNRELATED, SAME_ISSUE_DIFF, low-confidence)
  • Step 6: Render report using the repository template

Cross-issue scan — PR #8021

No adjacent fixes or contradictions found above the medium confidence floor.

Suppressed: 20 unrelated, 0 same-issue duplicates.

The closest lexical candidate, #7215, has a different root and execution path: transparent-proxy locality for warm-daemon gateway-client dial-back. PR #8021 changes only restored-clone pending.json publication stabilization before the existing exact CLI request selection, so it neither fixes nor contradicts #7215.

@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/actions/sandbox/auto-pair-approval-script.test.ts (1)

73-74: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Replace source-text checks with descriptor behavior checks.

These assertions only prove that the generated script contains both predicates. They do not prove that a zero-link descriptor retries or that a multiply-linked descriptor fails closed.

Execute the generated script with real hard-link and atomic-replacement fixtures.

As per path instructions, tests must prefer observable outcomes over source-text assertions.

🤖 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/actions/sandbox/auto-pair-approval-script.test.ts` around lines 73 -
74, Replace the source-text assertions in the restoredClone test with behavioral
checks of the generated script: execute it against real hard-link and
atomic-replacement fixtures, verify zero-link descriptors retry, and verify
multiply-linked descriptors fail closed. Preserve the existing generated-script
setup while asserting observable outcomes rather than predicate text.

Source: Path instructions

src/lib/actions/sandbox/auto-pair-approval.test.ts (1)

411-425: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an atomic-replacement test for the opened descriptor.

This fixture injects JSONDecodeError before the production code can observe a zero link count. It tests malformed JSON retry, but it does not test the rotated-inode path.

Add a fixture that calls os.replace after opening the descriptor and before the post-read validation. Assert that the next retry approves the replacement state.

As per path instructions, tests must prefer observable outcomes over source-text or implementation assertions.

🤖 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/actions/sandbox/auto-pair-approval.test.ts` around lines 411 - 425,
Extend the transient publication fixture in the test around
transientPendingPublicationScript to call os.replace after opening the
descriptor and before post-read validation, simulating an atomic inode rotation.
Assert the observable outcome that the subsequent retry approves the replacement
state, rather than asserting injected script text or implementation details.

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/actions/sandbox/auto-pair-approval-receipt.test.ts`:
- Around line 17-20: Replace the test-body availability check in the test case
with an it.skipIf(...) condition that checks whether python3 is available, so
the test is skipped before execution without adding an executable conditional
inside the body.

In `@src/lib/actions/sandbox/auto-pair-approval.ts`:
- Around line 420-423: Update open_clone_json_descriptor in
src/lib/actions/sandbox/auto-pair-approval.ts at lines 420-423 to repeat
regular-file and link-count validation after json.load, mapping st_nlink == 0 to
CloneStateEntryRotated. In src/lib/actions/sandbox/auto-pair-approval.test.ts at
lines 411-425, add an atomic os.replace-after-open fixture that verifies retry
and approval of the replacement state. In
src/lib/actions/sandbox/auto-pair-approval-script.test.ts at lines 73-74,
replace source-text checks with executable hard-link and rotated-inode cases
that assert observable outcomes.

---

Nitpick comments:
In `@src/lib/actions/sandbox/auto-pair-approval-script.test.ts`:
- Around line 73-74: Replace the source-text assertions in the restoredClone
test with behavioral checks of the generated script: execute it against real
hard-link and atomic-replacement fixtures, verify zero-link descriptors retry,
and verify multiply-linked descriptors fail closed. Preserve the existing
generated-script setup while asserting observable outcomes rather than predicate
text.

In `@src/lib/actions/sandbox/auto-pair-approval.test.ts`:
- Around line 411-425: Extend the transient publication fixture in the test
around transientPendingPublicationScript to call os.replace after opening the
descriptor and before post-read validation, simulating an atomic inode rotation.
Assert the observable outcome that the subsequent retry approves the replacement
state, rather than asserting injected script text or implementation details.
🪄 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: 7a7e5add-7870-4b4f-99e8-148ab1055f2f

📥 Commits

Reviewing files that changed from the base of the PR and between 60b33ab and a0690bc.

📒 Files selected for processing (4)
  • src/lib/actions/sandbox/auto-pair-approval-receipt.test.ts
  • src/lib/actions/sandbox/auto-pair-approval-script.test.ts
  • src/lib/actions/sandbox/auto-pair-approval.test.ts
  • src/lib/actions/sandbox/auto-pair-approval.ts

Comment thread src/lib/actions/sandbox/auto-pair-approval-receipt.test.ts Outdated
Comment thread src/lib/actions/sandbox/auto-pair-approval.ts Outdated
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@prekshivyas

Copy link
Copy Markdown
Collaborator Author

Exact-head security review update

PASS at f41db9e6ee84ce691218ca4a59e638898a0c6f40 against base 60b33abeca789b35aa8970d169948a279147376e; no findings.

The only delta from the full nine-category review at a0690bc23 is test-only: the receipt proof uses Vitest it.skipIf instead of an imperative Python-availability branch. It changes no production code, fixture inputs, assertions, credentials, authorization, filesystem handling, logging, dependencies, cryptography, configuration, or runtime behavior.

All nine verdicts remain PASS: 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; and System Security.

Full analysis: #8021 (comment)

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@prekshivyas

prekshivyas commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Exact-head security review

PASS at b4d7085113f630d493f0d4fff9b53fede59a48d1 against base 299050fc0563db0cd3a803298a6fb986dcfbb745; no findings.

The post-review hardening closes the descriptor TOCTOU window identified by CodeRabbit. Regular-file and link-count validation now runs both before and after JSON parsing. An atomic replacement after open makes the old descriptor unlinked, maps only that state to the bounded retry, and the retry opens and validates the replacement file. Multiple hard links, non-regular files, symlinks, changed directories, other filesystem errors, non-object JSON, and persistent malformed JSON remain fail closed.

  1. Secrets and Credentials — PASS. No secrets, tokens, keys, credential files, or credential output changed.
  2. Input Validation and Data Sanitization — PASS. Fixed path components, descriptor-relative O_NOFOLLOW opens, regular-file checks, link-count checks, and object-shape validation remain enforced.
  3. Authentication and Authorization — PASS. Retry still precedes and does not alter exact identity, role, scope, paired-token, single-request, or canonical approval checks.
  4. Dependencies and Third-Party Libraries — PASS. No dependency or supply-chain surface changed.
  5. Error Handling and Logging — PASS. Only sanitized existing receipts are emitted; state, exceptions, paths, credentials, and raw output are not exposed.
  6. Cryptography and Data Protection — PASS. No cryptographic or protected-data format changed.
  7. Configuration and Security Headers — PASS. No endpoint, port, privilege, policy, container, or web-security configuration changed.
  8. Security Testing — PASS. Executable tests now prove partial JSON stabilization, atomic replacement after descriptor open, and fail-closed multiple-hard-link behavior. Focused source coverage passes 42/42; trusted live coverage for both pairing modes is pending.
  9. System Security — PASS. The retry is bounded to ten reads with 100 ms intervals, detects inode rotation after parsing, retains descriptor pinning, and does not weaken least privilege or approval selection.

Files reviewed: auto-pair-approval.ts, auto-pair-approval.test.ts, auto-pair-approval-receipt.test.ts, auto-pair-approval-script.test.ts, and issue-4462-scope-upgrade-approval.test.ts.

@github-actions

github-actions Bot commented Jul 31, 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 · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 more warning, the same number of suggestions.
2 additional E2E selections from the second opinion

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

  • device-auth-health: 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.

Second-opinion 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: issue-4462-scope-upgrade-approval, onboard-repair, onboard-resume, snapshot-commands

Workflow run details

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

@senthilr-nv
senthilr-nv enabled auto-merge (squash) July 31, 2026 19:06
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Security review — exact head 34cf60afb

Verdict

PASS. Safe to merge from a security perspective. The follow-up changes only bounded internal timing: it keeps the restored/connect approval limit at one, preserves the existing allowlist and descriptor validation, and gives the outer process enough time to return its fixed sanitized receipt. No findings.

Findings

No findings.

Detailed analysis

  1. Secrets and credentials — PASS: No secrets or credential material were added. Tests continue to use fixtures, and the approval path does not expose captured output.
  2. Input validation and data sanitization — PASS: User-controlled input handling is unchanged. The new interpolated values are fixed numeric constants; the restored state reader retains regular-file, link-count, directory-identity, JSON-shape, and request-shape checks.
  3. Authentication and authorization — PASS: The allowlist, required scopes, paired identity checks, and single canonical approval limit are unchanged. Raising the outer cap does not authorize another attempt.
  4. Dependencies and third-party libraries — PASS: No dependency or registry change.
  5. Error handling and logging — PASS: The clone-only result remains a fixed receipt; raw command output, request identifiers, tokens, and internal exceptions are not returned.
  6. Cryptography and data protection — PASS: No cryptographic primitive, token representation, or transport behavior changed.
  7. Configuration and security headers — PASS: No container, network-policy, port, privilege, HTTP, or security-header change.
  8. Security testing — PASS: Regression coverage exercises partial publication, atomic replacement, hard-link rejection, fixed receipts, the one-approval budget invariant, and both trusted pairing modes. Local focused tests passed 29/29 and changed tests passed 217/217.
  9. System security — PASS: The change preserves fail-closed filesystem handling and TOCTOU defenses. The outer cap now covers the bounded pending-read and post-timeout observation paths with 10 seconds of process-startup headroom; it does not add retries to the authorization operation.

Files reviewed

  • src/lib/actions/sandbox/auto-pair-approval.ts
  • src/lib/actions/sandbox/connect-autopair-budget.ts
  • src/lib/actions/sandbox/connect-autopair-budget.test.ts
  • src/lib/actions/sandbox/auto-pair-approval-receipt.test.ts
  • src/lib/actions/sandbox/auto-pair-approval-script.test.ts
  • src/lib/actions/sandbox/auto-pair-approval.test.ts
  • test/e2e/live/issue-4462-scope-upgrade-approval.test.ts

@senthilr-nv senthilr-nv self-assigned this Jul 31, 2026
@senthilr-nv senthilr-nv added v0.0.101 Release target bug-fix PR fixes a bug or regression area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: security Security controls, permissions, secrets, or hardening security and removed v0.0.100 labels Jul 31, 2026
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Exact-head security review update

PASS at be90d672fe4bd4715fbed4bf23786b332d9ab64f against base 90f73918eeed5dcef9fe5733608e0a40dc3a7411; no findings.

The only head change after the full nine-category PASS review at 34cf60afb is a verified merge of the new main. With upstream/main refreshed, the PR diff remains the same seven reviewed pairing files and git diff --check upstream/main...HEAD passes. No PR code, test, authorization, allowlist, approval count, descriptor validation, error receipt, dependency, configuration, cryptography, or logging behavior changed in the merge.

All nine verdicts remain PASS: 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; and System Security.

@senthilr-nv senthilr-nv added v0.0.100 and removed v0.0.101 Release target labels Jul 31, 2026
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Exact-head security review update

PASS. I reviewed PR #8021 at exact head a85be064db3c37f76cb1fcb1dd1629fd88625be5 against base 90f73918eeed5dcef9fe5733608e0a40dc3a7411. The follow-up preserves a bounded 30-second OpenShell transport margin outside the existing bounded in-sandbox path. It changes no request eligibility, authorization, allowlist, approval count, credential handling, or diagnostic output. No blocking or non-blocking security findings.

  1. Secrets and credentials — PASS. No secret, token, key, credential file, or raw child output is added.
  2. Input validation and sanitization — PASS. Existing descriptor-relative, fail-closed restored-state validation is unchanged.
  3. Authentication and authorization — PASS. Exact local identity, scope, paired-token, and single-request checks remain unchanged; only the host-side execution ceiling changes.
  4. Dependencies and third-party libraries — PASS. No dependency, version, registry, or license surface changes.
  5. Error handling and logging — PASS. Fixed sanitized receipts and failure classifications are unchanged.
  6. Cryptography and data protection — PASS. No cryptographic, key-handling, transport-protection, or persisted-data format changes.
  7. Configuration and security headers — PASS. No endpoint, port, privilege, policy, CORS, CSP, debug, or runtime configuration changes.
  8. Security testing — PASS. The budget test now proves that the 45-second outer cap retains at least the fixed 30-second transport margin beyond the worst bounded inner path. The focused approval/restore suite passed 30 tests, and the changed-test selection passed 218 tests.
  9. System security — PASS. Work remains bounded to one canonical approval attempt. The larger outer cap allows transport and interpreter startup to complete but does not add retries or extend the inner OpenClaw approval deadline.

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Exact-head security review — bca6e3c7b238480a7fdc2d7a25d0e40bc0c5d983

Verdict: PASS — no blocking security finding.

Category Result Evidence
Secrets and credentials PASS No secrets are added or logged. Captured stdout, stderr, error messages, signal values, request IDs, and device IDs remain private.
Input validation and sanitization PASS Restored-clone selection still requires canonical descriptor-backed JSON, regular single-link files, stable directories, an exact local device/public-key match, and bounded roles/scopes. Retry is limited to missing publication, invalid JSON during publication, or a replaced inode.
Authentication and authorization PASS The compatibility path remains clone-local and permits only the reviewed cli/operator pairing-to-write transition. Unknown, ambiguous, or mismatched requests fail closed before approval.
Dependencies and third-party libraries PASS No dependency or action pin changes.
Error handling and logging PASS Host execution failures now map to fixed non-secret receipts (timeout, spawn, signal, command, or invalid receipt) without forwarding raw command output. The unknown catch path remains the fixed exec-failed fallback.
Cryptography and data protection PASS No cryptographic primitive or storage-contract change. Rotated credentials are still synchronized through the existing mode-0600 atomic replacement path.
Configuration and security headers PASS No exposed service, policy, header, or supported configuration change. The bounded outer timeout returns to 25 seconds; the unsupported 45-second hypothesis is removed.
Security testing PASS Added receipt-classification coverage; changed tests passed 219/219, focused approval tests 15/15, restore/pairing tests 17/17, CLI type-check passed, and normal commit/pre-push hooks passed.
System security PASS Descriptor pinning, O_NOFOLLOW, directory identity checks, link-count checks, one canonical approval attempt, and bounded subprocess timers remain intact. No shell interpolation or privilege expansion is introduced.

Files reviewed: all 7 files changed from base 90f73918eeed5dcef9fe5733608e0a40dc3a7411 through exact head bca6e3c7b238480a7fdc2d7a25d0e40bc0c5d983.

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Exact-head security review addendum — 1e4a9a0673ff004a35fb7dedebb65c7cd31bc20c

Verdict: PASS — no blocking finding in any of the nine security categories.

The only change after the full nine-category review at bca6e3c7b is a test-title clarification from “sanitized” to “omits raw output.” It changes no executable code or security behavior. The prior evidence remains exact for secrets/credentials, validation, authentication/authorization, dependencies, error handling/logging, cryptography/data protection, configuration/security headers, security testing, and system security.

Exact-head verification: the focused receipt test passed 2/2, normal commit hooks passed, pre-push CLI type-check passed, and GitHub commit verification is being checked for this head.

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Exact-head sensitive-path security review

Reviewed head: b9ddd0c7459d0faf90692ed6ff144d653b5a876a

Result: PASS — no findings.

  1. Secrets and sensitive output — PASS. The generated approval program is now carried on stdin instead of process argv, reducing process-list exposure. Fixed receipts continue to omit stdout, stderr, exception text, signal values, sandbox identifiers, and credential material.
  2. Injection and command execution — PASS. The sandbox name remains a distinct OpenShell argument, while the internally generated program is supplied to sh -s as stdin. No user-controlled string is promoted into a shell command by this change.
  3. Authentication and authorization bypass — PASS. The change does not broaden the local-device allowlist, approval count, candidate selection, or scope-upgrade rules. It only makes the existing authenticated approval pass reach execution reliably.
  4. Unsafe configuration or fail-open behavior — PASS. Pending-state reads still fail closed for symlinks, non-regular files, hard links, directory replacement, non-object JSON, and persistent malformed state. Only the three bounded publication-in-progress states retry.
  5. Path traversal and filesystem races — PASS. The full PR validates directory and descriptor identity around reads and rejects unsafe file shapes. The stdin transport change does not alter filesystem paths.
  6. SSRF and network policy bypass — PASS. No endpoint, egress, policy, or network-routing behavior changes.
  7. Privilege and sandbox boundary — PASS. Execution remains inside the named OpenShell sandbox. No capability, privilege, host mount, or boundary is added.
  8. Resource exhaustion and lifecycle — PASS. The approval pass retains its 25-second outer cap and bounded inner retries; stdin streaming introduces no unbounded loop or retained process.
  9. Dependencies and supply chain — PASS. No dependency, action, image, installer source, or generated artifact pin changes.

Validation reviewed: normal hooks passed; focused approval/receipt suites passed 29/29; npm run test:changed passed 216/216; CLI type-check and build passed. The exact trusted live E2E is running separately and does not change this static security result.

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
@senthilr-nv

Copy link
Copy Markdown
Collaborator

Exact-head sensitive-path security review addendum

Reviewed head: 1aa00507fc715eb7d1a3e89c5973b6f9e211aa77

Result: PASS — no findings.

The only delta after the full nine-category review at b9ddd0c7459d0faf90692ed6ff144d653b5a876a is test-only. The fake OpenShell integration fixture records sandbox-exec stdin, identifies the internal approval program from that recorded input, asserts the real argv ends in sh -s, and asserts the program is absent from argv. It changes no production code, authorization, credential handling, filesystem trust, network policy, privilege, timeout, dependency, or runtime configuration.

All nine prior verdicts remain PASS: secrets and sensitive output; injection and command execution; authentication and authorization; unsafe configuration and fail-open behavior; path traversal and filesystem races; SSRF and network policy; privilege and sandbox boundary; resource exhaustion and lifecycle; dependencies and supply chain.

Exact-head evidence: the focused integration suite passed 9/9, normal hooks passed, and pre-push CLI type-check passed.

@senthilr-nv

Copy link
Copy Markdown
Collaborator

Security review addendum for exact head 6920013da6a41e897203067ebd53dd11530890c8:

  • Secrets and sensitive output: PASS — the new receipts are fixed literals and do not include paths, identifiers, tokens, command output, or exception text.
  • Injection and command execution: PASS — no command construction, argv, stdin, subprocess, or shell behavior changed.
  • Authentication and authorization: PASS — approval selection, allowlists, canonical approval, and fail-closed behavior are unchanged.
  • Input and state validation: PASS — existing validation branches retain the same exits; only their sanitized classifications are made specific.
  • Permissions and filesystem safety: PASS — descriptor, no-follow, inode, hard-link, and shape checks are unchanged.
  • Dependencies and supply chain: PASS — no dependency or lockfile changes.
  • Logging and privacy: PASS — classifications reveal only the bounded failure layer, not raw state or private values.
  • Configuration and deployment: PASS — no configuration or deployment changes.
  • Test coverage: PASS — focused approval/receipt/restore suite passed 27/27; normal hooks and CLI typecheck passed.

Result: PASS. This commit is diagnostic-only and does not relax the restored-clone pairing boundary.

@senthilr-nv

Copy link
Copy Markdown
Collaborator

Security review — PASS

Reviewed exact head f02d990cd49a13469b280baf5379713bd890e6f6 against base ffc1ae6f438a0a16f37a184b4e6198dacf9223aa. No security findings; this head is safe to merge once required CI and trusted E2E pass.

No findings table is included because the review found no actionable issue.

  1. Secrets and credentials — PASS. No secrets or credential material were added; fixed receipts continue to suppress raw command output and identifiers.
  2. Input validation and sanitization — PASS. State paths remain absolute-only; dot segments, unsupported directory names, separator-bearing entries, non-regular files, hard links, symlinks, changed directories, and invalid JSON shapes fail closed.
  3. Authentication and authorization — PASS. Approval remains limited to one exact local clone pairing transition and delegates the write to canonical openclaw devices approve; no scope or allowlist was widened.
  4. Dependencies — PASS. No dependency or third-party code changes.
  5. Error handling and logging — PASS. Execution and state failures use fixed terminal receipts; raw stderr, tokens, paths, request IDs, and exception details are not returned.
  6. Cryptography and data protection — PASS. No cryptographic behavior changed; existing identity/public-key and token validation remains intact.
  7. Configuration and security headers — PASS. No network, container, port, header, or runtime configuration was weakened.
  8. Security testing — PASS. The restored-clone regression proves the legacy read-directory walk fails at / with list-state-root-failed, while path-only ancestor traversal reaches clone state. Existing symlink, hard-link, rotation, malformed-state, and TOCTOU cases remain covered.
  9. System security — PASS. O_PATH is used only for ancestor/state-root traversal. O_DIRECTORY and O_NOFOLLOW remain mandatory; child state directories retain readable descriptors for fsync; every directory is revalidated by device/inode before use; state files retain O_NOFOLLOW, regular-file, link-count, and post-read revalidation.

Files reviewed: src/lib/actions/sandbox/auto-pair-approval.ts, src/lib/actions/sandbox/connect-autopair-budget.ts, their five changed focused tests, test/sandbox-connect-inference/helpers.ts, its integration test, and the two changed live E2E tests (11 files total).

Evidence: approval suites 13/13, restore-pairing/budget 20/20, integration 9/9, E2E support 19/19, npm run test:changed 216/216, CLI typecheck, repository checks, test-size checks, and normal commit/pre-push hooks passed. Trusted snapshot-commands on this exact head remains the final behavioral gate.

@senthilr-nv
senthilr-nv merged commit 02b2c74 into main Aug 1, 2026
74 of 75 checks passed
@senthilr-nv
senthilr-nv deleted the codex/fix-snapshot-pending-publication-race branch August 1, 2026 01:10
@senthilr-nv senthilr-nv mentioned this pull request Aug 1, 2026
23 tasks
senthilr-nv added a commit that referenced this pull request Aug 1, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Adds the canonical dated changelog entry for `v0.0.100` so the
maintainer release plan can verify the pre-tag documentation
prerequisite. The entry summarizes the user-facing changes merged since
`v0.0.99` and links to the relevant guides.

## Changes

- Add `docs/changelog/2026-07-31.mdx` with the exact `## v0.0.100`
heading.
- Cover restored OpenClaw pairing, transactional replacement, Deep
Agents Code, onboarding recovery, lifecycle cleanup, Hermes builds, host
provenance, documentation, and trusted E2E evidence.
- Distinguish active Docker and Kubernetes runtime-bundle enforcement
from the still-inactive managed shared-state transaction foundation.

## Source Coverage

The release entry maps the doc-impacting merged PRs in the
`v0.0.99..main` release range to `docs/changelog/2026-07-31.mdx`: #8021,
#8024, #7973, #8028, #7947, #7788, #7884, #8023, #7969, #8020, #7989,
#8000, #7907, #7942, #7567, #8013, #7955, #8017, #8014, #8015, #7629,
#7644, #7821, #7971, and #7991.

PR #7974 was reviewed after the final rebase and excluded because it
changes internal maintainer-skill attribution policy and tests only; it
does not change a user-facing product or documentation surface.

## 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
- [x] Existing tests cover changed behavior — justification: the
changelog contract test validates the dated entry, version heading, SPDX
form, and route constraints.
- [ ] Tests not applicable — justification:
- [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: `docs/changelog/2026-07-31.mdx`; exact-head review passed
for `6093f44f`; writing rules and documentation style reviewed; `npx
vitest run test/changelog-docs.test.ts` passed 6/6; `npm run docs`
passed with zero Fern errors and two generic Fern upgrade notices.
- Agent: Codex Desktop
<!-- docs-review-head-sha: 6093f44 -->
<!-- docs-review-agents-blob-sha: 3dd7c24 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit: Not applicable; no DGX Station host script changed.
- Station profile/scenario: Not applicable.
- Result: Not applicable.
- Supporting evidence: Not applicable.

## 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, or tests
are marked not applicable above — command/result or justification: `npx
vitest run test/changelog-docs.test.ts` passed 6/6 at `6093f44f`.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: Not applicable to a dated
prose-only release entry.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) —
validation passed with zero errors; Fern emitted two generic upgrade
notices.
- [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)
— the changelog entry has the required parser-safe MDX SPDX header;
dated changelog entries intentionally do not use page frontmatter.

---

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
  * Added release notes for v0.0.100.
* Documented improvements to restore pairing, sandbox replacement,
onboarding recovery, lifecycle cleanup, runtime handling, build support,
host readiness, and end-to-end validation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-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 area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Restored snapshot pairing can fail while pending device state is published

3 participants