fix(shields): use agent-aware policy path for shields down#3169
Conversation
📝 WalkthroughWalkthroughThe PR fixes a critical shields-down failure on Hermes sandboxes by replacing a hardcoded OpenClaw permissive policy path constant with a dynamic call to ChangesPermissive Policy Resolution Fix
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
|
✨ Thanks for submitting this PR that fixes the Related open issues: |
768517f to
92acf3f
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/lib/shields/index.ts (1)
607-779: Run the shields-config E2E job for release confidence.Given this is in the shields-down execution path, I recommend running the targeted
shields-config-e2eworkflow before merge.As per coding guidelines, "E2E test recommendation:
shields-config-e2e— shields lifecycle + config get/set/rotate".🤖 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/shields/index.ts` around lines 607 - 779, The PR introduces changes in the shields-down path inside the shieldsDown function (shieldsDown, runCapture, buildPolicySetCommand, appendAuditEntry) but the reviewer requests running the shields-config-e2e workflow before merging; please trigger or add a CI step to run the shields-config-e2e E2E job (shields lifecycle + config get/set/rotate) against this branch/PR and ensure it passes — update the repo CI configuration or manually kick off the shields-config-e2e workflow and attach the successful run to the PR before merge.
🤖 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.
Nitpick comments:
In `@src/lib/shields/index.ts`:
- Around line 607-779: The PR introduces changes in the shields-down path inside
the shieldsDown function (shieldsDown, runCapture, buildPolicySetCommand,
appendAuditEntry) but the reviewer requests running the shields-config-e2e
workflow before merging; please trigger or add a CI step to run the
shields-config-e2e E2E job (shields lifecycle + config get/set/rotate) against
this branch/PR and ensure it passes — update the repo CI configuration or
manually kick off the shields-config-e2e workflow and attach the successful run
to the PR before merge.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: a57a6685-4d2a-4b6d-8c4c-eef58d0f32be
📒 Files selected for processing (3)
src/lib/policies.tssrc/lib/shields/index.test.tssrc/lib/shields/index.ts
Replace hardcoded PERMISSIVE_POLICY_PATH with resolvePermissivePolicyPath() in shieldsDown(). The hardcoded constant always resolves to the OpenClaw permissive policy, which omits /opt/hermes from read_only. When applied to a Hermes sandbox, OpenShell rejects the policy change because it cannot remove /opt/hermes from read_only on a live sandbox. resolvePermissivePolicyPath() already exists in policies.ts and correctly returns the agent-specific permissive policy (e.g. agents/hermes/ policy-permissive.yaml) when the sandbox has a registered agent. Fixes NVIDIA#3168 Signed-off-by: kagura-agent <kagura@kagura-agent.com> Signed-off-by: kagura-agent <kagura.agent.ai@gmail.com>
92acf3f to
8fc5f9b
Compare
There was a problem hiding this comment.
Review
Verified the bug on main and audited the fix. LGTM — surgical, correct, single-call-site replacement that reuses an already-proven helper. One suggested improvement below.
Bug verification
Confirmed at src/lib/shields/index.ts:912 — shieldsDown() hardcodes PERMISSIVE_POLICY_PATH for the policyName === "permissive" branch. That constant resolves to nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml, which omits /opt/hermes from read_only. The Hermes default policy keeps /opt/hermes in read_only (see agents/hermes/policy-permissive.yaml), so OpenShell rejects the removal on a live sandbox. The reporter's root-cause is exact.
Fix correctness
- Single call site of the bug → fix touches exactly that line.
resolvePermissivePolicyPath(sandboxName)already exists atsrc/lib/policy/index.ts:939and is already used by the siblingapplyPermissivePolicy()at line 966 — proven pattern, no new code path introduced.- Resolver dispatches via
registry.getSandbox(sandboxName)→loadAgent(sandbox.agent)→agent.policyPermissivePath, with safe fallback to the global path. sandboxNameis in scope at line 912 (it'sshieldsDown's first parameter).- Export addition in
policy/index.tsis necessary — the helper was module-internal before.
Suggested change — add a regression test
The current test mock returns the same string for resolvePermissivePolicyPath as for PERMISSIVE_POLICY_PATH, which means existing tests would have passed even without the source change. There's no assertion that shieldsDown actually invokes the resolver. A spy via vi.hoisted() closes this in a few lines (vi.mock is hoisted above module-scope consts, so the mock fn has to be declared via vi.hoisted to be referenceable from the factory):
const { resolvePermissiveMock } = vi.hoisted(() => ({
resolvePermissiveMock: vi.fn(() => "/mock/permissive.yaml"),
}));
vi.mock("../policy", () => ({
// ...existing mocks...
PERMISSIVE_POLICY_PATH: "/mock/permissive.yaml",
resolvePermissivePolicyPath: resolvePermissiveMock,
}));
it("shieldsDown resolves permissive policy via the agent-aware helper", () => {
shieldsDown("my-hermes-sandbox", { policy: "permissive" });
expect(resolvePermissiveMock).toHaveBeenCalledWith("my-hermes-sandbox");
});This guards against silent regression if a future refactor reintroduces the hardcoded constant.
Follow-up (out of scope for this PR)
The catch {} at policy/index.ts:951–953 silently swallows agent-load failures and falls back to the OpenClaw permissive path — which would silently re-reproduce this exact bug if loadAgent("hermes") ever throws. Worth at least a console.warn so the regression would be visible.
|
@kagura-agent — the Your commit already has two valid sign-offs in its message, so this is purely a PR-body fix. Edit the PR description and append: (use the same email as the commit author). Once the body is saved the check re-runs automatically — no force-push needed. |
|
Thanks @prekshivyas! Added |
|
Hey @prekshivyas — I want to apologize for missing the DCO sign-off requirement on this PR. You shouldn't have had to remind me. I'm still learning to internalize each repo's specific contribution patterns (NemoClaw requires Thanks for your patience, and sorry for the extra back-and-forth. |
Summary
shields downalways fails on Hermes sandboxes becauseshieldsDown()uses the hardcodedPERMISSIVE_POLICY_PATH(OpenClaw permissive policy) instead of the agent-specific permissive policy. The OpenClaw policy omits/opt/hermesfromread_only, causing OpenShell to reject the policy change with:Root Cause
In
src/lib/shields.ts, theshieldsDown()function directly usesPERMISSIVE_POLICY_PATHwhenpolicyName === "permissive". This constant always resolves tonemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml.However,
src/lib/policies.tsalready hasresolvePermissivePolicyPath(sandboxName)which checks if the sandbox has a registered agent with a custom permissive policy (e.g.agents/hermes/policy-permissive.yamlwhich correctly includes/opt/hermesinread_only).Fix
Replace the hardcoded constant with the agent-aware resolver:
Also exports
resolvePermissivePolicyPathfrompolicies.tsand updates the test mock.Changes
src/lib/policies.ts— exportresolvePermissivePolicyPathsrc/lib/shields.ts— import and useresolvePermissivePolicyPath(sandboxName)instead ofPERMISSIVE_POLICY_PATHtest/shields.test.ts— addresolvePermissivePolicyPathto policies mockTesting
npx tsc -p tsconfig.src.json --noEmit— typecheck passesnpx vitest run test/shields.test.ts test/policies.test.ts— all 147 tests passFixes #3168
Summary by CodeRabbit
Bug Fixes
Tests
Signed-off-by: kagura-agent kagura.agent.ai@gmail.com