Skip to content

fix(security): surface immutable symlink hardening status#1499

Merged
cv merged 2 commits intoNVIDIA:mainfrom
13ernkastel:codex/pr-1137-hardening-observability-mainline
Apr 6, 2026
Merged

fix(security): surface immutable symlink hardening status#1499
cv merged 2 commits intoNVIDIA:mainfrom
13ernkastel:codex/pr-1137-hardening-observability-mainline

Conversation

@13ernkastel
Copy link
Copy Markdown
Contributor

@13ernkastel 13ernkastel commented Apr 5, 2026

Summary

This follow-up builds on #1137 and improves the observability around immutable symlink hardening without changing the underlying defense-in-depth approach.

What Changed

  • factors .openclaw symlink validation into a reusable helper so both startup paths use the same validation logic
  • adds explicit security logging when immutable hardening succeeds, is partial, or is skipped because chattr is unavailable
  • extends the gateway-isolation E2E to fail if chattr is missing from the image, so the mitigation cannot silently disappear

Why

The original immutable-hardening fix is directionally strong, but the chattr path is intentionally best-effort and currently silent. That makes the mitigation harder to trust and harder to debug because:

  • a missing chattr binary looks the same as successful hardening
  • partial chattr +i failures are suppressed with no visibility
  • the image can regress and stop shipping chattr without CI catching it

These changes make the mitigation easier to audit while staying compatible with the current layered hardening model.

Validation

  • bash -n scripts/nemoclaw-start.sh
  • bash -n test/e2e-gateway-isolation.sh
  • git diff --check
  • not run: test/e2e-gateway-isolation.sh (docker is not installed in this environment)

Relationship To #1137

This is a repost of the follow-up originally opened as latenighthackathon/NemoClaw#1, now targeted at NVIDIA/NemoClaw as requested.

Note

This replaces #1467, which GitHub auto-closed because the repository's contributor open-PR limit was hit at the time.

Signed-off-by: 13ernkastel LennonCMJ@live.com

Summary by CodeRabbit

  • Chores

    • Enhanced startup process validation to ensure system integrity and correct configuration
    • Improved security hardening mechanisms with comprehensive logging and graceful fallback handling when system features are unavailable
  • Tests

    • Updated end-to-end integration tests to verify system hardening capabilities and feature availability

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ebe299c6-fd83-4e71-b381-167f1efd5fdb

📥 Commits

Reviewing files that changed from the base of the PR and between 2842c2f and d1c4baa.

📒 Files selected for processing (2)
  • scripts/nemoclaw-start.sh
  • test/e2e-gateway-isolation.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/e2e-gateway-isolation.sh
  • scripts/nemoclaw-start.sh

📝 Walkthrough

Walkthrough

Added symlink validation and conditional hardening to the startup script (scripts/nemoclaw-start.sh) and adjusted e2e test ordering to check for chattr availability before running the sandbox-vs-gateway kill/isolation test (test/e2e-gateway-isolation.sh).

Changes

Cohort / File(s) Summary
Symlink Validation & Hardening
scripts/nemoclaw-start.sh
Introduced validate_openclaw_symlinks() to verify resolved symlink targets under /sandbox/.openclaw/* and fail startup if mismatched; added harden_openclaw_symlinks() to attempt chattr +i hardening with detailed logging and tolerant failure behavior; replaced inline validation/hardening with these function calls in both root and non-root startup paths.
Test Reordering & Precondition
test/e2e-gateway-isolation.sh
Replaced previous Test 11 with a new precondition that checks for chattr availability as root; moved the sandbox-vs-gateway kill/isolation check to Test 12; renumbered the capabilities/bounding-set validation test label to Test 13 (logic unchanged).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Init as Startup Script
  participant Validator as validate_openclaw_symlinks()
  participant FS as /sandbox/.openclaw (filesystem)
  participant Hardener as harden_openclaw_symlinks()
  participant Chattr as `chattr` binary

  Init->>Validator: invoke (non-root & root paths)
  Validator->>FS: read symlinks (readlink -f)
  FS-->>Validator: resolved targets
  Validator-->>Init: success/fail (return 0/1)

  alt hardening available
    Init->>Hardener: invoke (root path)
    Hardener->>Chattr: check availability (command -v)
    Chattr-->>Hardener: exists
    Hardener->>FS: apply chattr +i to files/dirs
    FS-->>Hardener: success/failure per path
    Hardener-->>Init: log counts, return 0 (tolerant)
  else chattr missing
    Hardener->>Chattr: not found
    Hardener-->>Init: log and return 0 (skip hardening)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through links both old and new,

I checked each path to see what's true,
I asked the chattr to stand and stay,
If it won't, I still let startup play,
A little hop for safer day.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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 accurately describes the main change: refactoring symlink validation into reusable functions and adding explicit logging for immutable symlink hardening status to improve observability.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@13ernkastel
Copy link
Copy Markdown
Contributor Author

@cv this is open upstream now: #1499.

#1467 would not reopen cleanly after the auto-close, so I recreated the PR from the same branch once a contributor PR slot was free.

@13ernkastel 13ernkastel force-pushed the codex/pr-1137-hardening-observability-mainline branch from 2842c2f to d1c4baa Compare April 5, 2026 23:39
@13ernkastel
Copy link
Copy Markdown
Contributor Author

Maintainers: this PR has been rebased onto current main and is now mergeable, but the refreshed GitHub Actions runs are blocked in action_required and do not appear to have started jobs yet. It looks like this fork PR may need workflow approval before pr, commit-lint, and dco-check can run. Could someone please approve the runs so the checks can execute?

@cv cv merged commit 2c40b46 into NVIDIA:main Apr 6, 2026
8 checks passed
tranzmatt pushed a commit to tranzmatt/NemoClaw that referenced this pull request Apr 6, 2026
## Summary

This follow-up builds on NVIDIA#1137 and improves the observability around
immutable symlink hardening without changing the underlying
defense-in-depth approach.

## What Changed

- factors `.openclaw` symlink validation into a reusable helper so both
startup paths use the same validation logic
- adds explicit security logging when immutable hardening succeeds, is
partial, or is skipped because `chattr` is unavailable
- extends the gateway-isolation E2E to fail if `chattr` is missing from
the image, so the mitigation cannot silently disappear

## Why

The original immutable-hardening fix is directionally strong, but the
`chattr` path is intentionally best-effort and currently silent. That
makes the mitigation harder to trust and harder to debug because:

- a missing `chattr` binary looks the same as successful hardening
- partial `chattr +i` failures are suppressed with no visibility
- the image can regress and stop shipping `chattr` without CI catching
it

These changes make the mitigation easier to audit while staying
compatible with the current layered hardening model.

## Validation

- `bash -n scripts/nemoclaw-start.sh`
- `bash -n test/e2e-gateway-isolation.sh`
- `git diff --check`
- not run: `test/e2e-gateway-isolation.sh` (`docker` is not installed in
this environment)

## Relationship To NVIDIA#1137

This is a repost of the follow-up originally opened as
`latenighthackathon#1`, now targeted at `NVIDIA/NemoClaw` as
requested.

## Note

This replaces `NVIDIA#1467`, which GitHub auto-closed because the repository's
contributor open-PR limit was hit at the time.

Signed-off-by: 13ernkastel <LennonCMJ@live.com>


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

## Summary by CodeRabbit

* **Chores**
* Enhanced startup process validation to ensure system integrity and
correct configuration
* Improved security hardening mechanisms with comprehensive logging and
graceful fallback handling when system features are unavailable

* **Tests**
* Updated end-to-end integration tests to verify system hardening
capabilities and feature availability

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

Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants