> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemoclaw/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemoclaw/_mcp/server.

# Understand Process Controls

> Review NemoClaw process capabilities, resource limits, runtime identity, and image hardening.

NemoClaw limits the capabilities, user privileges, and resource quotas available to processes inside the sandbox.

OpenShell enforces additional process-level controls not covered here, including seccomp BPF socket domain filters and a specific enforcement application order (namespace entry, privilege drop, Landlock, seccomp).
Refer to the [Process Controls](https://docs.nvidia.com/openshell/latest/security/best-practices.html#process-controls) section of the OpenShell Security Best Practices.

## Capability Drops

The entrypoint drops dangerous Linux capabilities from the bounding set at startup using `capsh`.
This limits what capabilities any child process (gateway, sandbox, agent) can ever acquire.

The managed images install `setpriv` from `util-linux` and require it when the entrypoint switches from root to the `sandbox` and `gateway` users.
When `CAP_SETPCAP` is available, the same `setpriv` operation removes the remaining privilege-separation capabilities from the child process at the same time as the user change.

The initial entrypoint drop removes `cap_sys_admin`, `cap_sys_ptrace`, `cap_net_raw`, `cap_dac_override`, `cap_sys_chroot`, `cap_fsetid`, `cap_setfcap`, `cap_mknod`, `cap_audit_write`, and `cap_net_bind_service`.
When the additional `setpriv` bounding-set drop runs, the child process also loses `cap_setuid`, `cap_setgid`, `cap_fowner`, `cap_chown`, and `cap_kill`.

The extra bounding-set capability drop is best effort.
If `capsh` is not available or `CAP_SETPCAP` is not in the bounding set, the entrypoint logs a warning and retains the runtime-provided bounding set.
The entrypoint still uses `setpriv` to change the user, group, and supplementary groups without the extra bounding-set drop.

When a root entrypoint must change identity, it fails closed if `setpriv` is unavailable instead of starting an agent service as root.

To make the drop fail-closed instead of best-effort, set `NEMOCLAW_REQUIRE_CAP_DROP=1` in the entrypoint environment.
The agent then refuses to start unless it verifies that the agent process tree's bounding set is free of dangerous capabilities.

It does not boot on a host whose bounding set still holds them, typically one that cannot perform the drop because `CAP_SETPCAP` or `capsh` is missing and the container runtime did not provide a clean bounding set.

This is opt-in because such hosts are common, including many cloud VMs, Docker Desktop, and WSL.
Leaving it unset preserves the best-effort default.

The check covers the agent process tree only.
The container runtime spawns a `nemoclaw connect` shell outside that tree, so the check does not affect it (tracked in [NVIDIA/OpenShell#1452](https://github.com/NVIDIA/OpenShell/issues/1452)).

For additional protection, pass `--cap-drop=ALL` with `docker run` or Compose.
Refer to [Review Sandbox Hardening](../../manage-sandboxes/configure-sandboxes/review-sandbox-hardening).

| Aspect              | Detail                                                                                                                                                                                                                                                                                                                          |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | The entrypoint drops dangerous capabilities at startup using `capsh`, then requires `setpriv` for user step-down. When `CAP_SETPCAP` is unavailable, the user step-down continues without the extra privilege-separation bounding-set drop and logs a warning.                                                                  |
| What you can change | When launching with `docker run` directly, pass `--cap-drop=ALL --cap-add=NET_BIND_SERVICE` for stricter enforcement. In the standard NemoClaw onboarding flow, the entrypoint handles capability dropping automatically.                                                                                                       |
| Risk if relaxed     | `CAP_SYS_ADMIN` and `CAP_SYS_PTRACE` expand kernel and process attack surface. `CAP_NET_RAW` allows raw socket access for network sniffing. `CAP_DAC_OVERRIDE` bypasses filesystem permission checks. If `capsh` cannot run or `CAP_SETPCAP` is unavailable, the container retains more of the runtime-provided capability set. |
| Recommendation      | Run on an image that includes `capsh` and `setpriv` (NemoClaw-managed images include them). For defense-in-depth, also pass `--cap-drop=ALL` at the container runtime level.                                                                                                                                                    |

## Gateway Process Isolation

Gateway and agent UID isolation depends on the container process topology.
The stock OpenClaw image defaults to the `sandbox` user for OpenShell compatibility.
An OpenShell-managed container has OpenShell as PID 1 and launches `nemoclaw-start` as a non-root process, so the supervisor, gateway, and agent all use the `sandbox` UID.
The managed-image publication workflow explicitly sets `NEMOCLAW_MANAGED_IMAGE_RUNTIME_USER=root` for its reviewed release images.
That build-time setting lets the entrypoint run the gateway as the separate `gateway` user and agent commands as the `sandbox` user.
A direct container runtime can override the image user to `root`.
That root-entrypoint topology runs the gateway as the separate `gateway` user and agent commands as the `sandbox` user.

| Aspect              | Detail                                                                                                                                                                                                                                                                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Default             | A stock Dockerfile build declares `USER sandbox`. The OpenShell-managed topology runs the gateway and agent under the same sandbox UID because `no-new-privileges` prevents the non-root entrypoint from changing users.                                                                                                                                     |
| What you can change | The managed-image publication workflow can set `NEMOCLAW_MANAGED_IMAGE_RUNTIME_USER=root` at build time. A direct container runtime can also override the image user to `root`. OpenClaw custom images must keep `USER sandbox` as the default.                                                                                                              |
| Risk if relaxed     | A same-UID agent can signal peer processes and can attempt to imitate the expected gateway process shape. The root managed controller prevents PID-reuse mistakes, but it cannot prove provenance against a malicious same-UID process or provide the direct root-entrypoint restart seal for mutable config.                                                |
| Recommendation      | Keep the stock OpenClaw image default user as `sandbox`. Use the managed-image publication setting or a direct root-entrypoint deployment when separate gateway and agent UIDs are required. Treat an OpenShell-managed controller that shares the `sandbox` UID as an authenticated lifecycle control, not as proof that the target process is trustworthy. |

## No New Privileges

The `no-new-privileges` flag prevents processes from gaining additional privileges through setuid binaries or capability inheritance.

| Aspect              | Detail                                                                                                                                                                                                                              |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | OpenShell sets `PR_SET_NO_NEW_PRIVS` using `prctl()` inside the sandbox process as part of the seccomp filter setup. The NemoClaw Compose example also shows the equivalent `security_opt: no-new-privileges:true` setting.         |
| What you can change | OpenShell's seccomp path enforces this inside the sandbox. It is not a user-facing knob.                                                                                                                                            |
| Risk if relaxed     | Without this flag, a compromised process could execute a setuid binary to escalate to root inside the container, then attempt container escape techniques.                                                                          |
| Recommendation      | No action needed. OpenShell enforces this automatically when the sandbox network policy is active. When an OpenShell-managed topology starts an entrypoint as a non-root user, this flag prevents that process from changing users. |

## Process Limit

A process limit caps the number of processes the sandbox user can spawn.
The entrypoint sets both soft and hard limits using `ulimit -u 512`.
This behavior is best effort.
If the container runtime restricts `ulimit` modification, the entrypoint logs a security warning and continues without the limit.

| Aspect              | Detail                                                                                                                                                                                                                                                                                                    |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | 512 processes (`ulimit -u 512`), best-effort.                                                                                                                                                                                                                                                             |
| What you can change | Increase or decrease the limit with `--ulimit nproc=N:N` in `docker run` or the `ulimits` section in Compose. The runtime-level ulimit takes precedence over the entrypoint's setting.                                                                                                                    |
| Risk if relaxed     | Removing or raising the limit makes the sandbox vulnerable to fork-bomb attacks, where a runaway process spawns children until the host runs out of resources. If the entrypoint cannot set the limit (logs `[SECURITY] Could not set soft/hard nproc limit`), the container runs without process limits. |
| Recommendation      | Keep the default at 512. If the agent runs workloads that spawn many child processes (such as parallel test runners), increase to 1024 and monitor host resource usage. If the entrypoint logs a warning about ulimit restrictions, set the limit through the container runtime instead.                  |

## Open File Descriptor Limit

An open file descriptor limit caps the number of files, sockets, and pipes the sandbox user can hold open at once.
The entrypoint sets both soft and hard limits using `ulimit -n 65536`.
This behavior is best effort.
If the container runtime restricts `ulimit` modification, the entrypoint logs a security warning and continues without the limit.

| Aspect              | Detail                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | 65536 open files, soft and hard (`ulimit -n 65536`), best-effort.                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| What you can change | Increase or decrease the limit with `--ulimit nofile=N:N` in `docker run` or the `ulimits` section in Compose. The runtime-level ulimit takes precedence over the entrypoint's setting.                                                                                                                                                                                                                                                                                                                                |
| Risk if relaxed     | Without this cap, the sandbox inherits the Docker daemon default (`nofile` \~1048576). A runaway or hostile process can then open file descriptors until it exhausts them, causing a denial of service that can starve the gateway, the agent, or the host of file handles. If the entrypoint cannot set the limit (logs `[SECURITY] Could not set soft/hard nofile limit`), the container runs without a file-descriptor cap. For more information, refer to [#4527](https://github.com/NVIDIA/NemoClaw/issues/4527). |
| Recommendation      | Keep the default at 65536. If the agent legitimately keeps many connections or files open, raise it deliberately and monitor host file-descriptor usage. If the entrypoint logs a warning about ulimit restrictions, set the limit through the container runtime instead.                                                                                                                                                                                                                                              |

## Non-Root User

The sandbox runs agent processes as a dedicated `sandbox` user and group.
The stock OpenClaw image starts the entrypoint as `sandbox` for OpenShell compatibility.
A build from the managed-image publication workflow can select `root` so the entrypoint starts the gateway and agent commands under separate UIDs.
A direct runtime can override the image user to `root`, which lets the entrypoint separate the `gateway` and `sandbox` UIDs before it runs agent commands.

| Aspect              | Detail                                                                                                                                                                                                                                                           |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | `run_as_user: sandbox`, `run_as_group: sandbox`. The stock OpenClaw image runs the entrypoint, gateway, and agent under the sandbox UID.                                                                                                                         |
| What you can change | Change the `process` section in the policy file to run as a different user. The managed-image publication workflow can select the root entrypoint at build time, and direct container runtimes can override the image user to `root`.                            |
| Risk if relaxed     | Running agent commands as `root` gives the agent access to modify any file in the container filesystem and increases the impact of container escape vulnerabilities.                                                                                             |
| Recommendation      | Keep agent commands under the `sandbox` user. Use `root` only for the entrypoint supervisor when the managed-image publication workflow or a direct container runtime selects it. Do not run agent commands as `root` or make `root` the OpenClaw image default. |

## PATH Hardening

The entrypoint locks the `PATH` environment variable to system directories, preventing the agent from injecting malicious binaries into command resolution.

| Aspect              | Detail                                                                                                                                                                                                                                               |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | The default sandbox entrypoint sets `PATH` to `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` at startup. Agent-specific images may add locked read-only runtime directories, such as `/opt/venv/bin` for LangChain Deep Agents Code. |
| What you can change | This is not a user-facing knob. The entrypoint enforces it.                                                                                                                                                                                          |
| Risk if relaxed     | Without PATH hardening, the agent could create an executable named `curl` or `git` in a writable directory earlier in the PATH, intercepting commands run by the entrypoint or other processes.                                                      |
| Recommendation      | No action needed. The entrypoint handles this automatically.                                                                                                                                                                                         |

## Build Toolchain Removal

The Dockerfile removes compilers and network probes from the runtime image.

| Aspect              | Detail                                                                                                                                                                                          |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | The Dockerfile purges `gcc`, `gcc-12`, `g++`, `g++-12`, `cpp`, `cpp-12`, `make`, `netcat-openbsd`, `netcat-traditional`, and `ncat` from the sandbox image.                                     |
| What you can change | Modify the Dockerfile to keep these tools, or install them at runtime if package manager access is allowed.                                                                                     |
| Risk if relaxed     | A compiler lets the agent build arbitrary native code, including kernel exploits or custom network tools. `netcat` enables arbitrary TCP connections that bypass HTTP-level policy enforcement. |
| Recommendation      | Keep build tools removed. If the agent needs to compile code, run the build in a separate, purpose-built container and copy artifacts into the sandbox.                                         |

## Image Digest Pinning

The managed blueprint references the sandbox image by an immutable `@sha256:` digest instead of a mutable tag such as `:latest`.
A registry-side tag change cannot silently select another managed sandbox image.

| Aspect              | Detail                                                                                                                                                        |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | NemoClaw selects the managed sandbox image by its exact digest.                                                                                               |
| What you can change | Use the onboarding `--from` path when you need to build from a reviewed custom image. Locally built custom images do not use the managed registry digest.     |
| Risk if relaxed     | Reverting to a mutable tag (`:latest`) allows a registry-side change to replace the sandbox image without any blueprint update, which is a supply-chain risk. |
| Recommendation      | Keep the managed digest-pinned image unless you need a reviewed custom image. Pin the custom image's base and dependencies before you build it.               |

## Auth Profile Permissions

The entrypoint and migration flows enforce `chmod 600` on all `auth-profiles.json` files under `~/.openclaw`.
This prevents other users on the host from reading stored credentials.

| Aspect              | Detail                                                                                                                                              |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default             | `600` permissions applied recursively at startup and after migration restores.                                                                      |
| What you can change | This is not a user-facing knob. The entrypoint enforces it.                                                                                         |
| Risk if relaxed     | Looser permissions let other users or processes on the host read provider API keys and tokens stored in auth profiles.                              |
| Recommendation      | No action needed. If you see a `permission denied` error when reading auth profiles, verify that you are running as the same user who created them. |