release-1.1.1
opensandbox-group/OpenSandboxrelease-1.1.1Oct 9, 2026by github-actions[bot]
Upgrading?
AI Summary
This patch release fixes a critical bug in the 1.1.0 server wheel where FastPath gRPC stubs were missing due to hatchling's VCS-exclude filtering, ensuring clean imports. It also introduces identity-bound filesystem operations, tenant isolation for sandboxes sharing a Kubernetes namespace, and server hardening improvements.
Key Highlights
- Fixes the broken 1.1.0 server wheel by including FastPath gRPC stubs in the package.
- Identity-bound filesystem operations where execd executes file APIs as an explicit UID/GID.
- Server hardening with race-free snapshot creation and meaningful backend error codes (502/504).
- Tenant isolation for sandboxes sharing a Kubernetes namespace.
New Features
- Pause/resume functionality for the agent-sandbox provider.
- Tenant isolation via the opensandbox.io/tenant label stamping.
- Docker publish_host configuration to restrict port exposure.
- Upstream proxy chaining for the egress sidecar.
- env support on template create for fast-sandbox golden images.
- Watch-driven Kubernetes creation latency reduction.
- FastPath error message propagation through capacity mapping.
Full Release Notes
Stable cut of the `1.1.1` patch line: fixes the broken `1.1.0` server wheel — hatchling's VCS-exclude filtering silently dropped the committed FastPath gRPC stubs from the PyPI package, so every `1.1.0` install of `opensandbox-server` failed at import time; PyPI is immutable, so the fix ships on this line ([#1959](https://github.com/opensandbox-group/OpenSandbox/pull/1959)). SDK/CLI/server packages publish at `1.1.1` (`1.1.1-rc.1` shipped images only). Everyone on `1.1.0` should upgrade. Baseline for every section below: `release-1.1.0`.
## Highlights
- Fixes the `1.1.0` server wheel: FastPath stubs now ship in the package and installs import cleanly; SDK/CLI/server packages publish at `1.1.1` ([#1959](https://github.com/opensandbox-group/OpenSandbox/pull/1959))
- Identity-bound filesystem operations: execd executes file APIs as an explicit Linux UID/GID, with `FilesWithIdentity`/`files_with_identity` in all five SDKs; isolated sessions gain multiple independent overlay mounts ([#2070](https://github.com/opensandbox-group/OpenSandbox/pull/2070) [#2093](https://github.com/opensandbox-group/OpenSandbox/pull/2093) [#2094](https://github.com/opensandbox-group/OpenSandbox/pull/2094) [#2095](https://github.com/opensandbox-group/OpenSandbox/pull/2095) [#2096](https://github.com/opensandbox-group/OpenSandbox/pull/2096) [#2097](https://github.com/opensandbox-group/OpenSandbox/pull/2097) [#2032](https://github.com/opensandbox-group/OpenSandbox/pull/2032))
- Server hardening: snapshot creation submits the runtime object before persisting so early reads can't map to `Failed`, proxied backend failures map to 502/504 instead of a generic 500, and diagnostics work for pooled sandboxes ([#2098](https://github.com/opensandbox-group/OpenSandbox/pull/2098) [#2077](https://github.com/opensandbox-group/OpenSandbox/pull/2077) [#2084](https://github.com/opensandbox-group/OpenSandbox/pull/2084) [#2104](https://github.com/opensandbox-group/OpenSandbox/pull/2104))
## Server
- Implement pause/resume for the agent-sandbox provider by bridging to `spec.operatingMode` (`Running`/`Suspended`) on `agents.x-k8s.io/v1beta1`, with state derivation (`Paused`/`Pausing`/`Resuming`/`Terminated`) and 409 on invalid transitions; both endpoints previously returned "not supported" ([#1975](https://github.com/opensandbox-group/OpenSandbox/pull/1975))
- Isolate tenants that share one Kubernetes namespace: creates stamp `opensandbox.io/tenant`, and list/get/delete/pause/resume/proxy hide other tenants' labeled sandboxes as 404 while unlabeled legacy sandboxes stay visible until expiry; also adds `kubernetes.insecure_skip_tls_verify` for ServiceAccount CA mismatches ([#1973](https://github.com/opensandbox-group/OpenSandbox/pull/1973))
- Heal the silent renew-intent drop after a server restart in multi-tenant mode: the resolver now falls back to a cluster-wide label lookup with a 403 circuit breaker and structured warnings, trusts an ingress-observed namespace from the intent payload when verifiable, and single-tenant deployments never resolve beyond the configured namespace ([#1819](https://github.com/opensandbox-group/OpenSandbox/pull/1819))
- Add `[docker] publish_host` to publish bridge-mode sandbox ports on one host address (default `0.0.0.0` unchanged) — with `127.0.0.1` or the Docker bridge gateway, the tokenless execd port no longer lands on public interfaces ([#1954](https://github.com/opensandbox-group/OpenSandbox/pull/1954))
- Add a typed, admin-only `[egress.upstream_proxy]` config section (URL + optional authorization, validated at load) that injects the sidecar's chained upstream CONNECT proxy on both Docker and Kubernetes, with fail-closed 400s when the requested `networkPolicy` is incompatible; secret values are no longer echoed in config-validation errors ([#1999](https://github.com/opensandbox-group/OpenSandbox/pull/1999)), plus `ca_cert_path` (Docker) and `ca_secret_name` (Kubernetes) so `https://` proxies signed by a private CA are trusted without replacing the system trust store — the PEM augments `/etc/ssl/certs` in the sidecar ([#2030](https://github.com/opensandbox-group/OpenSandbox/pull/2030))
- Make snapshot creation race-free for early readers on k8s/fsb: `POST /sandboxes/{id}/snapshots` now creates the runtime object (SandboxSnapshot CR / fsb submit) before persisting the `Creating` row and returns without queueing a worker, so read-time sync can no longer map a not-yet-created object to `Failed` — including on other HA replicas; recovery resubmits stuck rows inline ([#2098](https://github.com/opensandbox-group/OpenSandbox/pull/2098)), fixing the window where a client polling right after create flipped the row to a permanent `Failed` ([#2077](https://github.com/opensandbox-group/OpenSandbox/pull/2077))
- Map proxied backend failures to meaningful statuses: read/write timeouts return 504 `BACKEND_TIMEOUT`, mid-response resets and protocol errors return 502 `BACKEND_RESPONSE_FAILED`, keeping 502 `BACKEND_CONNECTION_FAILED` for connect failures — a sandbox that dies mid-request no longer looks like a server bug ([#2084](https://github.com/opensandbox-group/OpenSandbox/pull/2084))
- Find pool-allocated pods for k8s diagnostics: pooled BatchSandboxes don't carry the `opensandbox.io/id` pod label, so every logs/events/inspect call returned 404; the lookup now falls back to the pods listed in the workload's `alloc-status` annotation ([#2104](https://github.com/opensandbox-group/OpenSandbox/pull/2104))
- Remove auto-created Docker volumes when create fails before the provisioning block runs (image pull, credential/upstream-proxy checks, Windows prerequisites, OSSFS prep) — a mistyped image name no longer leaks the PVC it triggered ([#2103](https://github.com/opensandbox-group/OpenSandbox/pull/2103))
- Report deleting pooled/task-mode BatchSandboxes as `Stopping`/`DELETING`: `metadata.deletionTimestamp` now wins over runtime status publication, so a sandbox whose pods go not-ready during finalization no longer flips back to `Pending`/`CREATING` ([#2122](https://github.com/opensandbox-group/OpenSandbox/pull/2122))
- Stop Docker metadata PATCHes from resurrecting deleted keys: `patch()` now starts from the override file (as `get()` does) instead of re-merging container labels, so `{"env": null}` stays deleted and an emptied override file doesn't restore the original labels ([#2065](https://github.com/opensandbox-group/OpenSandbox/pull/2065))
- Accept `env` on template create and bake it into the fast-sandbox golden image (`/etc/sandbox-init.env`, inheriting the source image's OCI `Config.Env`), closing the gap where `SandboxTemplate.spec.envs` existed but the lifecycle API rejected it; supported across all SDKs ([#1984](https://github.com/opensandbox-group/OpenSandbox/pull/1984))
- Wake Kubernetes creation waits on informer watch events instead of fixed 1-second polling, cutting prewarmed-pool create latency from ~1 s to tens of milliseconds while keeping the polling fallback ([#1996](https://github.com/opensandbox-group/OpenSandbox/pull/1996))
- Ship the committed FastPath gRPC stubs in the server wheel by force-including them past hatchling's VCS excludes, and smoke-import the built wheel in the release workflow before publishing — this is the `1.1.0` install-time breakage fix ([#1959](https://github.com/opensandbox-group/OpenSandbox/pull/1959))
- Fix the Fast Sandbox snapshot CR plural (`sandboxsnapshots`) in Helm RBAC and the fsb snapshot runtime, where `sandboxesnapshots` could fail list/watch with missing RBAC ([#1972](https://github.com/opensandbox-group/OpenSandbox/pull/1972))
- Propagate the underlying FastPath error message through the 429 capacity mapping (keeping status and `Retry-After`, adding a `cause` field) so admission/runtime failures like a broken KVM device are no longer masked as pool exhaustion, and warn-log the raw error before mapping ([#2001](https://github.com/opensandbox-group/OpenSandbox/pull/2001))
- Clarify the renewal contract: `renew-expiration` may shorten, preserve, or extend expiration (any future target is valid) and `max_sandbox_timeout_seconds` caps only creation, not renewal or total lifetime — documentation and SDK references aligned, with regression coverage across Docker, Kubernetes, and FastSandbox ([#2087](https://github.com/opensandbox-group/OpenSandbox/pull/2087))
- Fix Docker edges: reject a repeated pause of an already-paused sandbox with the documented 409 instead of surfacing Docker's "already paused" as 500 ([#2023](https://github.com/opensandbox-group/OpenSandbox/pull/2023)), and clear Docker masked/read-only system paths only for sandboxes that opt into the isolation extension so nested Bubblewrap can mount a private procfs ([#1982](https://github.com/opensandbox-group/OpenSandbox/pull/1982))
## SDKs
- Add identity-bound filesystem operations end to end: execd gains additive `/v1/filesystem/{uid}/{gid}` routes backed by a per-request worker process running with explicit credentials and account-derived supplementary groups (fail-closed, existing routes unchanged), and every sandbox SDK exposes it — Python `files_with_identity`, JavaScript `filesWithIdentity`, Kotlin `filesWithIdentity`, C# `FilesWithIdentity`, Go `FilesWithIdentity` — so Linux checks the selected user's permissions during actual access; identity selection belongs in the trusted backend, this enforces filesystem permissions and is not a tenant boundary ([#2070](https://github.com/opensandbox-group/OpenSandbox/pull/2070) [#2093](https://github.com/opensandbox-group/OpenSandbox/pull/2093) [#2094](https://github.com/opensandbox-group/OpenSandbox/pull/2094) [#2095](https://github.com/opensandbox-group/OpenSandbox/pull/2095) [#2096](https://github.com/opensandbox-group/OpenSandbox/pull/2096) [#2097](https://github.com/opensandbox-group/OpenSandbox/pull/2097))
- Expose multiple independent overlay mounts per isolated session across the API and all five SDKs: `CreateIsolatedSessionRequest.overlays` (`{path, mode, persist}`) with separate host-tracked or ephemeral tmpfs uppers, `workspace` kept as sugar, and `SessionState` echoing the canonical list — completing the internal foundation from [#2021](https://github.com/opensandbox-group/OpenSandbox/pull/2021) ([#2032](https://github.com/opensandbox-group/OpenSandbox/pull/2032))
- Add `commands.setEnv` for persistent runtime env injection in all five sandbox SDKs (Python async/sync, JavaScript, Kotlin/Java, Go, C#): appends `KEY=VALUE` to the sandbox env file with runtime-exact serialization, local key/NUL validation, and a loud failure when `EXECD_ENVS` is unset ([#2013](https://github.com/opensandbox-group/OpenSandbox/pull/2013))
- Systematic cross-language audit cleanup across sandbox, code-interpreter, and MCP SDKs: Go retry backoff collapsing to zero delay and dropped session `cwd`, Python isolated-session ignoring `encoding` and readiness budgets reporting stale errors, JS resume sharing and killing the source sandbox's transport, Kotlin codes runs dropping every SSE-framed event and never setting `exitCode`, C# create failing on fresh-sandbox 404 and NREs on empty bodies, and MCP per-call closes tearing down the server-wide shared transport — each fixed with regression tests ([#2020](https://github.com/opensandbox-group/OpenSandbox/pull/2020))
- Support `env` on template create across all five SDKs, matching the server-side golden-image baking ([#1984](https://github.com/opensandbox-group/OpenSandbox/pull/1984))
- Align background command stream completion across languages: with execd's fixed completion delay removed, background result collection in Go, Kotlin, and C# now returns on startup acknowledgement like Python and JavaScript instead of waiting for EOF and inferring exit code 0 — query command status for the eventual outcome; foreground calls still read to EOF for older servers ([#1825](https://github.com/opensandbox-group/OpenSandbox/pull/1825))
### Python
- Raise on error responses from `create_session` and `delete_session`: both passed the parsed model to the error handler (which needs the raw status), so 400/404/500 returned `None` as success and unknown statuses raised with a bogus `status_code=200` — the CLI could print "Deleted session" for a session that never existed ([#2066](https://github.com/opensandbox-group/OpenSandbox/pull/2066))
- Expose `follow_redirects` on `ConnectionConfig`/`ConnectionConfigSync`, propagated to all handwritten async/sync httpx clients including SSE clients and generated-client wrappers ([#1123](https://github.com/opensandbox-group/OpenSandbox/pull/1123))
- Keep the last real endpoint error when the readiness deadline expires mid-request: the budget no longer records its own `SandboxReadyTimeoutException` as `last_error`, so causes like `KUBERNETES::POD_IP_NOT_AVAILABLE` aren't masked as a plain timeout ([#2121](https://github.com/opensandbox-group/OpenSandbox/pull/2121))
- Authenticate Code Interpreter requests in server-proxy mode: context creation and streamed execution now attach the API key like sandbox file requests, fixing 401s from the same proxy ([#2125](https://github.com/opensandbox-group/OpenSandbox/pull/2125))
- Serialize `SandboxPoolSync.shutdown()` teardown: concurrent shutdown (or shutdown racing `start()`) could close the warmup event loop twice; teardown is now idempotent under a dedicated lock ([#2041](https://github.com/opensandbox-group/OpenSandbox/pull/2041))
- Orphan the shared warmup event loop instead of closing it over an in-flight warmup: when the bounded drain wait ends with warmups still running, shutdown leaves the loop alive so the in-flight warmup finishes and cleans up its sandbox, instead of destroying the pending task and skipping cleanup ([#2142](https://github.com/opensandbox-group/OpenSandbox/pull/2142))
- MCP: map expected OpenSandbox validations to MCP 2.x `ToolError` so clients get the actionable message instead of a generic "Error executing tool" ([#2108](https://github.com/opensandbox-group/OpenSandbox/pull/2108))
### JavaScript
- Treat empty-body non-2xx responses as errors: openapi-fetch sets no `error` for `Content-Length: 0`/204/HEAD responses, so an empty 404/502/503 from a gateway made `deleteSandbox`, `pauseSandbox`, and file deletes look successful in both the sandbox and code-interpreter packages ([#2101](https://github.com/opensandbox-group/OpenSandbox/pull/2101))
### Kotlin
- Identity-bound filesystem operations via `sandbox.filesWithIdentity(uid, gid)` — see the cross-SDK entry above ([#2095](https://github.com/opensandbox-group/OpenSandbox/pull/2095))
### C#
- Identity-bound filesystem operations via `sandbox.FilesWithIdentity(uid, gid)` — see the cross-SDK entry above ([#2096](https://github.com/opensandbox-group/OpenSandbox/pull/2096))
### Go
- Identity-bound filesystem operations via `sandbox.FilesWithIdentity(uid, gid)` — see the cross-SDK entry above ([#2097](https://github.com/opensandbox-group/OpenSandbox/pull/2097))
- Document previously uncovered surfaces: file operations, volume mounts (`host`/`pvc`/`ossfs`), the full template workflow, `WaitUntilReady` with custom health checks, and `SandboxManager` ([#2024](https://github.com/opensandbox-group/OpenSandbox/pull/2024))
## Controller
- Add OpenTelemetry allocator-path metrics on the `opensandbox/controller` meter: pool-allocation schedule, alloc-state persist, and alloc-result sync duration histograms with namespace/pool/success attributes, exported over OTLP ([#2014](https://github.com/opensandbox-group/OpenSandbox/pull/2014))
- Prepare the pool-assign surface for custom extension: the `Predicate` interface and predicate methods under `poolassign` are now exported — the package remains under `kubernetes/internal/`, so external Go modules cannot import it yet ([#2037](https://github.com/opensandbox-group/OpenSandbox/pull/2037))
- Auto-replace BatchSandbox pods stuck in provisioning failures during initial startup: never-Ready pods waiting in `ImagePullBackOff`/`ErrImagePull` are deleted after a threshold so the scheduler can escape a broken node (a full disk had left one production fleet with 114 stuck sandboxes), with a per-sandbox, per-generation replacement budget and a `PodRecoveryLimitReached` warning; permanently broken images are skipped ([#1961](https://github.com/opensandbox-group/OpenSandbox/pull/1961))
- Support custom snapshot image URI templates: `--snapshot-image-uri-template` / `controller.snapshot.imageURITemplate` name rootfs and QEMU VM-state targets with snapshot/sandbox/container/namespace metadata and `date`/`dateInZone` helpers, validated (invalid refs, duplicate targets) before Job creation; empty keeps existing naming ([#2004](https://github.com/opensandbox-group/OpenSandbox/pull/2004))
- Fix the free-pod predicate admitting pods on a non-empty IP alone: the task scheduler bound tasks to pods Kubernetes marked `NotReady` (still starting or restarting), the assignment POST failed with no retry, and a healthy sibling was skipped; readiness is now required like every other predicate ([#2138](https://github.com/opensandbox-group/OpenSandbox/pull/2138))
- Keep the last-known task status when a status query fails during release: a single timed-out `/getTasks` no longer marks a `releasing` task as gone, which skipped `Set(nil)`, skipped the postStop hook, and let the controller drop the cleanup finalizer or return the pod to the pool while the task still ran ([#2067](https://github.com/opensandbox-group/OpenSandbox/pull/2067))
- Skip pause dispatch for an already-`Paused` BatchSandbox: renewing a paused sandbox bumped its generation and re-triggered `handlePause`, which needs a running source pod and drove the sandbox to `Failed`/`PauseFailed` ([#2082](https://github.com/opensandbox-group/OpenSandbox/pull/2082))
- Fix an image-committer deadlock where pausing the QEMU container via cgroup v2 freeze never completes (KVM worker kernel threads never reach `frozen`), by skipping the redundant freeze for the QEMU container already paused over QMP and committing with `--pause=false` ([#1986](https://github.com/opensandbox-group/OpenSandbox/pull/1986))
## Execd
- Execute ordinary filesystem operations under an explicit Linux identity: additive `/v1/filesystem/{uid}/{gid}` routes spawn a per-request worker process with the selected uid/gid and account-derived supplementary groups, fail-closed on unsupported platforms; existing routes keep their current identity — the SDK-facing follow-ups ship in the same release ([#2070](https://github.com/opensandbox-group/OpenSandbox/pull/2070))
- Expose the public isolated-session overlays API (validation, canonical merge with legacy `workspace`, per-overlay allocator assignment) — details and SDK support under SDKs ([#2032](https://github.com/opensandbox-group/OpenSandbox/pull/2032))
- Give overlay sessions a durable cleanup identity outside their removable subtree (`<upper_root>/.execd-cleanup/<session-id>`): startup recovery removes only exact matching directories, and partial deletion or lost records are retried within the process or across restarts instead of orphaning upper dirs ([#2107](https://github.com/opensandbox-group/OpenSandbox/pull/2107))
- Let children of a finished background command keep running: the post-`Wait` context cancel no longer SIGKILLs the whole process group, so a backgrounded `nohup ./server &` survives its script — cancellation and timeouts still kill the group ([#2074](https://github.com/opensandbox-group/OpenSandbox/pull/2074))
- Kill the whole process group when a bash session run times out: only bash itself was killed, so `(sleep 2; …)` children kept the run hanging past its deadline ([#2079](https://github.com/opensandbox-group/OpenSandbox/pull/2079))
- Preserve `\n`/`\r` bytes in foreground `/command` stdout/stderr event text, so concatenated events reconstruct the command's line endings including blank lines and a trailing unterminated fragment; the Python SDK's display-oriented `Execution.text` and stderr summary no longer insert extra blank lines when CRLF arrives across events, while raw `logs.stdout`/`logs.stderr` keep their original text ([#2033](https://github.com/opensandbox-group/OpenSandbox/pull/2033))
- Remove the per-run bash session script file (`execd_bash_*.sh`), which retained a copy of every session environment variable — secrets included — readable by any later command as the same user ([#2076](https://github.com/opensandbox-group/OpenSandbox/pull/2076))
- Clamp the HTTP `Range` end before computing length: `bytes=0-9223372036854775807` overflowed into a negative length and answered 206 with a broken `Content-Range`/`Content-Length` and no body, on both regular and isolated-session downloads ([#2089](https://github.com/opensandbox-group/OpenSandbox/pull/2089))
- Remove the fixed one-second delay after command completion, cutting median terminal-event-to-return latency from ~1000 ms to sub-millisecond while retaining output flushing and heartbeat cleanup ([#1825](https://github.com/opensandbox-group/OpenSandbox/pull/1825))
- Stop logging every stdout/stderr chunk at info level, which accounted for 99.8% of execd log volume on output-heavy workloads ([#1906](https://github.com/opensandbox-group/OpenSandbox/pull/1906))
## Networking
### egress
- Continue the credential-bound TLS interception foundation (OSEP-0023) **[EXPERIMENTAL]** across the line: generation-pinned live revision-session callbacks held under the mitmproxy lifecycle lock ([#2036](https://github.com/opensandbox-group/OpenSandbox/pull/2036)), credential-free ClientHello classification of ECH/SNI/static pass-through with `needs_registry` admission requests ([#2046](https://github.com/opensandbox-group/OpenSandbox/pull/2046)), a bounded connection-admission registry that denies on exhaustion instead of downgrading to opaque pass-through ([#2062](https://github.com/opensandbox-group/OpenSandbox/pull/2062)) and flags admissions uncovered by selector cutovers ([#2072](https://github.com/opensandbox-group/OpenSandbox/pull/2072)), request admission pinned to one immutable snapshot with no old-credential fallback and permanent fences for removed hosts ([#2088](https://github.com/opensandbox-group/OpenSandbox/pull/2088)), bounded request-handle lifecycles with a global budget and paginated inspection ([#2091](https://github.com/opensandbox-group/OpenSandbox/pull/2091)), monotonic retirement deadlines for uncovered connections ([#2100](https://github.com/opensandbox-group/OpenSandbox/pull/2100)), joint Receiver/TLS-Registry publication with prepare/commit/abort retry semantics ([#2106](https://github.com/opensandbox-group/OpenSandbox/pull/2106)) wired into the authenticated revision IPC via an internal InstallationReceiver ([#2120](https://github.com/opensandbox-group/OpenSandbox/pull/2120)), revision-backed Vault mutation transactions with exact-attempt reconciliation and readiness fencing ([#2124](https://github.com/opensandbox-group/OpenSandbox/pull/2124)), frozen effective-policy revision candidates revalidating every binding including HTTP-only ones ([#2139](https://github.com/opensandbox-group/OpenSandbox/pull/2139)), guarded revision recovery and readiness publication with exact bootstrap identity and quarantined uncertain outcomes ([#2151](https://github.com/opensandbox-group/OpenSandbox/pull/2151)), and cross-language IPC recovery coverage against the production endpoint ([#2136](https://github.com/opensandbox-group/OpenSandbox/pull/2136)) — groundwork only; public Vault writes still 503 under the gate and selective TLS stays disabled
- Extend the chained upstream CONNECT proxy: trust `https://` proxies signed by a private CA via an append-style `OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_EXTRA_CA` bundle that augments the system trust store for all upstream TLS verification, configured from the server's `ca_cert_path`/`ca_secret_name` ([#2030](https://github.com/opensandbox-group/OpenSandbox/pull/2030)); support the chained proxy under the fast-sandbox profile with profile-wide endpoint drops so sandbox workloads cannot reach the upstream proxy directly, infrastructure DNS seeding resolved concurrently through dnsproxy upstreams and the Pod resolver, and atomic nft table seeding with drop elements permanent across daemon downtime ([#2003](https://github.com/opensandbox-group/OpenSandbox/pull/2003))
- Add an opt-in chained upstream CONNECT proxy to the transparent mitmproxy path (`OPENSANDBOX_EGRESS_UPSTREAM_PROXY`/`_AUTH`), routing sandbox egress through corporate forward proxies with SNI/Host-consistent CONNECT authority, fail-closed startup validation, and no behavior change when unset ([#1816](https://github.com/opensandbox-group/OpenSandbox/pull/1816))
- Roll back the persisted policy file when an nft apply fails, so a restart never loads a policy the caller was told had failed — potentially looser than the one actually running ([#2075](https://github.com/opensandbox-group/OpenSandbox/pull/2075))
- Tolerate nested percent-encoded slashes in the credential proxy path guard: the single-layer `%2f` relaxation now applies at any decode depth, so `pip` downloads from internal PyPI proxies no longer fail with 403 `request path contains ambiguous segments` while Credential Vault is active; dot-segments, backslashes at every depth, and non-converging decodes are still rejected ([#2153](https://github.com/opensandbox-group/OpenSandbox/pull/2153))
- Continue the earlier credential-bound groundwork: bootstrap authenticated revision sessions on sidecar launch and restart behind an internal gate ([#1948](https://github.com/opensandbox-group/OpenSandbox/pull/1948)), stage unpublished Credential Vault mutation candidates with acknowledge-before-publish commit semantics ([#1980](https://github.com/opensandbox-group/OpenSandbox/pull/1980)), serialize `/policy` and Vault writes behind a shared mutation barrier ([#1991](https://github.com/opensandbox-group/OpenSandbox/pull/1991)), stage always-rule reloads before publishing ([#1997](https://github.com/opensandbox-group/OpenSandbox/pull/1997)), retain exact attempt identity across indeterminate coordinator outcomes ([#2007](https://github.com/opensandbox-group/OpenSandbox/pull/2007)), and add post-bootstrap revision updates with exact-attempt reconciliation ([#2017](https://github.com/opensandbox-group/OpenSandbox/pull/2017))
### ingress
- Fail at chart render time when `providerType=fast-sandbox` is set without a secure-access key ring: the gateway previously passed `helm template` and then CrashLoopBackOff'd on `FastPath routing requires --secure-access-keys`; the deployment guide now also documents the gateway as required on Kubernetes (sandbox Pods are ClusterIP-only) and installed before the server ([#2047](https://github.com/opensandbox-group/OpenSandbox/pull/2047))
- Support per-request opt-out of access renew intents via an `OpenSandbox-Access-Renew: skip` header, suppressed before throttle state is touched and stripped on both the gateway and the server proxy paths — for health probes and other heartbeat-style traffic ([#1966](https://github.com/opensandbox-group/OpenSandbox/pull/1966))
## Fast Sandbox
- Bump the pinned fast-sandbox source twice more: `83139cc` makes the Firecracker runtime require XFS with reflink at startup ([#2123](https://github.com/opensandbox-group/OpenSandbox/pull/2123)); `b702fbe` preserves the guest gateway MAC across snapshot restores with a committed-cache recheck before delivery retry and ARP-cache regression coverage, and the vendored CRD bundle drops the `boxlite` runtime enum that upstream removed ([#2145](https://github.com/opensandbox-group/OpenSandbox/pull/2145)); the earlier `2b5e840` pin drops the node-side guest kernel asset (`kernelPath` becomes optional), adds snapshot CPU-template compatibility admission, and rebinds jailed `/dev/kvm` to host device numbers before restore ([#2028](https://github.com/opensandbox-group/OpenSandbox/pull/2028)), with the intermediate `fb87a53` bumping the builder's default guest kernel to 6.18.36 ([#1992](https://github.com/opensandbox-group/OpenSandbox/pull/1992)) and `f45bc60` dropping CRD CEL validations for older API servers, making P2P optional, and letting template guests inherit the source image's OCI env ([#1989](https://github.com/opensandbox-group/OpenSandbox/pull/1989))
- Create the shared system namespace in the `base` chart (`fastSandbox.namespaces.createSystem`, default `true`, `helm.sh/resource-policy: keep`): the fast-sandbox control-plane ServiceAccounts previously assumed the namespace was bootstrapped later, breaking the documented base-first install order and every rendered-manifest/GitOps flow ([#2044](https://github.com/opensandbox-group/OpenSandbox/pull/2044))
- Chart: add controller tolerations, a `sandboxtemplateBuilderPodSpec` PodSpec-fragment ConfigMap merged into golden-image build pods, a `fastletProxyImage` override so the injected sidecar no longer has to come from docker.io, and agent/janitor runtime resources for tainted or registry-restricted clusters ([#1968](https://github.com/opensandbox-group/OpenSandbox/pull/1968))
- Replace MinIO with RustFS in the integration environment ([#2009](https://github.com/opensandbox-group/OpenSandbox/pull/2009))
## Misc
- CLI: add template and snapshot management (`osb template create|get|list|delete`, `osb snapshot ...`, plus `--template`/`--snapshot-id` on `sandbox create`) ([#2002](https://github.com/opensandbox-group/OpenSandbox/pull/2002)), kubectl-style `-f/--file` request files for `sandbox create` and `template create` covering the full wire format with strict unknown-field rejection ([#2019](https://github.com/opensandbox-group/OpenSandbox/pull/2019)), fix `sandbox metrics --watch` failing on execd's raw SSE field names ([#1970](https://github.com/opensandbox-group/OpenSandbox/pull/1970)), exit non-zero when a foreground command's SSE stream ends without a completion or error event instead of reporting success ([#2099](https://github.com/opensandbox-group/OpenSandbox/pull/2099)), and reject failed or unconfirmed background starts before printing success metadata ([#2109](https://github.com/opensandbox-group/OpenSandbox/pull/2109)), and edit `osb config set` values through a real TOML parser instead of string concatenation, preserving comments and layout with correct escaping so quoted or multiline values no longer corrupt the config ([#2146](https://github.com/opensandbox-group/OpenSandbox/pull/2146))
- Charts: correct chart metadata, unify image tag defaults on `release-<appVersion>` fallbacks, make `imagePullPolicy` configurable, keep the dataplane Namespace on `helm.sh/resource-policy: keep`, and rewrite the deployment guide around the umbrella release flow with an explicit install order ([#2006](https://github.com/opensandbox-group/OpenSandbox/pull/2006))
- Docs: publish fast-sandbox performance pages with measured create/snapshot/restore figures ([#1951](https://github.com/opensandbox-group/OpenSandbox/pull/1951) [#1992](https://github.com/opensandbox-group/OpenSandbox/pull/1992)) and refresh the README performance claims with ACK measurements ([#2086](https://github.com/opensandbox-group/OpenSandbox/pull/2086) [#2115](https://github.com/opensandbox-group/OpenSandbox/pull/2115)), add an ACK deployment guide and an upstream-proxy operations guide ([#2048](https://github.com/opensandbox-group/OpenSandbox/pull/2048) [#2045](https://github.com/opensandbox-group/OpenSandbox/pull/2045)), restructure the server, operator, execd, and node-agent architecture pages around verified design decisions with redrawn diagrams ([#2058](https://github.com/opensandbox-group/OpenSandbox/pull/2058) [#2064](https://github.com/opensandbox-group/OpenSandbox/pull/2064) [#2069](https://github.com/opensandbox-group/OpenSandbox/pull/2069) [#2137](https://github.com/opensandbox-group/OpenSandbox/pull/2137)), add an interactive fast-sandbox integration architecture diagram ([#2034](https://github.com/opensandbox-group/OpenSandbox/pull/2034) [#2127](https://github.com/opensandbox-group/OpenSandbox/pull/2127)), document execd implementation-compatibility boundaries ([#2050](https://github.com/opensandbox-group/OpenSandbox/pull/2050)), multi-runtime Kubernetes deployments ([#1684](https://github.com/opensandbox-group/OpenSandbox/pull/1684)), rclone volume mounts ([#2071](https://github.com/opensandbox-group/OpenSandbox/pull/2071)), snapshot durability after abnormal termination ([#2111](https://github.com/opensandbox-group/OpenSandbox/pull/2111)), sandbox expiration semantics ([#2087](https://github.com/opensandbox-group/OpenSandbox/pull/2087)), and `apply_patch` in sandboxes ([#2110](https://github.com/opensandbox-group/OpenSandbox/pull/2110)), add GitHub Copilot CLI, DeerFlow, and scheduled pool-resize examples ([#2053](https://github.com/opensandbox-group/OpenSandbox/pull/2053) [#2011](https://github.com/opensandbox-group/OpenSandbox/pull/2011) [#2141](https://github.com/opensandbox-group/OpenSandbox/pull/2141)), sharpen the README intro ([#1960](https://github.com/opensandbox-group/OpenSandbox/pull/1960)), repair links broken by the docs restructure ([#1957](https://github.com/opensandbox-group/OpenSandbox/pull/1957)), mark OSEP-0016 as implemented ([#1955](https://github.com/opensandbox-group/OpenSandbox/pull/1955)), remove the unmaintained NullClaw example ([#2016](https://github.com/opensandbox-group/OpenSandbox/pull/2016)), pin the Compose example to a release image with the proxy fixes ([#2073](https://github.com/opensandbox-group/OpenSandbox/pull/2073)), and refresh the roadmap ([#2135](https://github.com/opensandbox-group/OpenSandbox/pull/2135))
- Security/dependency bumps: fast-uri, undici, and containerd CVEs ([#2057](https://github.com/opensandbox-group/OpenSandbox/pull/2057)), PyJWT (critical), oauthlib, brace-expansion, and fast-uri ([#2102](https://github.com/opensandbox-group/OpenSandbox/pull/2102)), and urllib3, source-map-js, and vue ([#2117](https://github.com/opensandbox-group/OpenSandbox/pull/2117))
- node-agent/CI: add a nightly full-stack log-collection e2e on Kind proving real sandbox stdout reaches the file sink and finalizes on deletion ([#2143](https://github.com/opensandbox-group/OpenSandbox/pull/2143)), narrow the fast-sandbox integration trigger scope ([#2054](https://github.com/opensandbox-group/OpenSandbox/pull/2054)), and harden the integration scripts' error handling so subshell failures can't tear down the shared environment ([#2068](https://github.com/opensandbox-group/OpenSandbox/pull/2068))
- Fast-sandbox tooling: add a self-hosted KVM integration-test workflow ([#1978](https://github.com/opensandbox-group/OpenSandbox/pull/1978) [#1985](https://github.com/opensandbox-group/OpenSandbox/pull/1985)), a helper that provisions preallocated reflink-XFS state disks for Firecracker ([#1995](https://github.com/opensandbox-group/OpenSandbox/pull/1995)), a realistic golden-image test workload ([#1983](https://github.com/opensandbox-group/OpenSandbox/pull/1983)), and a reproducible Kubernetes rootfs resume benchmark ([#2113](https://github.com/opensandbox-group/OpenSandbox/pull/2113))
- Tests and housekeeping: cover upstream-proxy compatibility against real mitmdump with Vault/proxy credential isolation ([#2043](https://github.com/opensandbox-group/OpenSandbox/pull/2043)) and Authorization on streamed uploads ([#1940](https://github.com/opensandbox-group/OpenSandbox/pull/1940)); harden the Python pool-lifecycle stress tests ([#2026](https://github.com/opensandbox-group/OpenSandbox/pull/2026) [#2144](https://github.com/opensandbox-group/OpenSandbox/pull/2144)) and fix task-manager test races ([#2060](https://github.com/opensandbox-group/OpenSandbox/pull/2060) [#2061](https://github.com/opensandbox-group/OpenSandbox/pull/2061)); make the PauseResume e2e status tamper work on pre-1.24 kubectl ([#2085](https://github.com/opensandbox-group/OpenSandbox/pull/2085)); sweep low-value and duplicate tests across the Go and Python suites with no production changes ([#2126](https://github.com/opensandbox-group/OpenSandbox/pull/2126)); apply a zero-behavior-change node-agent cleanup ([#2140](https://github.com/opensandbox-group/OpenSandbox/pull/2140)) and remove dead CLI code ([#2018](https://github.com/opensandbox-group/OpenSandbox/pull/2018)); drop the unused `.pre-commit-config.yaml` ([#2049](https://github.com/opensandbox-group/OpenSandbox/pull/2049)); fix a dead docs link ([#2118](https://github.com/opensandbox-group/OpenSandbox/pull/2118)) and a test license-header owner ([#1976](https://github.com/opensandbox-group/OpenSandbox/pull/1976)); and prepare and pin the `1.1.1-rc.1` pre-release ([#2035](https://github.com/opensandbox-group/OpenSandbox/pull/2035) [#2042](https://github.com/opensandbox-group/OpenSandbox/pull/2042))
- release: bump platform version to `1.1.1` across charts and image references
## Upgrade & Compatibility
- The `1.1.0` server package on PyPI is broken at import time and cannot be replaced (PyPI is immutable) — upgrade to this line; see [#1959](https://github.com/opensandbox-group/OpenSandbox/pull/1959)
- Behavior change: the HTTP proxy maps backend read/write timeouts to 504 and mid-response failures to 502 with typed error codes instead of a generic 500; SDK default retry configs differ for the new 504 — the Go SDK's `DefaultRetryConfig` retries 504 like 502/503, while Python's default retries 502/503 only ([#2084](https://github.com/opensandbox-group/OpenSandbox/pull/2084))
- Behavior change: children left behind by a finished background command keep running after it exits, matching the foreground path; cancellation and timeouts still kill the group ([#2074](https://github.com/opensandbox-group/OpenSandbox/pull/2074))
- Behavior change: snapshot creation on k8s/fsb submits the runtime object before persisting and recovery resubmits inline; polling clients no longer observe a spurious permanent `Failed` ([#2098](https://github.com/opensandbox-group/OpenSandbox/pull/2098))
- Behavior change: background command result collection in Go, Kotlin, and C# returns on startup acknowledgement and no longer infers exit code 0 — query command status for the eventual outcome ([#1825](https://github.com/opensandbox-group/OpenSandbox/pull/1825))
- Behavior change: in multi-tenant mode, another tenant's labeled sandboxes in a shared namespace now resolve as 404; unlabeled legacy sandboxes stay visible until expiry ([#1973](https://github.com/opensandbox-group/OpenSandbox/pull/1973))
- Chart: the `base` chart now creates the shared `fastSandbox.namespaces.system` namespace by default — set `fastSandbox.namespaces.createSystem=false` if you manage it externally ([#2044](https://github.com/opensandbox-group/OpenSandbox/pull/2044)); the ingress gateway is required on Kubernetes deployments and must be installed before the server, and fast-sandbox mode requires a secure-access key ring at render time ([#2047](https://github.com/opensandbox-group/OpenSandbox/pull/2047) [#2048](https://github.com/opensandbox-group/OpenSandbox/pull/2048))
- Fast-sandbox operators: restores never boot a kernel and direct boot requires an explicit operator `kernelPath` pin ([#2028](https://github.com/opensandbox-group/OpenSandbox/pull/2028)); the Firecracker runtime now requires XFS with reflink at startup — use the provided reflink-XFS state-disk helper on nodes that lack it ([#2123](https://github.com/opensandbox-group/OpenSandbox/pull/2123)); the vendored CRD drops the removed `boxlite` runtime enum ([#2145](https://github.com/opensandbox-group/OpenSandbox/pull/2145)); the integration environment reads `RUSTFS_*`/`RC_IMAGE` instead of `MINIO_*`/`MC_IMAGE` with no legacy alias ([#2009](https://github.com/opensandbox-group/OpenSandbox/pull/2009))
- Images: `opensandbox/<component>:release-1.1.1` (all three registries)
- Packages: server / CLI / SDKs all at `1.1.1`
- Charts: render from this tag (`helm template ./manifests/charts/opensandbox`)
- Kubernetes: supported range v1.21 – v1.34 (charts declare `kubeVersion: ">=1.21.1-0"`)
- Skew: server ↔ CLI/SDK same line supported; ±1 minor warns
## 👥 Contributors
Thanks to these contributors ❤️
- @Coder-Sang
- @GodBlf
- @Gujiassh
- @Harbor404
- @Pangjiping
- @Spground
- @SuperSgdk
- @TuGou-a
- @YxinMiracle
- @acodercat
- @alahaiyo
- @comqx
- @cwj2001
- @dcaminos
- @drakeo338
- @gau1991
- @hittyt
- @hpliStartAgain
- @JasonBuildAI
- @jianpingpei
- @jiawen7777
- @jwx0925
- @ju123123
- @kinfey
- @kittimzhe
- @lorenzozanee
- @lux-liang
- @mengdehong
- @MincongZhou
- @mpu
- @ninan-nn
- @riversiderig-serves
- @ruirui6946
- @skyser2003
- @y4ney
## Artifacts
- BOM: [docs/releases/1.1.1.yaml](./1.1.1.yaml)
- Images: `opensandbox/<component>:release-1.1.1` (Docker Hub / GHCR / ACR)
- Packages: PyPI ×5, npm ×2, Maven Central ×5, NuGet ×2 — all at `1.1.1`
- Go module: `github.com/alibaba/OpenSandbox/sdks/sandbox/go@v1.1.1`
## Installation
```bash
# Platform (Kubernetes) — render the chart at this tag and apply
git clone https://github.com/opensandbox-group/OpenSandbox
cd OpenSandbox
git checkout release-1.1.1
helm dependency build manifests/charts/opensandbox # package file:// sub-charts (not committed)
# Before first install, configure the server API key and enable the ingress
# gateway (required on Kubernetes; the bare render disables it, and the server
# refuses to start with an empty api_key) — see the deployment guide:
# https://open-sandbox.ai/deployment/
helm template ./manifests/charts/opensandbox | kubectl apply -f -
# or point your GitOps platform (Argo / Flux) at the repo path + tag
# SDKs
pip install opensandbox==1.1.1 # Python
npm install @alibaba-group/opensandbox@1.1.1 # JavaScript
# Kotlin/JVM: implementation("com.alibaba.opensandbox:sandbox:1.1.1")
dotnet add package Alibaba.OpenSandbox --version 1.1.1
go get github.com/alibaba/OpenSandbox/sdks/sandbox/go@v1.1.1
# Run the server locally
uvx opensandbox-server==1.1.1
```
Verify what you installed against the BOM: see
[Release Verification](https://open-sandbox.ai/community/release-verification).
Related Repositories
public-apis/public-apis★ 491,131
A collective list of free APIs
NousResearch/hermes-agent★ 255,909
The agent that grows with you
yt-dlp/yt-dlp★ 200,005
A feature-rich command-line audio/video downloader
microsoft/markitdown★ 191,483
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPT★ 187,700
AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters.