Skip to content

Proxy-mode baseline enrichment overrides include_workdir: false — workdir added to read_write unconditionally #905

Description

@prekshivyas

Summary

When a sandbox policy sets include_workdir: false and places the workdir (e.g. /sandbox) in read_only, the proxy-mode baseline enrichment in enrich_proto_baseline_paths() unconditionally adds /sandbox to read_write, defeating the policy's read-only intent.

Landlock grants the union of matching rules, so /sandbox appearing in both read_only and read_write results in full write access — the opposite of what the policy requested.

Related

Root Cause

The hardcoded proxy baseline in enrich_proto_baseline_paths():

PROXY_BASELINE_READ_WRITE: ["/sandbox", "/tmp"]

This adds /sandbox to read_write if it's not already in the read_write list. It does not check:

  • Whether include_workdir is false
  • Whether the path is already in read_only (indicating deliberate read-only intent)

Flow

  1. Gateway delivers policy: /sandbox in read_only, include_workdir: false, rw: 4 paths
  2. enrich_proto_baseline_paths() adds /sandbox to read_write → rw: 5 (logged as CONFIG:ENRICHED)
  3. prepare() checks include_workdir — it's false, so it doesn't add workdir again (but it's already there from step 2)
  4. Ruleset built with /sandbox in both read_only and read_write → Landlock union = read_write
  5. restrict_self() enforces — Landlock is active but /sandbox is writable

Evidence from Testing (OpenShell 0.0.29, NemoClaw sandbox)

Landlock IS enforced (confirming #810 fix works):

$ touch /dev/shm/test    → Permission denied  (DAC 1777, not in any policy list)
$ touch /var/tmp/test     → Permission denied  (DAC 1777, not in any policy list)

But workdir is writable despite read_only policy intent:

$ touch /sandbox/test               → OK  (should be blocked)
$ touch /sandbox/.openclaw/test     → OK  (should be blocked)
$ touch /sandbox/.local/test        → OK  (should be blocked)

Policy delivered by gateway (correct):

include_workdir: false
read_only: [/sandbox, /sandbox/.openclaw, ...]
read_write: [/tmp, /dev/null, /sandbox/.openclaw-data, /sandbox/.nemoclaw]  # 4 paths

Policy after enrichment (incorrect):

CONFIG:ENRICHED — ro:9 rw:5  (one path added to rw)

Startup log confirms no fallback to container-disk policy:

2026-04-21T16:59:25.188Z INFO openshell_sandbox: Fetching sandbox policy via gRPC
2026-04-21T16:59:25.210Z INFO openshell_sandbox: CONFIG:ENRICHED ...
2026-04-21T16:59:25.212Z INFO openshell_sandbox: CONFIG:PROBED ro:9 rw:5

Suggested Fix

In enrich_proto_baseline_paths(), before adding a baseline path to read_write:

  1. Check if include_workdir is false and the path matches the workdir — if so, skip it
  2. Or: check if the path already exists in read_only — if so, respect the explicit read-only intent and don't promote it

Option 2 is more general and handles cases beyond just the workdir.

Environment

  • OpenShell: 0.0.29
  • Kernel: Linux 6.8.0-1053-gcp (Landlock ABI v4)
  • NemoClaw: alpha (prekshi/openshell-0.0.29-landlock branch)

Activity

  1. johntmyers commented on Apr 21, 2026

    @johntmyers
    Collaborator

    🏗️ build-plan

    Implementation Plan

    Issue type: fix
    Complexity: Low
    Confidence: High — clear path

    Summary

    The regression is in proxy-mode baseline filesystem enrichment inside crates/openshell-sandbox/src/lib.rs. The fix should preserve explicit read_only intent when a baseline read-write path like /sandbox is already present in read_only, so proxy enrichment no longer promotes that path to writable access in either the proto or local-policy code paths.

    Scope

    • crates/openshell-sandbox/src/lib.rs: update proxy baseline enrichment so explicit read_only entries take precedence over baseline read_write additions, and keep the proto and local SandboxPolicy enrichment flows consistent.
    • crates/openshell-sandbox/src/lib.rs tests: add regression coverage for policies that set include_workdir: false and explicitly place /sandbox in read_only, ensuring enrichment does not add it to read_write.
    • architecture/sandbox.md and architecture/security-policy.md: document that baseline enrichment skips system-injected read_write promotions when the same path is explicitly configured as read_only.

    Implementation Steps

    1. Adjust the proxy baseline enrichment logic so a baseline read_write path is skipped when that path already exists in read_only, preserving explicit operator intent.
    2. Apply the same precedence rule to both enrich_proto_baseline_paths() and enrich_sandbox_baseline_paths() so gRPC-delivered and local-file policies behave the same way.
    3. Add unit tests covering the /sandbox regression and the general "explicit read-only beats baseline read-write" behavior.
    4. Update the relevant architecture docs to describe the precedence rule.

    Test Plan

    • Unit tests: Extend crates/openshell-sandbox/src/lib.rs tests to verify enrichment leaves /sandbox read-only when it is explicitly configured there, and that no overlapping read_only/read_write entry is introduced by enrichment.
    • Integration tests: N/A — the behavior is isolated to enrichment helpers and existing unit-test coverage is the right level.
    • E2E tests: N/A — no e2e/ changes are expected for this fix.

    Risks & Open Questions

    • The main risk is fixing only the proto path and leaving the local-file SandboxPolicy enrichment path inconsistent. The implementation should keep both helpers aligned.
    • /tmp should remain baseline writable unless a policy explicitly marks it read-only; the change should not reduce baseline access more broadly than intended.

    Documentation Impact

    • Update architecture/sandbox.md and architecture/security-policy.md to reflect that explicit read_only policy entries override system-injected baseline read_write enrichment.

    Revision 1 — initial plan

  2. self-assigned this
    on Apr 21, 2026
  3. johntmyers commented on Apr 21, 2026

    @johntmyers
    Collaborator

    🏗️ build-from-issue-agent

    Implementation Complete

    PR: #910

    What was built

    Proxy-mode baseline enrichment now preserves explicit read_only filesystem intent instead of promoting the same path into read_write. The fix covers both proto-backed and local-file policy enrichment and adds regression tests for each code path.

    Tests

    • Unit: 2 tests added
    • Integration: N/A
    • E2E: N/A

    Docs updated

    • architecture/sandbox.md
    • architecture/security-policy.md

    The issue will auto-close when the PR is merged.

  4. added a commit that references this issue on Apr 22, 2026
    e28ca07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

state:agent-readyApproved for agent implementationstate:pr-openedPR has been opened for this issue

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions