Skip to content

feat(policy): add opt-in allow-all network posture#5092

Open
larroy wants to merge 1 commit into
NVIDIA:mainfrom
larroy:feat/allow-all-network-posture
Open

feat(policy): add opt-in allow-all network posture#5092
larroy wants to merge 1 commit into
NVIDIA:mainfrom
larroy:feat/allow-all-network-posture

Conversation

@larroy

@larroy larroy commented Jun 10, 2026

Copy link
Copy Markdown

Summary

Adds an opt-in "allow-all" network posture that lets a sandbox reach any public host, alongside a scoped relaxation of the catch-all host guardrail. Deny-by-default remains the shipped default; allow-all activates only when explicitly selected.

Related Issue

Changes

  • New nemoclaw-blueprint/policies/openclaw-sandbox-allow-all.yaml: a single catch-all host: "*" base policy (ports 80/443) with prominent danger warnings. SSRF/private-network blocking still applies.
  • New allow-all tier in tiers.yaml that swaps the base policy instead of layering presets. Selectable via NEMOCLAW_POLICY_TIER=allow-all at create time or interactively post-create.
  • sandbox:shields:down --policy allow-all applies the catch-all to a running sandbox, reusing the permissive runtime FS-union path (resolveAllowAllPolicyPath, applyAllowAllPolicy).
  • Guardrail relaxed, not removed (scripts/validate-configs.ts): bare wildcard hosts (*/*:port) are permitted only in *-allow-all.yaml files; * stays rejected in all normal presets/base policies, and IP catch-alls (0.0.0.0/0, ::/0) stay rejected everywhere (preserves No Pre-Commit Validation Hook for Network Policy YAML Changes - IssueFinder - SN 21 #1445 intent).
  • Docs: tier reference + security best-practices warnings.

⚠️ Reviewer/QA note: bare host: "*" support in the OpenShell L7 proxy is not yet verified on a live sandbox. The policy file documents an enforcement: audit fallback if the proxy rejects *. Please confirm on a real sandbox before merge.

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)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • 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: Pedro Larroy pedro.larroy.lists@gmail.com

Summary by CodeRabbit

  • New Features

    • Added "Allow All" policy tier for disabling network egress filtering, enabling all outbound traffic from sandboxes via NEMOCLAW_POLICY_TIER=allow-all environment variable or nemoclaw sandbox:shields:down <name> --policy allow-all command.
  • Documentation

    • Updated policy documentation with new "Allow All" tier details and security warnings about data exfiltration risks; clarified this tier is for trusted development only.

Add an opt-in "allow-all" posture that lets the sandbox reach any public
host, alongside a scoped relaxation of the catch-all host guardrail.

- New openclaw-sandbox-allow-all.yaml: a single catch-all host: "*" base
  policy (ports 80/443) with prominent danger warnings. SSRF and
  private-network blocking still apply.
- New "allow-all" tier (tiers.yaml): swaps the base policy instead of
  layering presets. Selectable via NEMOCLAW_POLICY_TIER=allow-all at
  create time or interactively post-create.
- shields down --policy allow-all applies the catch-all to a running
  sandbox, reusing the permissive runtime FS-union path.
- Guardrail relaxed, not removed: validate-configs permits bare wildcard
  hosts only in *-allow-all.yaml files; "*" stays rejected in all normal
  presets/base policies and IP catch-alls (0.0.0.0/0, ::/0) stay rejected
  everywhere (preserves NVIDIA#1445 intent).
- Deny-by-default remains the shipped default; allow-all is opt-in only.
- Docs: tier reference + security best-practices warnings.

Note: bare host: "*" support in the OpenShell L7 proxy must be verified
on a live sandbox; the policy file documents the enforcement: audit
fallback if the proxy rejects "*".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@copy-pr-bot

copy-pr-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new "Allow All" network policy tier to NemoClaw that disables egress filtering via a catch-all wildcard host endpoint. The tier is configured as an opt-in, development-only alternative to the default deny-by-default baseline, with comprehensive validation exemptions, runtime application support, onboarding integration, and test coverage.

Changes

Allow-All Network Policy Tier

Layer / File(s) Summary
Policy tier definition and documentation
nemoclaw-blueprint/policies/openclaw-sandbox-allow-all.yaml, nemoclaw-blueprint/policies/tiers.yaml, docs/reference/network-policies.mdx, docs/security/best-practices.mdx
New allow-all YAML policy file defines a catch-all host endpoint (host: "*") for ports 80/443 with full L7 access. Tier registration and documentation warn that this removes egress filtering (though SSRF and private-network blocking remain active) and is intended for trusted development only.
Validation and allow-all exemption logic
scripts/validate-configs.ts, test/validate-configs-dangerous-hosts.test.ts
Validation script discovers the new allow-all policy YAML file. New helpers isAllowAllPolicyFile() and isBareWildcardHost() identify allow-all policy files and bare-wildcard host patterns (* optionally with port). Dangerous-host checking exempts bare-wildcard hosts only from allow-all policy files, while IP catch-all CIDRs remain flagged as dangerous.
Policy application library and exports
src/lib/policy/index.ts
Adds ALLOW_ALL_POLICY_PATH constant, resolveAllowAllPolicyPath() resolver, and applyAllowAllPolicy() function that fetches live sandbox policy, builds a runtime-permissive variant with the allow-all host, applies it via openshell, and cleans up temporary files. New symbols exported for use in onboarding and shields flows.
Sandbox onboarding and policy selection flow
src/lib/onboard.ts, src/lib/onboard/policy-selection.ts, test/policy-selection-allow-all.test.ts
Sandbox creation conditionally overrides base policy path to allow-all when tier resolves to allow-all (from NEMOCLAW_POLICY_TIER or recorded tier). Policy-selection dependencies extended with applyAllowAllPolicy callback; when allow-all tier is selected, preset selection is skipped and applyAllowAllPolicy is called directly. New test suite validates allow-all branch behavior and tier recording.
CLI documentation and shields-down policy support
src/commands/sandbox/shields/down.ts, src/lib/shields/index.ts
sandbox:shields:down command help text updated to document permissive|allow-all options and YAML file paths. Shields-down runtime extended to support allow-all as a built-in policy variant alongside permissive, reusing runtime-permissive construction with allow-all baseline path resolution.
Tier test updates
test/policy-tiers.test.ts
Tier listing now expects four tiers in order (restricted, balanced, open, allow-all). Label validation narrowed to first three tiers; allow-all tier verified to have no presets and dev/testing-only labeling (matching for "allow all" and catch-all/no-egress phrasing).

Sequence Diagram

sequenceDiagram
  participant CLI
  participant Onboarding
  participant PolicySelection
  participant PolicyLib
  participant OpenshellAPI
  participant Sandbox
  
  CLI->>Onboarding: create sandbox with NEMOCLAW_POLICY_TIER=allow-all
  Onboarding->>Onboarding: resolve tier → allow-all
  Onboarding->>Onboarding: switch basePolicyPath to ALLOW_ALL_POLICY_PATH
  Onboarding->>PolicySelection: setupPoliciesWithSelection with applyAllowAllPolicy
  PolicySelection->>PolicySelection: tierName === "allow-all" detected
  PolicySelection->>PolicySelection: onSelection([]) - skip presets
  PolicySelection->>Sandbox: wait for sandbox ready
  Sandbox-->>PolicySelection: ready
  PolicySelection->>PolicyLib: applyAllowAllPolicy(sandboxName)
  PolicyLib->>OpenshellAPI: resolve openshell binary
  PolicyLib->>Sandbox: fetch live policy YAML
  Sandbox-->>PolicyLib: current policy state
  PolicyLib->>PolicyLib: buildRuntimePermissivePolicy (merge live + allow-all)
  PolicyLib->>OpenshellAPI: openshell policy set --wait (apply runtime policy)
  OpenshellAPI->>Sandbox: apply policy (host: "*")
  PolicyLib->>PolicyLib: cleanupTempDir
  PolicyLib-->>PolicySelection: allow-all applied
  PolicySelection-->>Onboarding: complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#3788: Both PRs modify the onboarding policy-tier flow and NEMOCLAW_POLICY_TIER handling in src/lib/onboard.ts; retrieved PR's early env validation needs to account for the new allow-all tier option.
  • NVIDIA/NemoClaw#4910: Both PRs modify test/policy-tiers.test.ts tier helper APIs and tier expectations (listing, getTier assertions), with directly overlapping test code changes.
  • NVIDIA/NemoClaw#4661: Both PRs modify the onboarding policy-selection flow around setupPoliciesWithSelection/onSelection in src/lib/onboard/policy-selection.ts; main PR adds allow-all branch that calls onSelection([]) then applies policy, while retrieved PR changes handlePoliciesState to persist selections based on onSelection invocation.

Suggested labels

enhancement: policy, area: sandbox, documentation, v0.0.62

Suggested reviewers

  • cv
  • ericksoa
  • prekshivyas

Poem

🐰 A wildcard hops through egress gates,
Allow-all cheers for dev playmates,
No filtering frets, just trust and test,
Though SSRF still knows what's best!
Careful now—this power's immense,
But oh what freedom, just for once!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(policy): add opt-in allow-all network posture' clearly and concisely summarizes the main change: introducing an optional allow-all network policy feature while maintaining deny-by-default as the default.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/allow-all-network-posture

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: 5

🧹 Nitpick comments (2)
docs/reference/network-policies.mdx (1)

72-76: ⚡ Quick win

Split this warning into one sentence per line and remove the extra em dash.

LLM pattern detected. This paragraph packs multiple sentences onto single source lines, and it uses more than one em dash in the same paragraph.

As per coding guidelines, "One sentence per line in source" and "Excessive em dashes. One per paragraph is fine; multiple per paragraph ... should be flagged."

🤖 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 `@docs/reference/network-policies.mdx` around lines 72 - 76, The Warning block
and the following paragraph pack multiple sentences on single source lines and
use multiple em dashes; edit the Warning paragraph and the line starting "Allow
All has no presets..." so each sentence is on its own source line, remove the
extra em dash so only one em dash appears in the Warning paragraph, and preserve
the existing content/meaning (references to
`nemoclaw-blueprint/policies/openclaw-sandbox-allow-all.yaml`,
`NEMOCLAW_POLICY_TIER=allow-all`, and the CLI `nemoclaw sandbox:shields:down
<name> --policy allow-all` should remain unchanged).

Source: Coding guidelines

docs/security/best-practices.mdx (1)

107-109: ⚡ Quick win

Reflow this warning to one sentence per line and replace the clause colon.

This block keeps several sentences on one source line, and the colon after "selected sandbox" is general punctuation rather than a list introducer.

As per coding guidelines, "One sentence per line in source" and "Colons should only introduce a list."

🤖 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 `@docs/security/best-practices.mdx` around lines 107 - 109, Reflow the Warning
block so each sentence is on its own source line and remove the colon after
"selected sandbox" by replacing it with a comma (or reword to avoid a colon);
specifically edit the Warning block text inside the
docs/security/best-practices.mdx Warning section so that sentences like the
Allow All policy description, the SSRF/private-network note, and the final
advisory are each on separate lines and the phrase "for the selected sandbox:"
becomes "for the selected sandbox," (or an equivalent clause without a colon).

Source: Coding guidelines

🤖 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 `@docs/reference/network-policies.mdx`:
- Line 70: The doc currently contradicts itself: the new table row "Allow All" /
`allow-all` says it swaps the base policy but the paragraph above still claims
the baseline policy is always applied; update the surrounding tier description
and any nearby paragraphs (the text around the tiers table and the
baseline-policy description) to reflect that selecting the `allow-all` tier
replaces/swaps the base policy rather than applying it in addition, so the page
consistently documents `allow-all` as the only documented behavior that disables
the baseline filtering.

In `@nemoclaw-blueprint/policies/tiers.yaml`:
- Around line 53-56: The tier "allow-all" description promises unrestricted
outbound access but the actual policy in openclaw-sandbox-allow-all.yaml only
permits host: "*" on ports 80 and 443; update the "allow-all" tier copy to
explicitly call out the 80/443 restriction (e.g., append that outbound is
limited to ports 80 and 443) or alternatively remove/adjust the port restriction
in openclaw-sandbox-allow-all.yaml so the description matches the policy; be
sure to edit the "name: allow-all" tier description string to reflect the chosen
fix.

In `@scripts/validate-configs.ts`:
- Around line 220-223: The helper isAllowAllPolicyFile currently keys the
wildcard exemption on the basename only, letting files like
presets/slack-allow-all.yaml bypass checks; update it to scope the exemption by
path/schema kind instead of basename by verifying the file's full relative path
or directory (e.g., ensure the file resides in the dedicated base policy
directory or matches the exact allowed base policy path used by discoverTargets)
before returning true; adjust the same logic used at the other occurrence (lines
mentioned around 363-367) so only the dedicated allow-all base policy can use a
bare "*" and presets or other policy locations are not exempted.

In `@src/lib/onboard.ts`:
- Around line 3374-3379: The code reads recordedTier via
registry.getSandbox(sandboxName)?.policyTier after the recreate/prune path has
already removed the sandbox, so recreated sandboxes lose their previous
"allow-all" tier; change the flow to capture the sandbox's prior policyTier
before the prune/delete runs (e.g. fetch and store the value earlier where the
sandbox still exists), then use that stored value instead of calling
registry.getSandbox(...) when computing recordedTier and allowAllAtCreate (which
influences basePolicyPath and policies.ALLOW_ALL_POLICY_PATH); ensure the stored
priorTier is threaded into the logic that sets allowAllAtCreate/basePolicyPath
so recreated sandboxes retain the recorded tier defaults.
- Around line 3367-3383: Extract the allow-all base policy resolution logic from
onboard.ts into a helper in the existing policy helper/module (e.g., add a
function like resolveBasePolicyPath(agent, sandboxName) in the policies helper)
so onboard.ts no longer contains the inline env/recordedTier/allowAllAtCreate
logic; the new helper should: compute basePolicyPath = (agent &&
agentOnboard.getAgentPolicyPath(agent)) || defaultPolicyPath, read recordedTier
via registry.getSandbox(sandboxName)?.policyTier, read envTier from
process.env.NEMOCLAW_POLICY_TIER, determine allowAllAtCreate and, if true,
return policies.ALLOW_ALL_POLICY_PATH and the decision message (or a boolean)
otherwise return the normal basePolicyPath; then update onboard.ts to call this
new helper (replacing basePolicyPath, recordedTier, envTier, and
allowAllAtCreate usage) and remove the inline block so behavior (including the
console message about allow-all) remains identical while reducing onboard.ts
size.

---

Nitpick comments:
In `@docs/reference/network-policies.mdx`:
- Around line 72-76: The Warning block and the following paragraph pack multiple
sentences on single source lines and use multiple em dashes; edit the Warning
paragraph and the line starting "Allow All has no presets..." so each sentence
is on its own source line, remove the extra em dash so only one em dash appears
in the Warning paragraph, and preserve the existing content/meaning (references
to `nemoclaw-blueprint/policies/openclaw-sandbox-allow-all.yaml`,
`NEMOCLAW_POLICY_TIER=allow-all`, and the CLI `nemoclaw sandbox:shields:down
<name> --policy allow-all` should remain unchanged).

In `@docs/security/best-practices.mdx`:
- Around line 107-109: Reflow the Warning block so each sentence is on its own
source line and remove the colon after "selected sandbox" by replacing it with a
comma (or reword to avoid a colon); specifically edit the Warning block text
inside the docs/security/best-practices.mdx Warning section so that sentences
like the Allow All policy description, the SSRF/private-network note, and the
final advisory are each on separate lines and the phrase "for the selected
sandbox:" becomes "for the selected sandbox," (or an equivalent clause without a
colon).
🪄 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: Enterprise

Run ID: 582ee336-36a4-4ced-9916-e3974f8b93c5

📥 Commits

Reviewing files that changed from the base of the PR and between 8c98d76 and 58bff66.

📒 Files selected for processing (13)
  • docs/reference/network-policies.mdx
  • docs/security/best-practices.mdx
  • nemoclaw-blueprint/policies/openclaw-sandbox-allow-all.yaml
  • nemoclaw-blueprint/policies/tiers.yaml
  • scripts/validate-configs.ts
  • src/commands/sandbox/shields/down.ts
  • src/lib/onboard.ts
  • src/lib/onboard/policy-selection.ts
  • src/lib/policy/index.ts
  • src/lib/shields/index.ts
  • test/policy-selection-allow-all.test.ts
  • test/policy-tiers.test.ts
  • test/validate-configs-dangerous-hosts.test.ts

| Restricted | None | Base sandbox only. No third-party network access beyond inference and core agent tooling. |
| Balanced (default) | `npm`, `pypi`, `huggingface`, `brew`, `brave when supported` | Full dev tooling and web search for agents that support web search. No messaging platform access. |
| Open | `npm`, `pypi`, `huggingface`, `brew`, `brave when supported`, `slack`, `discord`, `telegram`, `wechat` (experimental), `whatsapp` (experimental), `jira`, `outlook` | Broad access across third-party services including messaging and productivity. |
| Allow All | None — swaps the base policy | Catch-all egress to any public host (no network filtering). Opt-in for trusted dev/testing only. |

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the surrounding tier description so allow-all is the only documented behavior.

This new table row and warning say allow-all swaps the base policy, but the paragraph above still says the baseline policy is always applied regardless of tier. Please align those statements so the page does not describe two different runtime behaviors.

Also applies to: 72-76

🤖 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 `@docs/reference/network-policies.mdx` at line 70, The doc currently
contradicts itself: the new table row "Allow All" / `allow-all` says it swaps
the base policy but the paragraph above still claims the baseline policy is
always applied; update the surrounding tier description and any nearby
paragraphs (the text around the tiers table and the baseline-policy description)
to reflect that selecting the `allow-all` tier replaces/swaps the base policy
rather than applying it in addition, so the page consistently documents
`allow-all` as the only documented behavior that disables the baseline
filtering.

Comment on lines +53 to +56
- name: allow-all
label: Allow All (no egress filtering — dev/testing only)
description: Catch-all egress to any public host. Swaps the base policy for the allow-all catch-all; presets do not apply. Maximum scope — you accept full responsibility.
presets: []

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Call out the 80/443 limit in the tier copy.

The selector text reads like unrestricted outbound access, but openclaw-sandbox-allow-all.yaml still only permits host: "*" on ports 80 and 443. As written, the UI copy promises broader reach than the policy actually grants.

🤖 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 `@nemoclaw-blueprint/policies/tiers.yaml` around lines 53 - 56, The tier
"allow-all" description promises unrestricted outbound access but the actual
policy in openclaw-sandbox-allow-all.yaml only permits host: "*" on ports 80 and
443; update the "allow-all" tier copy to explicitly call out the 80/443
restriction (e.g., append that outbound is limited to ports 80 and 443) or
alternatively remove/adjust the port restriction in
openclaw-sandbox-allow-all.yaml so the description matches the policy; be sure
to edit the "name: allow-all" tier description string to reflect the chosen fix.

Comment on lines +220 to +223
function isAllowAllPolicyFile(file: string): boolean {
const base = file.replaceAll("\\", "/").split("/").pop() ?? "";
return /-allow-all\.ya?ml$/.test(base);
}

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't key the wildcard exemption off basename alone.

discoverTargets() also validates every preset under nemoclaw-blueprint/policies/presets/. With the current helper, a preset like slack-allow-all.yaml would bypass the dangerous-host guard purely because of its filename, even though this PR's contract is that only the dedicated allow-all base policy may use bare *.

Suggested direction
+const ALLOW_ALL_POLICY_FILES = new Set([
+  "nemoclaw-blueprint/policies/openclaw-sandbox-allow-all.yaml",
+]);
+
 function isAllowAllPolicyFile(file: string): boolean {
-  const base = file.replaceAll("\\", "/").split("/").pop() ?? "";
-  return /-allow-all\.ya?ml$/.test(base);
+  return ALLOW_ALL_POLICY_FILES.has(file.replaceAll("\\", "/"));
 }

If you want this to stay extensible, the important part is scoping the exemption by path/schema kind, not by basename.

Also applies to: 363-367

🤖 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 `@scripts/validate-configs.ts` around lines 220 - 223, The helper
isAllowAllPolicyFile currently keys the wildcard exemption on the basename only,
letting files like presets/slack-allow-all.yaml bypass checks; update it to
scope the exemption by path/schema kind instead of basename by verifying the
file's full relative path or directory (e.g., ensure the file resides in the
dedicated base policy directory or matches the exact allowed base policy path
used by discoverTargets) before returning true; adjust the same logic used at
the other occurrence (lines mentioned around 363-367) so only the dedicated
allow-all base policy can use a bare "*" and presets or other policy locations
are not exempted.

Comment thread src/lib/onboard.ts
Comment on lines +3367 to +3383
let basePolicyPath = (agent && agentOnboard.getAgentPolicyPath(agent)) || defaultPolicyPath;
// Allow-all is not a preset bundle — it swaps the base policy for the
// catch-all (host: "*"). At create time the tier is known only when it comes
// from the environment (non-interactive) or a recorded recreate; interactive
// fresh onboards choose the tier post-create and apply it via
// setupPoliciesWithSelection. Swapping the base here means an env/recreate
// allow-all sandbox boots permissive from the very first request.
const recordedTier = registry.getSandbox(sandboxName)?.policyTier ?? null;
const envTier = (process.env.NEMOCLAW_POLICY_TIER || "").trim().toLowerCase();
const allowAllAtCreate =
envTier === "allow-all" || (recordedTier === "allow-all" && !envTier);
if (allowAllAtCreate) {
basePolicyPath = policies.ALLOW_ALL_POLICY_PATH;
console.log(
" Policy tier 'allow-all': booting with catch-all egress (no network filtering).",
);
}

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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Move the new allow-all onboarding glue behind a helper to get the guardrail green.

CI is already failing because src/lib/onboard.ts exceeded its growth budget, and these inline allow-all additions are the new surface. Hoisting the base-policy resolution and extra dependency wiring into an existing policy helper/module should preserve behavior while bringing this file back under the guardrail.

As per pipeline failures, src/lib/onboard.ts is currently blocked by the codebase growth guardrail.

Also applies to: 6342-6358

🤖 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 `@src/lib/onboard.ts` around lines 3367 - 3383, Extract the allow-all base
policy resolution logic from onboard.ts into a helper in the existing policy
helper/module (e.g., add a function like resolveBasePolicyPath(agent,
sandboxName) in the policies helper) so onboard.ts no longer contains the inline
env/recordedTier/allowAllAtCreate logic; the new helper should: compute
basePolicyPath = (agent && agentOnboard.getAgentPolicyPath(agent)) ||
defaultPolicyPath, read recordedTier via
registry.getSandbox(sandboxName)?.policyTier, read envTier from
process.env.NEMOCLAW_POLICY_TIER, determine allowAllAtCreate and, if true,
return policies.ALLOW_ALL_POLICY_PATH and the decision message (or a boolean)
otherwise return the normal basePolicyPath; then update onboard.ts to call this
new helper (replacing basePolicyPath, recordedTier, envTier, and
allowAllAtCreate usage) and remove the inline block so behavior (including the
console message about allow-all) remains identical while reducing onboard.ts
size.

Source: Pipeline failures

Comment thread src/lib/onboard.ts
Comment on lines +3374 to +3379
const recordedTier = registry.getSandbox(sandboxName)?.policyTier ?? null;
const envTier = (process.env.NEMOCLAW_POLICY_TIER || "").trim().toLowerCase();
const allowAllAtCreate =
envTier === "allow-all" || (recordedTier === "allow-all" && !envTier);
if (allowAllAtCreate) {
basePolicyPath = policies.ALLOW_ALL_POLICY_PATH;

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Read the previous policy tier before the recreate flow clears the registry entry.

On the recreate path, Line 3264 already removes the sandbox from the registry before this lookup runs, so registry.getSandbox(sandboxName)?.policyTier is null here. A sandbox that previously used allow-all therefore reboots with the default base policy unless NEMOCLAW_POLICY_TIER is set again, which breaks the intended first-boot behavior for recreated allow-all sandboxes. Capture the prior tier before prune/delete and thread that value into this decision instead.

Based on PR objectives, recreated allow-all sandboxes are supposed to boot with the recorded tier’s base policy.

🤖 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 `@src/lib/onboard.ts` around lines 3374 - 3379, The code reads recordedTier via
registry.getSandbox(sandboxName)?.policyTier after the recreate/prune path has
already removed the sandbox, so recreated sandboxes lose their previous
"allow-all" tier; change the flow to capture the sandbox's prior policyTier
before the prune/delete runs (e.g. fetch and store the value earlier where the
sandbox still exists), then use that stored value instead of calling
registry.getSandbox(...) when computing recordedTier and allowAllAtCreate (which
influences basePolicyPath and policies.ALLOW_ALL_POLICY_PATH); ensure the stored
priorTier is threaded into the logic that sets allowAllAtCreate/basePolicyPath
so recreated sandboxes retain the recorded tier defaults.

@wscurran wscurran added area: policy Network policy, egress rules, presets, or sandbox policy feature PR adds or expands user-visible functionality labels Jun 10, 2026
@wscurran

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: policy Network policy, egress rules, presets, or sandbox policy feature PR adds or expands user-visible functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants