diff --git a/architecture/sandbox.md b/architecture/sandbox.md index 7d5fdb23bc..d760598c73 100644 --- a/architecture/sandbox.md +++ b/architecture/sandbox.md @@ -310,16 +310,20 @@ without keep-alive), the relay flushes and shuts down downstream writes before ending the exchange, including TLS close notification. Response middleware preserves this lifetime rule; persistent responses remain eligible for reuse. -An explicit `protocol: tcp` endpoint with a valid DNS hostname opts into native -DNS and transparent TCP when the selected runtime advertises that substrate. -Hostless `allowed_ips` and literal-IP selectors remain available only to the -legacy explicit-proxy path when `protocol` is omitted. The shared supervisor -answers only eligible DNS names, returns an epoch-scoped synthetic address, and -publishes the expiring name, endpoint, ports, policy generation, and validated -real addresses as one correlation. A connection to that synthetic address is -captured before the bypass fence, mapped back to its workload process, authorized -through the same egress pipeline, and dialed only through the pinned addresses. -Omitted protocol endpoints retain explicit-proxy behavior. +The supervisor answers a DNS name only when a policy endpoint with concrete +ports has a host that matches it, whatever the endpoint's protocol. It returns +an epoch-scoped synthetic address and publishes the expiring name, endpoint, +ports, policy generation, and validated real addresses as one correlation. For +each external TCP `connect` that the sandbox broker captures, the supervisor +maps a synthetic destination back to its name, or uses a literal destination IP +as the host, authorizes the open through the same egress pipeline, and replays +it as a virtual CONNECT. Relay selection then matches an explicit CONNECT: +unless the endpoint sets `tls: skip`, the supervisor terminates detected TLS, +sends HTTP through the HTTP relays, and uses the raw byte relay for other +payloads, or fails closed when the endpoint requires request inspection. +Upstream dials use only the pinned validated addresses. A `protocol: tcp` +endpoint therefore adds no request rules but does not bypass TLS handling. It +must use a DNS hostname rather than an IP literal or hostless `allowed_ips`. Provider credential placeholders are resolved through the live provider state for each HTTP request, after destination and L7 policy admission. A static diff --git a/architecture/security-policy.md b/architecture/security-policy.md index 98946df833..a79c7bb1c7 100644 --- a/architecture/security-policy.md +++ b/architecture/security-policy.md @@ -316,9 +316,10 @@ through the proposal loop instead of treating the denial as terminal. gateway reuses the persisted prover result. If it changed, the gateway persists the refreshed candidate and requires a fresh review instead of applying it. Decode, prover, merge, provider-composition, or credential - failures leave the chunk pending with an application error. The audit event uses `CONFIG:APPROVED` and carries - `auto=true`, `source=`, `prover_delta=empty`, and - `resolved_from=` as unmapped fields, with message text + failures leave the chunk pending with an application error. The audit + event uses `CONFIG:APPROVED` and carries `auto:true`, + `source:`, `prover_delta:empty`, and + `resolved_from:` as unmapped fields, with message text `"auto-approved: no new prover findings"` — never `safe`. The opt-in gate preserves OpenShell's default-deny posture: with no setting at either scope, every proposal lands in `pending` for human review, even diff --git a/crates/openshell-cli/src/run.rs b/crates/openshell-cli/src/run.rs index 74d92351ff..2e925539a6 100644 --- a/crates/openshell-cli/src/run.rs +++ b/crates/openshell-cli/src/run.rs @@ -724,7 +724,8 @@ pub async fn sandbox_create( // Persist `--approval-mode` as a sandbox-scoped setting now that the // sandbox exists. `manual` is the implicit default (no setting needed); // any other value is written so it survives sandbox restarts and can be - // flipped later via `openshell settings set proposal_approval_mode`. + // flipped later via + // `openshell settings set --key proposal_approval_mode --value `. // If the write fails the sandbox still runs in default `manual` — surface // the recovery command so the user can retry. if approval_mode != "manual" { @@ -744,7 +745,7 @@ pub async fn sandbox_create( Ok(_) => {} Err(status) => { eprintln!( - "{} failed to set approval mode '{approval_mode}' on sandbox '{sandbox_name}': {}\n retry with: openshell settings set {sandbox_name} proposal_approval_mode {approval_mode}", + "{} failed to set approval mode '{approval_mode}' on sandbox '{sandbox_name}': {}\n retry with: openshell settings set {sandbox_name} --key proposal_approval_mode --value {approval_mode}", "warning:".yellow().bold(), status.message(), ); diff --git a/crates/openshell-supervisor-process/src/skills/policy_advisor.md b/crates/openshell-supervisor-process/src/skills/policy_advisor.md index 8d792aaedb..f09c0b573c 100644 --- a/crates/openshell-supervisor-process/src/skills/policy_advisor.md +++ b/crates/openshell-supervisor-process/src/skills/policy_advisor.md @@ -131,20 +131,24 @@ A complete narrow REST-inspected rule looks like this: Auto-approval is opt-in via the `proposal_approval_mode` setting, managed through the standard settings model. Reviewers set it at the -gateway scope (fleet-wide) with `openshell settings set --global -proposal_approval_mode auto` or at the sandbox scope with `openshell -settings set proposal_approval_mode auto`. The CLI's `openshell -sandbox create --approval-mode auto` is a shorthand that writes the -sandbox-scoped setting at create time. Gateway scope wins when both are -set; the default (no setting) is `"manual"`. +gateway scope (fleet-wide) or at the sandbox scope: + +```shell +openshell settings set --global --key proposal_approval_mode --value auto +openshell settings set --key proposal_approval_mode --value auto +``` + +The CLI's `openshell sandbox create --approval-mode auto` is a shorthand +that writes the sandbox-scoped setting at create time. Gateway scope wins +when both are set; the default (no setting) is `"manual"`. When auto-approval is enabled and the prover finds nothing new, the gateway approves the chunk with actor `system:auto` and the -`CONFIG:APPROVED` audit event carries `auto=true`, `source=`, -`prover_delta=empty`, and `resolved_from=`. The -agent's `/wait` returns approved in ~1 second. When the prover does -find something — or the setting is `"manual"`/unset — the chunk lands -in `pending` for human review. +`CONFIG:APPROVED` audit event carries `auto:true`, +`source:`, `prover_delta:empty`, and +`resolved_from:`. The agent's `/wait` returns approved +in ~1 second. When the prover does find something — or the setting is +`"manual"`/unset — the chunk lands in `pending` for human review. The prover answers four formal questions about each proposed change. Each "yes" answer is its own categorical finding — there is no @@ -217,13 +221,9 @@ The new submission wins by structural overlap. - If pushing with `git` fails, that is a separate L4 or protocol-specific path from GitHub REST API access. Propose it separately. -## Local logs (read-only) - -Two local files complement the API and are useful when debugging policy -behavior: +## Logs -- `/var/log/openshell.YYYY-MM-DD.log` — shorthand log of sandbox activity. - This is what `/v1/denials` reads from. -- `/var/log/openshell-ocsf.YYYY-MM-DD.log` — full OCSF JSON events, only - written when the `ocsf_json_enabled` setting is on. Not used by - `/v1/denials`; useful for SIEM ingestion. +The OpenShell supervisor runs outside this sandbox and keeps the sandbox +activity logs, such as `/var/log/openshell.YYYY-MM-DD.log`, in its own +filesystem. You cannot read those files from inside the sandbox. Use +`GET /v1/denials` for recent denials. diff --git a/docs/about/installation.mdx b/docs/about/installation.mdx index 8a8ac97689..06b85a0d56 100644 --- a/docs/about/installation.mdx +++ b/docs/about/installation.mdx @@ -19,7 +19,17 @@ Install OpenShell with a single command: curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh ``` -The script detects your operating system and installs the OpenShell CLI, standalone policy prover, and gateway. On Linux, it installs from the Snap Store when `snap` is available and `OPENSHELL_VERSION` is unset or `dev`. Explicit release tags and prereleases use the native Debian or RPM package. It then starts the local gateway server so you can begin creating sandboxes. +The script detects your operating system and installs the OpenShell CLI and +gateway. On Linux, it installs from the Snap Store when `snap` is available and +`OPENSHELL_VERSION` is unset or `dev`. Explicit release tags and prereleases use +the native Debian or RPM package. It then starts the local gateway server so you +can begin creating sandboxes. + +The Homebrew, Debian, and RPM packages also install the `openshell-prover` CLI, +which runs the [policy prover](/reference/policy-prover). The snap package does +not include it, so on a snap installation, download the `openshell-prover` +archive for your platform from the [OpenShell +releases](https://github.com/NVIDIA/OpenShell/releases). Snap installs use `latest/stable` by default and `latest/edge` when `OPENSHELL_VERSION=dev`. Set `OPENSHELL_VERSION` to a release tag to install diff --git a/docs/reference/sandbox-compute-drivers.mdx b/docs/reference/sandbox-compute-drivers.mdx index 395a04edf8..f962232057 100644 --- a/docs/reference/sandbox-compute-drivers.mdx +++ b/docs/reference/sandbox-compute-drivers.mdx @@ -18,9 +18,13 @@ grants lack a trusted label resolver and are unavailable with admission enabled. See [External Resource Admission](gateway-config#external-resource-admission) for configuration, migration, and the explicit unsafe opt-out. -Most compute drivers run the OpenShell supervisor inside the sandbox workload. -The supervisor launches the agent process, applies policy, routes egress through -the proxy, injects configured credentials, and maintains the gateway session. +The Docker, Podman, MicroVM, and Kubernetes drivers run the OpenShell supervisor +outside the sandbox workload, in a separate container, Pod, or host process. +Inside the workload, `openshell-sandbox` applies filesystem and system call +restrictions and launches the agent process. The supervisor evaluates network +policy, routes egress through its proxy, injects configured credentials, and +maintains the gateway session. + A driver may instead set `driver_reports_runtime_readiness`. In that mode, driver-reported readiness does not require a supervisor session. The canonical create-time policy is part of `DriverSandboxSpec`; a driver that enforces policy diff --git a/docs/sandboxes/inference-routing.mdx b/docs/sandboxes/inference-routing.mdx index 4ba63ea7ca..c98c44f318 100644 --- a/docs/sandboxes/inference-routing.mdx +++ b/docs/sandboxes/inference-routing.mdx @@ -147,12 +147,18 @@ endpoints: binaries: - /usr/bin/curl - /usr/local/bin/curl - - /usr/bin/python3 - - /usr/local/bin/python + - /usr/bin/python3.* + - /usr/local/bin/python3.* - /sandbox/.uv/python/** - /sandbox/.venv/** ``` +OpenShell matches the real path of each executable, not a symlink such as +`/usr/bin/python3`, so the profile uses globs that match versioned interpreters +such as `/usr/bin/python3.12`. To find an interpreter's real path, run +`readlink -f /usr/bin/python3` inside the sandbox, and adjust `binaries` to +match the executables in your image. + Import the profile, create an instance, and attach it: ```shell