Skip to content

fix(images): replay MCP discovery permissions - #8745

Closed
jyaunches wants to merge 4 commits into
mainfrom
codex/mcp-discovery-runtime-permissions
Closed

fix(images): replay MCP discovery permissions#8745
jyaunches wants to merge 4 commits into
mainfrom
codex/mcp-discovery-runtime-permissions

Conversation

@jyaunches

@jyaunches jyaunches commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Exact staging run 31396519688 showed that Docker preserved mode 0664 from the build context when it copied the reviewed MCP discovery runtime. Replay root ownership and read-only modes in each final image before bundle execution, while keeping the existing fail-closed tree assertion unchanged. Add a PR-only Deep Agents Code regression that rebuilds the exact staging source and recorded Docker recipe without claiming that the unavailable historical image was reproduced byte-for-byte.

Related Issue

Fixes #8665.

PR #8702 independently overlaps this defect. Its current head lost the permission-normalizing COPY options during conflict resolution and all three managed-image builds reproduce the 0664 failure. This PR uses a distinct legacy-builder-compatible final-image replay and does not transfer that PR's code, tests, managed-startup copy changes, or runtime-directory diagnostics.

Changes

  • Replay root:root ownership, directory mode 0555, and regular-file mode 0444 under /usr/local/lib/nemoclaw/mcp-tool-discovery-runtime in the OpenClaw, Hermes, and Deep Agents Code final images.
  • Use non-dereferencing traversal so the replay cannot change an out-of-tree link target, then run the unchanged find -L tree assertion after bundle validation.
  • Report a named permission-replay failure without changing the existing bundle, JSON, tree, or managed-startup diagnostics.
  • Execute the shared Dockerfile replay against the real reviewed bundle at mode 0664, run the bundle afterward, and verify ownership, modes, bytes, failure behavior, and link scope for all three Dockerfiles.
  • Make the PR image workflow reproduce mode 0664 before each real managed-image build, then inspect the immutable final image for root ownership, 0555/0444 modes, and the exact bundle contract.
  • Rebuild the staging base from exact NemoClaw source d097a22145859102c0495b0310de264b7a27624f, apply the recorded final-image build arguments, prove layer ancestry, and run the final-image contract. The recorded ceaa94... index was local-only and unavailable, so the job treats it as provenance rather than an executable image identity.
  • Keep classic Docker builder compatibility by applying permissions in the final RUN layer instead of using COPY --chmod or COPY --chown.
  • Do not dispatch a Brev image build; exact staging validation remains a post-merge step.

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 restores an internal managed-image file-permission invariant. It changes no public command, configuration, default, API, operator workflow, or successful user behavior.
  • 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 independently reviewed exact head 7eeaefa24 across all nine security categories, including shell status handling, symlink scope, ownership and mode enforcement, output privacy, workflow authorization, and the historical-image limitation. It found no actionable security issue.
  • 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: The change repairs internal managed-image MCP tool-discovery filesystem metadata and adds CI-only regression coverage. It does not change public commands, configuration, defaults, APIs, or operator workflows; existing MCP tool-discovery documentation remains accurate.
  • 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 — 68 tests passed across the managed-image workflow, MCP discovery image contract, and all three final-image layout contracts; the 19-test workflow contract was rerun after the provenance wording correction.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — not applicable to this scoped image-permission repair. npm run validate:pr passed on exact head 7eeaefa24, including repository checks, source-shape budgets, Biome, hadolint, secret scanning, and CLI typecheck.
  • 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: Julie Yaunches jyaunches@nvidia.com

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@jyaunches jyaunches self-assigned this Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The Dockerfiles normalize ownership and permissions for the MCP tool-discovery runtime tree. The workflow reproduces permission drift and validates the built image. Contract tests verify failure handling, modes, ownership, content preservation, and symlink boundaries.

Changes

Discovery runtime permissions

Layer / File(s) Summary
Dockerfile permission replay
Dockerfile, agents/hermes/Dockerfile, agents/langchain-deepagents-code/Dockerfile
Each image build applies root ownership to the discovery-runtime tree, sets directories to 0555 and files to 0444, and reports failures through the managed-image assertion handler.
Managed image contract validation
.github/workflows/managed-images.yaml, test/managed-image-publication-workflow.test.ts
The workflow reproduces writable artifact modes before the local build. It validates image ownership, modes, symlink handling, and the invalid-arguments response. Tests verify step ordering and permission-drift behavior.
Permission replay contract tests
test/support/managed-bootstrap-image-contract.ts
The tests extract and execute the replay command against temporary fixtures. They verify failure propagation, ownership, modes, unchanged contents, and non-dereferenced symlinks. Cleanup restores writable permissions before removal.

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

Sequence Diagram(s)

sequenceDiagram
  participant Workflow
  participant ImageBuild
  participant DiscoveryRuntime
  Workflow->>Workflow: Reproduce permission drift
  Workflow->>ImageBuild: Build managed image
  ImageBuild->>DiscoveryRuntime: Normalize ownership and modes
  Workflow->>DiscoveryRuntime: Run discovery contract probe
  DiscoveryRuntime-->>Workflow: Return permissions and invalid-argument results
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#8642: Adds related managed-runtime ownership and mode assertions in image Dockerfiles.
  • NVIDIA/NemoClaw#8651: Stages the reviewed MCP tool-discovery artifacts handled by this change.
  • NVIDIA/NemoClaw#8702: Overlaps in Dockerfile runtime-tree normalization and managed-image contract tests.

Suggested labels: area: sandbox, area: security

Suggested reviewers: cv

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #8665 by replaying secure permissions, preserving fail-closed checks, adding failure reporting, and adding producer-equivalent coverage.
Out of Scope Changes check ✅ Passed The Dockerfile, workflow, and test changes directly support the image permission fix and related managed-image contract validation.
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 and concisely describes the main change: replaying MCP discovery permissions in images.
✨ 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/mcp-discovery-runtime-permissions

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

@github-code-quality

github-code-quality Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit a5fe6c4 in the codex/mcp-discovery-... branch remains at 96%, unchanged from commit f042117 in the main branch.


Updated August 10, 2026 17:45 UTC

@github-actions

github-actions Bot commented Aug 10, 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 · 0 warnings · 0 suggestions
  • Model comparison: normalized findings match; normalized terminology decisions differ; normalized E2E selections differ; severity counts match.
2 terminology differences from the second opinion

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

  • discovery permission drift at .github/workflows/managed-images.yaml:97: selected only by the second-opinion lane as justified.
  • permission-replay at Dockerfile:1521: selected only by the second-opinion lane as justified.

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

3 semantic terminology decisions

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

  • established — permission drift at .github/workflows/managed-images.yaml:97: Retain “permission drift” for unintended filesystem-mode or ownership variation.
  • justified — permission replay at Dockerfile:1521: Retain “permission replay” for the final-image ownership and mode reapplication.
  • justified — discovery contract at .github/workflows/managed-images.yaml:303: Retain “discovery contract” for the MCP tool-discovery JSON response contract.

E2E guidance

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

Recommended E2E: cloud-onboard, full-e2e, hermes-e2e, hermes-inference-switch, managed-image-multiarch-startup, security-posture, ubuntu-repo-cloud-langchain-deepagents-code

1 optional E2E recommendation
  • managed-image-protected-runtime

Workflow run details

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

Comment thread test/support/managed-bootstrap-image-contract.ts Fixed
Comment thread test/support/managed-bootstrap-image-contract.ts Fixed
Signed-off-by: Julie Yaunches <jyaunches@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.

🧹 Nitpick comments (1)
test/support/managed-bootstrap-image-contract.ts (1)

95-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reduce exact Dockerfile text assertions.

These assertions require one specific command spelling and ordering. Equivalent safe implementations can fail this test without changing the image contract.

Keep the fixture execution checks for failure reporting, ownership, modes, content, and symlink scope. Move remaining structural requirements to built-image behavior checks where possible.

As per path instructions, “Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call 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 `@test/support/managed-bootstrap-image-contract.ts` around lines 95 - 110,
Reduce the exact Dockerfile instruction assertions in the test covering
mcp-tool-discovery and managed startup metadata, retaining only checks needed
for fixture failure reporting and observable ownership, mode, content, and
symlink behavior. Remove assertions that depend on a specific command spelling
or ordering, and move structural requirements to built-image behavior checks
where feasible, following the public-boundary path guidance.

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.

Nitpick comments:
In `@test/support/managed-bootstrap-image-contract.ts`:
- Around line 95-110: Reduce the exact Dockerfile instruction assertions in the
test covering mcp-tool-discovery and managed startup metadata, retaining only
checks needed for fixture failure reporting and observable ownership, mode,
content, and symlink behavior. Remove assertions that depend on a specific
command spelling or ordering, and move structural requirements to built-image
behavior checks where feasible, following the public-boundary path guidance.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8fb8dd1d-980d-42df-a320-8ccfb8982d82

📥 Commits

Reviewing files that changed from the base of the PR and between b3c0a02 and 241c4b7.

📒 Files selected for processing (3)
  • .github/workflows/managed-images.yaml
  • test/managed-image-publication-workflow.test.ts
  • test/support/managed-bootstrap-image-contract.ts

Signed-off-by: Julie Yaunches <jyaunches@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: 1

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

Inline comments:
In `@test/managed-image-publication-workflow.test.ts`:
- Around line 491-494: Update the workflow response validator tested by the
assertions around contractSource to reject any keys outside the complete allowed
response shape, while preserving validation of protocol, ok, and detail. Replace
the invalid NaN-based extra-field fixture near the relevant test cases with
valid JSON such as an extra boolean property, and assert that the validator
rejects it so the test proves unknown-field behavior rather than JSON parsing
failure.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6db83399-4fca-4268-9af4-747336b0ba5c

📥 Commits

Reviewing files that changed from the base of the PR and between 241c4b7 and 2089c60.

📒 Files selected for processing (2)
  • .github/workflows/managed-images.yaml
  • test/managed-image-publication-workflow.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/managed-images.yaml

Comment on lines +491 to +494
expect(contractSource).toContain('result = JSON.parse(require("node:fs").readFileSync(0');
expect(contractSource).toContain("record.protocol !== expected.protocol");
expect(contractSource).toContain("record.ok !== expected.ok");
expect(contractSource).toContain("record.detail !== expected.detail");

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject valid extra fields in the contract test.

Line 577 uses NaN, which is invalid JSON. JSON.parse rejects it before the field validator runs. A valid extra property, such as "extra":true, currently passes because the validator checks only three required fields.

Define the complete allowed response shape. Reject unknown keys in the workflow validator. Add a valid extra-field fixture to this test.

Proposed test fixture change
- '{"protocol":1,"ok":false,"detail":"tool discovery received invalid runtime arguments","extra":NaN}\n',
+ '{"protocol":1,"ok":false,"detail":"tool discovery received invalid runtime arguments","extra":true}\n',

As per path instructions, tests must prove observable behavior rather than a parser failure.

Also applies to: 562-569, 575-578

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

In `@test/managed-image-publication-workflow.test.ts` around lines 491 - 494,
Update the workflow response validator tested by the assertions around
contractSource to reject any keys outside the complete allowed response shape,
while preserving validation of protocol, ok, and detail. Replace the invalid
NaN-based extra-field fixture near the relevant test cases with valid JSON such
as an extra boolean property, and assert that the validator rejects it so the
test proves unknown-field behavior rather than JSON parsing failure.

Source: Path instructions

@wscurran wscurran added area: packaging Packages, images, registries, installers, or distribution bug-fix PR fixes a bug or regression integration: dcode LangChain Deep Code integration behavior integration: hermes Hermes integration behavior integration: openclaw OpenClaw integration behavior labels Aug 10, 2026
jyaunches added a commit that referenced this pull request Aug 10, 2026
<!-- markdownlint-disable MD041 -->
## Summary

[Exact staging run
31396519688](https://github.com/brevdev/nemoclaw-image/actions/runs/31396519688)
showed that Docker preserved mode `0664` from the build context when it
copied the reviewed MCP discovery runtime. Replay root ownership and
read-only modes in each final image before bundle execution, while
keeping the existing fail-closed tree assertion unchanged. Add a PR-only
Deep Agents Code regression that rebuilds the exact staging source and
effective Docker configuration without claiming that the unavailable
historical image was reproduced byte-for-byte.

## Related Issue

Fixes #8665.

Supersedes #8745. GitHub accepted that PR's final fast-forward branch
update but did not synchronize its pull ref, commit list, or PR checks.
This replacement carries that GitHub-Verified history plus the review
repairs at commit `cef961c6ba411682a60819b02a9096b161374e8d` on a fresh
branch.

Independently supersedes the permission-fix scope of #8702. Its latest
PR commit lost the permission-normalizing `COPY` options during conflict
resolution and all three managed-image builds reproduce the `0664`
failure. This PR uses a distinct legacy-builder-compatible final-image
replay and does not transfer that PR's code, tests, managed-startup copy
changes, or runtime-directory diagnostics.

## Changes

- Replay `root:root` ownership, directory mode `0555`, and regular-file
mode `0444` under `/usr/local/lib/nemoclaw/mcp-tool-discovery-runtime`
in the OpenClaw, Hermes, and Deep Agents Code final images.
- Use non-dereferencing traversal so the replay cannot change an
out-of-tree link target, then run the unchanged `find -L` tree assertion
after bundle validation.
- Report a named permission-replay failure without changing the existing
bundle, JSON, tree, or managed-startup diagnostics.
- Execute the shared Dockerfile replay against the real reviewed bundle
at mode `0664`, run the bundle afterward, and verify ownership, modes,
bytes, failure behavior, and link scope for all three Dockerfiles.
- Make the PR image workflow reproduce mode `0664` before each real
managed-image build, then inspect the immutable final image for root
ownership, `0555`/`0444` modes, and the exact bundle contract.
- Rebuild the staging base from exact NemoClaw source
`d097a22145859102c0495b0310de264b7a27624f`, apply the staging run's
effective final-image configuration through the declared build
arguments, prove layer ancestry, and run the final-image contract. The
recorded `ceaa94...` index was local-only and unavailable, so the job
treats it as provenance rather than an executable image identity.
- Keep classic Docker builder compatibility by applying permissions in
the final `RUN` layer instead of using `COPY --chmod` or `COPY --chown`.
- Do not dispatch a Brev image build; exact staging validation remains a
post-merge step.

## 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)

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: This restores an internal
managed-image file-permission invariant. It changes no public command,
configuration, default, API, operator workflow, or successful user
behavior.
- [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: Codex Desktop
independently reviewed commit `cef961c6b` across all nine security
categories, including shell status handling, symlink scope, ownership
and mode enforcement, output privacy, workflow authorization, and the
historical-image limitation. It found no actionable security issue.
- [ ] 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: `no-docs-needed`
- Evidence: The change repairs internal managed-image MCP tool-discovery
filesystem metadata and adds CI-only regression coverage. It does not
change public commands, configuration, defaults, APIs, or operator
workflows; existing MCP tool-discovery documentation remains accurate.
- Agent: Codex Desktop
<!-- docs-review-head-sha: cef961c -->
<!-- docs-review-agents-blob-sha: c4923a3 -->

## 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, or tests
are marked not applicable above — 68 tests passed across the
managed-image workflow, MCP discovery image contract, and all three
final-image layout contracts; the 19-test workflow contract was rerun
after the final ordering assertion.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — not applicable to this scoped
image-permission repair. `npm run validate:pr` passed for the review
repair, including repository checks, source-shape budgets, Biome,
hadolint, secret scanning, and CLI typecheck; the final assertion also
passed normal commit and push hooks.
- [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)
- [ ] 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: Julie Yaunches <jyaunches@nvidia.com>


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

## Summary by CodeRabbit

- **Security**
- Managed images now enforce secure ownership and read-only permissions
for the tool-discovery runtime.
- Directories remain executable while files remain readable without
being writable, and symlinks are handled safely.

- **Bug Fixes**
- Improved consistency and reliability when building managed images,
including protection against permission drift.

- **Quality**
- Added automated validation for image security properties, runtime
execution, and discovery response format.

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

---------

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
@jyaunches

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #8754, which merged the complete fix for v0.0.106.

@jyaunches jyaunches closed this Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: packaging Packages, images, registries, installers, or distribution bug-fix PR fixes a bug or regression integration: dcode LangChain Deep Code integration behavior integration: hermes Hermes integration behavior integration: openclaw OpenClaw integration behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deep Code runtime contract blocks exact Brev Launchable image publication

4 participants