Skip to content

fix(sandbox): chmod 444 rc files after entrypoint writes#2125

Merged
ericksoa merged 3 commits into
mainfrom
fix/landlock-rc-file-permissions
Apr 21, 2026
Merged

fix(sandbox): chmod 444 rc files after entrypoint writes#2125
ericksoa merged 3 commits into
mainfrom
fix/landlock-rc-file-permissions

Conversation

@ericksoa

@ericksoa ericksoa commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • export_gateway_token and install_configure_guard write to .bashrc/.profile but never lock them read-only afterward
  • The Landlock policy declares /sandbox as read_only, but the files retain default umask permissions (644), failing the 04-landlock-readonly E2E assertion
  • Adds chmod 444 after both write loops

Test plan

  • Nightly E2E cloud-experimental-e2e job passes (04-landlock-readonly)

Fixes regression from #2081.

Summary by CodeRabbit

  • Chores
    • Shell configuration files are now set to read-only at the end of setup steps (after gateway token injection and install/configure guard), preventing accidental edits and ensuring configuration stability across completion of the setup process.

…ig guard

export_gateway_token and install_configure_guard write to .bashrc and
.profile but never lock them read-only afterward.  The Landlock
filesystem policy declares /sandbox as read_only, but the files end up
with default umask permissions (644), causing the 04-landlock-readonly
E2E assertion to fail.

Add chmod 444 after both write loops so the files are immutable once
the entrypoint finishes.
@coderabbitai

coderabbitai Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c59ef15-5d47-47bb-b697-e0a6346b76ec

📥 Commits

Reviewing files that changed from the base of the PR and between 8dcf80e and 2040758.

📒 Files selected for processing (1)
  • scripts/nemoclaw-start.sh
✅ Files skipped from review due to trivial changes (1)
  • scripts/nemoclaw-start.sh

📝 Walkthrough

Walkthrough

Added final permission locking (chmod 444) on ${_SANDBOX_HOME}/.bashrc and ${_SANDBOX_HOME}/.profile at the end of both export_gateway_token and install_configure_guard so rc-file mutations are made read-only after snippets are applied.

Changes

Cohort / File(s) Summary
Permission Locking
scripts/nemoclaw-start.sh
Appended chmod 444 to make ${_SANDBOX_HOME}/.bashrc and ${_SANDBOX_HOME}/.profile read-only after injecting the gateway-token snippet (export_gateway_token) and after installing the configure guard (install_configure_guard).

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 I hopped in code and found the spot,

I set the bits and closed the lot,
.bashrc snug and .profile tight,
Locked for Landlock through the night,
A quiet burrow, everything right.

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding chmod 444 permissions to rc files after entrypoint writes to address Landlock filesystem policy alignment.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/landlock-rc-file-permissions

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

@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 the current code and only fix it if needed.

Inline comments:
In `@scripts/nemoclaw-start.sh`:
- Around line 464-467: The rc files (.bashrc and .profile) are being set to mode
444 too early inside export_gateway_token, which breaks non-root startup because
install_configure_guard later mutates those same files; move the chmod 444
locking so it happens only after the final rc mutation step (i.e., after
install_configure_guard completes) and remove or relocate the early chmod loop
(the for rc_file ... chmod 444 block) — also apply the same relocation to the
other identical occurrence later in the script so both early-locking loops are
moved to run after the final configuration writes.
🪄 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: Pro Plus

Run ID: 53ced5b2-9389-406b-93d7-e4282bf45c38

📥 Commits

Reviewing files that changed from the base of the PR and between e15f4dc and 8dcf80e.

📒 Files selected for processing (1)
  • scripts/nemoclaw-start.sh

Comment thread scripts/nemoclaw-start.sh Outdated
export_gateway_token runs before install_configure_guard, so locking
the rc files in the first function breaks the second function's writes
under set -e.  Keep the lock only after the final rc mutation step.

Addresses CodeRabbit review feedback.
@ericksoa ericksoa merged commit af0a339 into main Apr 21, 2026
14 of 15 checks passed
cv added a commit that referenced this pull request Apr 22, 2026
#2181) (#2208)

## Summary

Fixes a security bug where `/tmp/nemoclaw-proxy-env.sh` was writable by
the sandbox user (`chmod 644`), allowing a sandbox-resident attacker to
append arbitrary shell code that executes on every `nemoclaw <name>
connect` via `.bashrc`/`.profile` sourcing. Introduces shared helpers to
prevent this class of bug going forward.

## Related Issue

Fixes #2181

## Changes

- **`scripts/nemoclaw-start.sh`**: Add `emit_sandbox_sourced_file()`
helper — centralizes `rm -f` (anti-symlink), content write, `chown
root:root`, and `chmod 444` into one reusable function for any file that
the sandbox user sources but must not modify
- **`scripts/nemoclaw-start.sh`**: Add `validate_tmp_permissions()` gate
— defence-in-depth check called before launching services in both root
and non-root paths, verifying proxy-env.sh is 444 and log files are 600
- **`scripts/nemoclaw-start.sh`**: Refactor proxy-env.sh generation to
pipe through `emit_sandbox_sourced_file` instead of ad-hoc `chmod 644`
- **`scripts/nemoclaw-start.sh`**: Add trust boundary map comment
documenting every `/tmp` file, its intended owner, mode, and whether it
is sourced by `.bashrc`/`.profile`
- **`test/service-env.test.ts`**: Add `extractEmitHelper()`, update all
sed anchors from `chmod 644` to `emit_sandbox_sourced_file`, add
permission assertion (`expect 444`)
- **`test/e2e-gateway-isolation.sh`**: Add Test 25 (sandbox user cannot
append to proxy-env.sh) and Test 26 (file permissions are 444
root-owned)
- **`Dockerfile.base`**: Update comment to reflect mode 444

### Architectural context

This is the same class of bug as #2125 (`.bashrc`/`.profile` missing
`chmod 444`) and #799 (audit logs writable). The shared helpers
introduced here (`emit_sandbox_sourced_file`,
`validate_tmp_permissions`) are designed to prevent the whack-a-mole
pattern where each new `/tmp` file independently invents its own
permission management. They map directly to s6-overlay `fix-attrs.d/`
entries for a future entrypoint decomposition.

A tracking issue for migrating the remaining ad-hoc `chmod`/`chown`
callsites and evaluating s6-overlay adoption will follow.

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

## Verification
- [x] `npx prek run --all-files` passes (shellcheck, hadolint, shfmt,
gitleaks, commitlint all pass; tsc/vitest skip due to incomplete npm
install in worktree)
- [ ] `npm test` passes (vitest not installed in worktree — CI will run)
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [ ] Docs updated for user-facing behavior changes
- [ ] `make 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)

## AI Disclosure
- [x] AI-assisted — tool: Claude Code (pi agent)

---
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>

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

* **Security Improvements**
* Enforce and document that sandbox-sourced temp config files are
created root-owned and read-only; added pre-start validation to fail
startup if temp/config or log permissions are incorrect.
* **Tests**
* Expanded end-to-end and unit tests to assert read-only enforcement,
prevent symlink-following attacks, and updated test ordering and labels.
<!-- 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>
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants