Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions docs/reference/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -639,9 +639,11 @@ Four tiers are available:
| Restricted | No tier defaults. Web search or other integrations selected earlier can still add their required presets; deselect them during policy review for baseline-only access. |
| Balanced (default) | Full dev tooling and a selected, supported web search provider. Package installs, model downloads, and inference. No messaging platform access by default. |
| Open | Broad access across third-party services including supported messaging and productivity presets. Agent-specific unsupported presets are filtered out. |
| Personal | Lets every sandbox binary open TCP connections to public and private address ranges on destination ports 80 and 443. Unspecified, loopback, and link-local ranges remain blocked. Also selects every maintained preset supported by the active agent. Intended only for trusted personal-use workloads. |
| Personal | Requires one broad web authority that lets every sandbox binary open TCP connections to public and private address ranges on destination ports 80 and 443. It replaces overlapping exact web endpoints while preserving non-web policy. Unspecified, loopback, and link-local ranges remain blocked. Intended only for trusted personal-use workloads. |

After selecting a tier, the wizard shows a combined preset and access-mode screen where you can include or exclude individual presets and toggle each between read and read-write access.
When Personal is selected or carried forward, `personal-open-internet` is mandatory for every agent and every onboarding entry point, including Portable.
The picker and policy modes control only additional presets; they cannot deselect, skip, or replace Personal's required web authority.
For details on tiers and the presets each includes, refer to [Network Policies](network-policies#policy-tiers).
When you finish the policy step, NemoClaw records the finalized built-in preset selection for that sandbox.
When onboarding creates or recreates a sandbox with presets, NemoClaw prints the exact finalized create-time policy scope before registering providers or creating the sandbox.
Expand All @@ -660,16 +662,18 @@ Interactive onboarding ignores an invalid environment value and shows the normal
`NEMOCLAW_POLICY_MODE` controls how non-interactive onboarding reconciles the tier-derived suggestions against the sandbox's currently-applied presets.
The default is `suggested`, which is *additive*.
Onboarding applies tier defaults and preserves any presets you previously added with [`$$nemoclaw <name> policy add`](#$$nemoclaw-name-policy-add) across re-onboards.
Use `custom` with `NEMOCLAW_POLICY_PRESETS` when you want the explicit list to be authoritative.
Onboarding removes any preset that is not in the list.
`skip` leaves the applied set untouched and does not apply tier defaults.
Use `custom` with `NEMOCLAW_POLICY_PRESETS` when you want the explicit list to be authoritative for optional presets.
Onboarding removes any optional preset that is not in the list.
`skip` does not add optional tier defaults and retains eligible optional presets already applied.
For Personal, all modes still apply or retain the mandatory `personal-open-internet` preset.
NemoClaw filters tier suggestions and resume selections by active agent support and the selected web search provider.
During automatic suggestion and resume reconciliation, it removes stale web-search selections when they conflict with the active agent or selected provider.
The Personal tier is the exception: it preserves every applicable maintained web-search preset even when onboarding did not configure that provider.
The Personal tier instead uses `personal-open-internet` for web transport and does not select Brave Search or Tavily Search merely to enable ordinary web fetches.
This makes keyless fetches available to any sandbox binary, but it does not add a provider-free `web_search` implementation.
<AgentOnly variant="hermes">
For Hermes, this includes replacing stale `nous-web` when Tavily is selected.
</AgentOnly>
An explicit `custom` preset list or interactive manual selection remains operator-controlled.
An explicit `custom` preset list or interactive manual selection remains operator-controlled for additional presets.

<AgentOnly variant="hermes">

Expand All @@ -681,8 +685,8 @@ When Tavily Search is selected, it replaces `nous-web` as the Hermes web search
| Value | Behaviour |
|-------|-----------|
| `suggested` (default) | Apply tier defaults and preserve any extra presets already applied. Aliases: `default`, `auto`. |
| `custom` | Apply exactly `NEMOCLAW_POLICY_PRESETS`. Previously-applied presets not in the list are removed. Alias: `list`. |
| `skip` | Skip the policy step entirely. Aliases: `none`, `no`. |
| `custom` | Apply exactly the optional presets in `NEMOCLAW_POLICY_PRESETS`. Previously-applied optional presets not in the list are removed. Personal still requires `personal-open-internet`. Alias: `list`. |
| `skip` | Do not add optional tier defaults; retain eligible optional presets already applied. Personal still applies or retains `personal-open-internet`. Aliases: `none`, `no`. |

<AgentOnly variant="openclaw">

Expand Down
29 changes: 17 additions & 12 deletions docs/reference/network-policies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ This is the supported registry-backed way to replay a live exact-key removal dur
| Restricted | No tier defaults | Starts from the baseline policy. Web search or messaging integrations selected earlier can still suggest their required presets; deselect them during policy review for baseline-only access. Restricted suppresses other agent-required additions; reapply them later with `policy add` only after reviewing the additional egress. |
| Balanced (default) | `npm`, `pypi`, `huggingface`, `brew`, selected `brave` or `tavily` web search preset | Full dev tooling and web search when you select a provider the active agent supports. No messaging platform access. Apply the `weather` preset explicitly if your agent needs read-only weather lookups. |
| Open | `npm`, `pypi`, `huggingface`, `brew`, selected `brave` or `tavily` web search preset, `weather`, `public-reference`, `slack`, `discord`, `telegram`, `wechat` (experimental), `whatsapp` (experimental), `jira`, `outlook` | Broad access across third-party services including messaging, productivity, weather, and public-reference APIs. |
| Personal | `personal-open-internet` and every maintained preset supported by the active agent | Lets every sandbox binary open TCP connections to public and private address ranges on destination ports `80` and `443`. Unspecified, loopback, and link-local ranges remain blocked. Also selects every maintained preset applicable to the active agent. |
| Personal | `personal-open-internet` (mandatory) | Lets every sandbox binary open TCP connections to public and private address ranges on destination ports `80` and `443`. The broad route replaces overlapping web endpoints while preserving non-web policy. Unspecified, loopback, and link-local ranges remain blocked. |

When Personal is selected or carried forward, the `personal-open-internet` preset is mandatory for every agent and every onboarding entry point.
Interactive choices, `NEMOCLAW_POLICY_MODE=custom`, and `NEMOCLAW_POLICY_MODE=skip` control only additional presets; they cannot deselect, skip, or replace Personal's required web authority.

<Warning title="Personal Tier Network Access">
The Personal tier applies the `personal-open-internet` policy preset with a hostless L4 endpoint on destination ports `80` and `443`.
Expand All @@ -155,12 +158,13 @@ The sandbox's filesystem, process, gateway authentication, and managed credentia
Use this tier only for trusted personal workloads with trusted prompts and data.
</Warning>

For a fresh onboarding run, the experimental portable profile selects `weather`, `public-reference`, and `github` when `NEMOCLAW_POLICY_PRESETS` is unset, blank, or contains only whitespace.
This default does not select `personal-open-internet`.
If `NEMOCLAW_POLICY_PRESETS` contains a non-blank list, portable onboarding treats that explicit list as authoritative instead.
`$$nemoclaw onboard --resume` does not inject the fresh-onboarding default.
Every fresh onboarding run through the experimental Portable profile selects the Personal tier.
When `NEMOCLAW_POLICY_PRESETS` is unset, blank, or contains only whitespace, Portable uses `suggested` mode with no optional preset override.
If `NEMOCLAW_POLICY_PRESETS` contains a non-blank list, Portable treats that list as authoritative for additional presets while still applying mandatory `personal-open-internet`.
`$$nemoclaw onboard --resume` does not override a recorded non-Personal tier; a resumed Personal tier retains or repairs its mandatory preset.

After selecting a tier, a combined preset and access-mode screen lets you include or exclude individual presets and toggle each between read (GET only) and read-write (GET + POST/PUT/PATCH) access.
After selecting a tier, a combined preset and access-mode screen lets you include or exclude optional presets and toggle each between read (GET only) and read-write (GET + POST/PUT/PATCH) access.
On Personal, NemoClaw restores `personal-open-internet` if it is deselected in the screen.
Tier-default presets are pre-selected; additional presets can be added from the built-in preset list available to the sandbox's active agent.
NemoClaw filters tier defaults and built-in preset choices by the active agent's supported integrations.
The `personal-open-internet` preset uses L4 passthrough, so its read-write label does not add HTTP method or path inspection.
Expand All @@ -182,16 +186,17 @@ These modes skip policy preset additions, but they do not preserve a disabled ch
`$$nemoclaw onboard --resume` reconciles the policy selection instead of skipping it when the effective messaging selection omits a channel whose preset remains applied.
NemoClaw keeps the preset for an in-sandbox QR-paired channel such as WhatsApp because you pair that channel inside the sandbox rather than through host environment values.
</AgentOnly>
The Personal tier instead keeps every applicable maintained web-search preset selected by default.
Explicit custom preset lists and manual interactive selections remain operator-controlled.
The Personal tier does not select a Brave Search or Tavily Search preset by default.
Its broad route supports ordinary keyless web fetches, while `web_search` still requires a separately configured provider.
Explicit custom preset lists and manual interactive selections remain operator-controlled for additional presets.
<AgentOnly variant="hermes">
Hermes managed-tool gateway selections can add Hermes-specific presets, such as Nous-hosted web, image, audio, browser, or code tools, without applying unsupported OpenClaw-only presets.
When Hermes uses Tavily, NemoClaw removes `nous-web` from the effective managed-tool selection while preserving other selected Nous tool presets.
</AgentOnly>
<AgentOnly variant="openclaw">
OpenClaw onboarding also adds the `openclaw-pricing` preset on top of tier defaults so session-cost records can populate from LiteLLM and OpenRouter without manual configuration.
On the Balanced and Open tiers, enabling OpenClaw OTEL diagnostics with a local endpoint adds the `openclaw-diagnostics-otel-local` preset.
The Personal tier selects that preset by default, while Restricted suppresses it during reconciliation.
OpenClaw onboarding also adds the `openclaw-pricing` preset on top of Balanced and Open tier defaults so session-cost records can populate from LiteLLM and OpenRouter without manual configuration.
On the Balanced, Open, and Personal tiers, enabling OpenClaw OTEL diagnostics with a local endpoint adds the `openclaw-diagnostics-otel-local` preset.
Personal suppresses the overlapping pricing route because `personal-open-internet` already owns ports `80` and `443`, while Restricted suppresses it to retain the restricted posture.
</AgentOnly>
<AgentOnly variant="deepagents">
When LangChain Deep Agents Code is onboarded with `--observability`, NemoClaw adds the `observability-otlp-local` preset on Balanced, Open, and Personal tiers.
Expand All @@ -202,7 +207,7 @@ The applied set therefore reflects the chosen tier *plus* any agent-required pre
The `policy list` provenance tags are inferred from the current tier YAML and the active agent at display time and are not persisted per preset.
A preset whose name matches an entry in the sandbox's current tier definition is labelled `[from <tier> tier]` even when an operator added it manually with `policy add` after onboarding; agent-specific preset names are only labelled `[from <agent> agent]` when the active agent matches.
Claude Code direct egress is not included in the Restricted, Balanced, or Open tiers.
The Personal tier selects the `claude-code` preset by default; on other tiers, apply it explicitly if you install and run the Claude Code CLI inside the sandbox with its own credentials.
Personal's broad route permits its port `443` transport but does not install or configure Claude Code; on other tiers, apply the `claude-code` preset explicitly if you install and run the CLI inside the sandbox with its own credentials.
Normal NemoClaw Anthropic inference still routes through the OpenShell gateway.

Tier definitions are stored in `nemoclaw-blueprint/policies/tiers.yaml`.
Expand Down
4 changes: 2 additions & 2 deletions docs/security/best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ The preset separately grants that registry transport to its listed npm, Yarn, an
</AgentOnly>

<Warning title="Personal Tier">
The Personal tier selects `personal-open-internet` and every maintained preset supported by the active agent.
The Personal tier selects `personal-open-internet` as its web authority and preserves non-web policy.
The open-internet preset allows every sandbox binary to reach public and private address ranges on destination ports `80` and `443` through L4 passthrough.
Traffic on those ports is not limited to HTTP or HTTPS.
OpenShell does not inspect the hostname, application protocol, HTTP method, path, or body for those connections.
Expand Down Expand Up @@ -372,7 +372,7 @@ Use only for a trusted single-user sandbox that needs arbitrary TCP egress on de
- Select the Personal tier during onboarding.
- Treat every prompt, downloaded package, webpage, and workspace file as able to trigger external TCP traffic on destination ports `80` and `443`.
- Do not place raw credentials or sensitive data in the sandbox unless the agent must use them.
- Return to Balanced or Restricted and recreate the sandbox when this broad egress is no longer required.
- Create a new Balanced or Restricted sandbox when this broad egress is no longer required. NemoClaw refuses to remove Personal in place because its normalized policy has already replaced overlapping web entries.

### Integration Testing

Expand Down
38 changes: 4 additions & 34 deletions nemoclaw-blueprint/policies/tiers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#
# Tier definitions for the NemoClaw policy selector.
#
# Each tier maps to a named posture. The base sandbox policy
# (openclaw-sandbox.yaml) is always applied regardless of tier.
# Tiers add presets on top of that baseline.
# Each tier maps to a named posture. The base sandbox policy is always the
# starting point. Personal then replaces overlapping port 80/443 endpoints
# with its single broad L4 authority while preserving non-web policy.
#
# access values:
# read — GET only (or equivalent read-only rules for that service)
Expand Down Expand Up @@ -52,36 +52,6 @@ tiers:

- name: personal
label: Personal
description: Trusted personal-use posture. Lets every sandbox binary open TCP connections to public and private address ranges on destination ports 80 and 443. Unspecified, loopback, and link-local ranges remain blocked. Also enables every maintained preset that applies to the selected agent. Do not use with untrusted prompts or data.
description: Trusted personal-use posture. Lets every sandbox binary open TCP connections to public and private address ranges on destination ports 80 and 443. Unspecified, loopback, and link-local ranges remain blocked. This broad route replaces overlapping web endpoints while active. Do not use with untrusted prompts or data.
presets:
- { name: personal-open-internet, access: read-write }
- { name: npm, access: read-write }
- { name: pypi, access: read-write }
- { name: huggingface, access: read-write }
- { name: brew, access: read-write }
- { name: brave, access: read-write }
- { name: tavily, access: read-write }
- { name: weather, access: read-write }
- { name: public-reference, access: read-write }
- { name: github, access: read-write }
- { name: gmail, access: read-write }
- { name: jira, access: read-write }
- { name: outlook, access: read-write }
- { name: claude-code, access: read-write }
- { name: local-inference, access: read-write }
- { name: local-memory, access: read-write }
- { name: openclaw-pricing, access: read-write }
- { name: openclaw-diagnostics-otel-local, access: read-write }
- { name: observability-otlp-local, access: read-write }
- { name: nous-web, access: read-write }
- { name: nous-image, access: read-write }
- { name: nous-audio, access: read-write }
- { name: nous-browser, access: read-write }
- { name: nous-code, access: read-write }
- { name: slack, access: read-write }
- { name: discord, access: read-write }
- { name: telegram, access: read-write }
- { name: googlechat, access: read-write }
- { name: wechat, access: read-write }
- { name: whatsapp, access: read-write }
- { name: teams, access: read-write }
13 changes: 13 additions & 0 deletions src/lib/actions/sandbox/rebuild-backup-phase.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,19 @@ describe("rebuild web-search policy normalization", () => {
),
).toEqual(["npm", "future-agent-required"]);
});

it.each(["openclaw", "hermes", "langchain-deepagents-code", "pi"] as const)(
"repairs a Personal rebuild target missing its tier-defining preset: %s",
(agent) => {
expect(
normalizeRebuildTargetPolicyPresets(
["npm"],
{ name: "alpha", agent, policyTier: " Personal " },
null,
),
).toEqual(["personal-open-internet", "npm"]);
},
);
});

describe("custom OpenClaw plugin provenance rebuild guard (#6108)", () => {
Expand Down
14 changes: 10 additions & 4 deletions src/lib/actions/sandbox/rebuild-backup-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
} from "../../onboard/observability-policy-presets";
import { resolveRecreatePolicyPresets } from "../../onboard/policy-preset-persistence";
import { isStaleBuiltinWebSearchPolicyPreset } from "../../onboard/policy-selection";
import { filterSuppressedAgentRequiredPresets } from "../../onboard/policy-tier-suppression";
import {
ensureRequiredTierPolicyPresets,
filterSuppressedAgentRequiredPresets,
} from "../../onboard/policy-tier-suppression";
import { parsePresetPolicyKeys } from "../../policy";
import { hasCompleteOpenClawImagePluginProvenance } from "../../state/openclaw-plugin-restore";
import { hasAuthoritativeOpenClawImagePluginProvenance } from "../../state/sandbox";
Expand Down Expand Up @@ -138,9 +141,12 @@ export function normalizeRebuildTargetPolicyPresets(
sandboxEntry: RebuildSandboxEntry,
webSearchConfig: WebSearchConfig | null,
): string[] {
return normalizeRebuildObservabilityPolicyPresets(
normalizeRebuildWebSearchPolicyPresets([...new Set(presets)], sandboxEntry, webSearchConfig),
sandboxEntry,
return ensureRequiredTierPolicyPresets(
sandboxEntry.policyTier,
normalizeRebuildObservabilityPolicyPresets(
normalizeRebuildWebSearchPolicyPresets([...new Set(presets)], sandboxEntry, webSearchConfig),
sandboxEntry,
),
);
}

Expand Down
Loading
Loading