Skip to content

feat(sandbox): add --permissive flag for audit2allow-style policy discovery#1856

Open
russellb wants to merge 1 commit into
NVIDIA:mainfrom
russellb:feat/1839-permissive-mode
Open

feat(sandbox): add --permissive flag for audit2allow-style policy discovery#1856
russellb wants to merge 1 commit into
NVIDIA:mainfrom
russellb:feat/1839-permissive-mode

Conversation

@russellb

Copy link
Copy Markdown
Contributor

Summary

Add permissive mode to sandboxes, enabling a single-pass onboarding workflow for discovering what network policy a workload needs. Instead of iteratively hitting denials, approving proposals one at a time, and rerunning, users create a permissive sandbox where the agent runs to completion. All would-be-denied connections succeed and generate draft proposals. Users review and approve the full set at once, then export the learned policy.

Related Issue

Closes #1839

Changes

  • proto/openshell.proto, proto/sandbox.proto: Add bool permissive to SandboxSpec and GetSandboxConfigResponse
  • crates/openshell-cli/src/main.rs, run.rs: Add --permissive flag to sandbox create with startup hint when no L7 protocol endpoints are declared
  • crates/openshell-server/src/grpc/policy.rs: Return permissive from stored sandbox spec in config response
  • crates/openshell-sandbox/src/lib.rs, grpc_client.rs, policy.rs: Read flag from config response, thread to proxy and Landlock paths via ProxyPolicy.permissive
  • crates/openshell-sandbox/src/proxy.rs: Log-but-allow on L4 deny (CONNECT and forward-proxy), L7 path-selection deny, and forward-proxy L7 enforcement. Emit DenialEvent with Allowed/Logged OCSF disposition. Use query_l7_route_snapshot_with_permissive to query endpoint configs for denied decisions so protocol hints drive L7 learning.
  • crates/openshell-sandbox/src/l7/relay.rs: Add permissive and denial_tx to L7EvalContext. Honor permissive in single-route and multi-route enforcement decisions. Emit DenialEvent with l7_method/l7_path for denied requests.
  • crates/openshell-sandbox/src/l7/websocket.rs: Honor permissive in WebSocket text-message and GraphQL-over-WebSocket enforcement, emitting DenialEvent instead of returning errors.
  • crates/openshell-sandbox/src/sandbox/linux/mod.rs: Add skip_landlock() to PreparedSandbox
  • crates/openshell-sandbox/src/process.rs, ssh.rs: Call skip_landlock() when permissive. Seccomp always enforced.
  • docs/sandboxes/policies.mdx: Add "Discover Policy with Permissive Mode" section with quick start example
  • e2e/python/test_sandbox_policy.py: 8 e2e tests covering L4 CONNECT, forward-proxy, L7 enforcement bypass, SSRF guardrails, L4 proposal generation, L7 proposal generation with method/path assertions, and no false proposals for allowed traffic

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated — 8 permissive mode tests validated against Podman gateway
  • Manual smoke test: openshell sandbox create --permissive, curl public APIs, verify proposals via openshell rule get

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)

@russellb russellb requested review from a team, derekwaynecarr and mrunalp as code owners June 10, 2026 17:32
@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.

…covery

Add permissive mode to sandboxes, enabling a single-pass onboarding
workflow for discovering what network policy a workload needs.

When `openshell sandbox create --permissive` is used, the proxy logs
but does not enforce network policy denials at both L4 (TCP connect)
and L7 (HTTP method/path) layers. Denied connections succeed with full
credential injection, and each denial feeds the existing
DenialAggregator → mechanistic mapper → draft proposal pipeline. Users
review all discovered endpoints at once with `openshell policy draft
get`, approve them, and export the learned policy.

Filesystem (Landlock) restrictions are skipped in permissive mode.
Seccomp, process identity, and SSRF guards remain enforced.

Permissive mode is threaded through all enforcement paths: CONNECT L4,
forward-proxy L4, single-route and multi-route L7 relay, forward-proxy
L7 path selection, and WebSocket/GraphQL message-level inspection. The
permissive flag flows from SandboxSpec (proto) through the gateway's
GetSandboxConfigResponse to the sandbox supervisor, which sets it on
ProxyPolicy and L7EvalContext.

Closes NVIDIA#1839

Signed-off-by: Russell Bryant <rbryant@redhat.com>
@russellb russellb force-pushed the feat/1839-permissive-mode branch from 5cb3448 to 69ed2d0 Compare June 10, 2026 18:35
@johntmyers

Copy link
Copy Markdown
Collaborator

We've had a lot of feedback and requests for something like this. My overall question is if we need to think about this more of an e2e system feature that doesn't require users to jump back in with the CLI to auto-approve everything and export a profile. My concern is that --permissive just becomes a de-facto way to run any sandbox here. The work we've done with policy.local and the auto-approval via the prover is orienting around bookends that can automate connections that are automatically deemed safe.

I don't have a concrete answer to the product experience here but just don't want the spirit of this turning into a way to launch sandboxes that are wide-open indefinitely. Some thoughts:

  • Is there a TTL we could consider (i.e. run in permissive for X minutes/hours)
  • Do pending rule chunks have annotations that say they were effectively generated as permissive mode or a "dry run" mode?

Curious on thoughts from @zredlined on the right UX we want to have. My gut says we want some system-owned experience here vs leaving it to users to "do the right thing." I could also imagine enterprises may not want this capability at all so also am curious if this should be a setting in the gateway to even have something like this available to users.

@russellb

Copy link
Copy Markdown
Contributor Author

Thanks for the UX discussion! I'm happy to completely redo this for whatever experience we can land on (or don't). I just found it easiest to start with something that works, so we have something to look at and pick on.

I agree that "just run in permissive" is not ideal, but that made me think about a possible user view. What if someone thinks, "I value the credential management in OpenShell, but I'm not interested in network access control, because I already handle that elsewhere." Someone in that frame of mind could find OpenShell's UX too restrictive and not adopt it at all. This isn't the persona I had in mind at all when doing this, but it's a thought.

I like these ideas: enforcing a configurable maximum timeout, allowing this feature to be turned off completely.

I know I intended to mark pending rules as "permissive generated," but I think I forgot to add it in the end.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: audit2allow-style permissive mode for sandbox policy learning

2 participants