Releases: Pyronewbic/Sluice
Release list
sluice v0.10.0
Hardening, supply-chain, and fleet-operations release: fleet-wide egress auditing, a preventive
egress byte cap, pinned/verified replay, and a broad sweep of fail-closed and portability fixes.
All local, self-hosted, no telemetry.
Added
- Fleet-wide egress audit —
sluice egress --verify --all/--export --allwalk every box's append-only audit log and hash chain with the engine down (no daemon needed). (#67) SLUICE_EGRESS_HARD_CAP_BYTES=N— a preventive in-box egress cap (viaxt_quota) that kills an over-cap transfer mid-flight; fails closed when the kernel module is absent. (#67)- Per-host egress budget (
SLUICE_EGRESS_MAX_BYTES) metered on what left the box; the direct-IPSLUICE_ALLOW_IPSlane is now metered before the ESTABLISHED accept. (#67) sluice lock --pinwrites a committablesluice.pinreplay manifest (base pinned by digest + exact versions);SLUICE_PIN=1performs a verified pinned replay build. (#67)- Versioned JSON contracts (
sluice.version/doctor/boxv1);ls --jsonembedslast_receipt; in-box DNS-tunnel audit and bump upload controls. (#67) sluice egressgains a summary header ("N reached, N blocked, <bytes>"), an audit-log footer nudging--export/--verify, andegress --verify --jsonfor CI integrity gating;egress --jsongains"window":"boot". (#43)- Denied raw-IP (direct CONNECT/URL) requests are now ledgered in the receipt and
egress --json, alongside an always-onfw_droppedtotal. (#72) - New managed-policy directives:
max-allow-ips-bytes,max-hard-cap-bytes,strict-unknown,require-signed-base. (#76, #81) sluice doctorreadout: trailing verdict line, always-on hardening row, git-tracked-mask warning, report-only managed-policy preflight (doctor --jsonaddspolicy.effective_allowlist+policy.refusals),SLUICE_MOUNTSvalidation, and rootless-podman host-limit checks. (#48, #46, #45, #72, #71)NOTICEfile + README Acknowledgments crediting the upstream base image, its packages, and the test framework. (#72)- Four capability demo GIFs across the README and docs: a malicious npm dependency contained at import, an exfil killed mid-flight by the hard cap, a fleet audit with the daemon down, and an org policy refusing a metadata-SSRF config.
Changed
- The credential prelaunch hook now runs before every session (run / shell / rebuild, warm boxes included) so short-lived tokens re-mint each run instead of expiring with the container. (#72)
sluice lsALLOW count reads the live allowlist instead of the stale build-time label. (#72)- A config-less first run now stops after scaffolding instead of building + running the detected command under
SLUICE_YES=1. (#72) sluice diffis now gated by the managed policy and config validators like every other box bring-up path. (#76)sluice learndrops a laundering host underforbid-laundering/SLUICE_STRICT_LAUNDERINGinstead of warn-and-keeping it onto the hot-reloaded allowlist. (#76)SLUICE_ALLOW_IPSrejects a hostname entry with a clear message (hostnames belong inSLUICE_ALLOW_DOMAINS) instead of silently sinking it to the DNS dead-end. (#79)sluice lock --scanexit code is a documented contract (0clean /3gate-tripped /4scanner-failed), normalized across grype and trivy;--check/--diff/--enforcereject unknown flags. (#44)- The SBOM (
lock --sbom/--pin) enumerates the full global-npm dependency closure (was top-level only), so a CVE in a transitive npm dep now reaches--scan. (#77) - A signed base image is resolved to a content digest once;
cosign verifyand the DockerfileFROMpin the same digest (closes a same-tag-republish gap on the:latestsigned-base path). (#77) -b <box> doctorresolves the engine leniently, reporting instead of dying on a badSLUICE_RUNTIME. (#55)- Agent presets:
geminidrops the inertGOOGLE_API_KEY,qwenforwardsDASHSCOPE_API_KEY, and stale/dead allowlist hosts were pruned fromclaude/amp. (#55, #65, #49)
Fixed
- Portability (build-breaking): hashing routes through
_sha256(preferssha256sum, falls back toshasum -a 256), unbricking every build/run on Alpine,*-slim, and most CI images whereshasumis absent. (#78) - Data-loss:
sluice apply/diffexclude masked paths from the overlay write-back, so a masked.envno longer truncates the real host secret to 0 bytes. (#75) - Denied raw-IP requests are matched with an interval-free regex, fixing silent under-reporting on
mawkbuilds without--re-interval(e.g. Debian). (#73) - Rootless podman keeps host repo ownership via
--userns=keep-id; podman'slocalhost/image-name prefix is stripped sols/ps/prune/receipt slugs resolve. (#69, #71) - Fail-closed audit reads:
ls --egress,learn, anddoctorreport unknown (?/null) instead of a false all-clear when the in-box audit log can't be read. (#61, #59) set -faround unquoted config word-splits in the launcher and the in-container entrypoint, so a glob char in aSLUICE_*value can't pathname-expand; wildcard allowlist entries stay literal during policy evaluation. (#54, #52, #45)sluice learnno longer aborts when the run-offset file is missing — it falls back to the full log. (#53)SLUICE_SECCOMP=auditwrites its generated profile to the stable per-box state dir instead of leaking one/tmpfile per run. (#54)- The overlay-workspace seed writes its apply-safety manifest only on a fully successful copy, so a partial seed can't delete untouched host files on
apply. (#54) egress --verifyhandles an unterminated final record and skips blank lines (full hash-chain coverage) and rejects typo'd flags. (#42, #55)install.shre-pointsorigintoSLUICE_REPOon a re-run and quotes a spaced$HOMEfpath dir. (#55)lock:LC_ALL=Csorts kill phantom cross-locale drift; same-version rebuilds and multi-version packages classify correctly;--sbom/--jsonstdout is byte-clean on a cold build. (#44, #42)
Security
- Closed egress allowlist fail-opens: the leading-dot wildcard form (
.storage.googleapis.com) thatsluice learnwrites now matchesforbid-laundering/ strict-laundering, andSLUICE_ALLOW_IPSrefuses masks broader than/8(was only/0). (#51) sluice initsingle-quotes every repo-derived value written into the generated config, closing an RCE via a hostile Procfile / make-target /package.jsonscript. (#50)- Closed five managed-policy trust-boundary bypasses:
deny-iprefuses anSLUICE_ALLOW_IPSentry that overlaps the denied CIDR in either direction (supernet included, e.g. a/24over a/32metadata deny); a malformed ceiling arg is a hard refusal, not a fail-open no-op. (#76) sluice learnfails closed on an unreachable managed policy, aligning it with the run path.
Internal
CI / supply-chain hardening (advisory actionlint / zizmor / gitleaks lanes, checksum-pinned grype + container-structure-test installs, SHA-pinned action bumps), a lane-membership drop-guard and a preflight ship-readiness workflow, added regression coverage, docs-drift fixes, and a consolidated Terraform Linux test-runner VM (sluice-vm.sh, Kata opt-in). (#57, #60, #62, #63, #64, #65, #66, #68, #70, #74, #80, #81)
Install
brew install Pyronewbic/tap/sluice # or: brew upgrade sluice
# or: curl -fsSL https://raw.githubusercontent.com/Pyronewbic/Sluice/main/install.sh | shFull changelog: v0.9.0...v0.10.0
v0.9.0
sluice v0.9.0
A security and auditability release. Egress is now evidence-grade - every run leaves a tamper-evident, hash-chained receipt you can export and verify - on top of a deny-capable central policy and ten adversarially-verified hardening fixes. Plus in-repo secret masking, five more detected stacks, and a rebuilt doc + demo set. Same default-deny egress firewall, non-root box, and project-dir-only mount as before.
Added
- Evidence-grade egress receipts - every run appends to a host-side, append-only, hash-chained log;
sluice egress --verifywalks the chain (red on any edit, reorder, or drop) and--exportships it to a SIEM. See docs/operations.md. - Central egress policy - a deny-capable, ceiling-setting org policy (
/etc/sluice/policy.conf): a deny is final and local config cannot loosen it. A URL-fetched policy is signature-authenticated. See docs/policy.md. SLUICE_MASK- shadow in-repo secrets (.env*, keys) from the box: the path still exists, the contents read empty.sluice doctorflags secret-looking files no pattern covers.SLUICE_OVERLAY_DIRS- give platform-specific dirs (e.g.node_modules) a box-local volume instead of leaking host artifacts into the box.- Five more stacks -
sluice initnow detects Java, PHP, .NET, Elixir, and Dart (11 total), with build-time dependency prefetch (Go/Rust/Ruby/Python) for tighter runtime egress andinit --updateto refresh detection without clobbering your edits.
Changed
- Hardened against 10 adversarially-verified findings - a forged-Host plaintext-HTTP exfil path, a uid-1000-writable
PATHprivilege escalation, a box-rewritten.gitcross-repo mount, a mixed-case DoH tunnel, and six more are closed; the egress byte-gate and in-box audit now fail closed. See THREAT_MODEL.md. sluiceruns quieter - the build transcript goes to a per-box log (tail replayed on failure), a multi-line run command is summarized on the plan line, and masked paths are counted rather than listed.- Supply chain - cosign verification is anchored to the signing-workflow identity, and
install.shpins to an exact commit and reports its sha. - Docs + demos rebuilt - a lean README front door plus topic guides (hardening, supply-chain, agents, configuration, operations), and a demo gallery regrouped around real user journeys.
Fixed
- The boot self-test always runs and proves every default-DROP rule (including the IPv6 stack) before the workload starts.
sluice applyno longer deletes host files created mid-session;learnapplies the DoH/laundering filter on the live-reload path;lockinventories pip--user/pipx sites, not just system pip.
Verify
Every release ships a deterministic source tarball, SHA256SUMS, and a cosign keyless signature bundle; the multi-arch base image is cosign-signed in GHCR. Verification steps are in SECURITY.md.
Full changelog: v0.8.0...v0.9.0
v0.8.0
sluice v0.8.0
A security-hardening release. Opt-in sandbox lockdown, a copy-on-write workspace mode, and tighter egress that closes DNS-based exfil tunnels - all on top of the same default-deny egress firewall, non-root box, and project-dir-only mount.
Added
- Hardened seccomp profile (opt-in) -
SLUICE_SECCOMP=hardenedruns the box under a tightened syscall filter. - Read-only rootfs (opt-in) -
SLUICE_READONLY_ROOT=1makes the container filesystem immutable. - Workspace overlay (opt-in) -
SLUICE_WORKSPACE=overlayruns against a throwaway copy of the repo; the agent's edits land in a scratch layer you review and apply. - Tighter default privileges - drop ALL Linux capabilities and add back only the boot-needed set, plus
no-new-privileges, resource bounds, and removal of in-box sudo. - DoH/DoT exfil block - DNS-over-HTTPS and DNS-over-TLS resolvers are refused even when their host is allowlisted, closing a covert egress tunnel.
- No-op run hint -
sluice runwarns whenSLUICE_RUN_CMDis a no-op so a silent success isn't mistaken for a hang.
Changed
- Test suite migrated to bats-core with a container-structure-test gate (asserts base-image invariants: no sudo, uid 1000, firewall packages). CI runs the gate on Docker and rootless Podman.
Verify
Every release ships a deterministic source tarball, SHA256SUMS, and a cosign keyless signature bundle. Verification steps are in SECURITY.md.
Full changelog: v0.7.0...v0.8.0
v0.7.0
Coding agents, supply-chain verification, and stronger isolation. Run coding agents one-shot inside the sandbox, gate dependencies with vuln scans and a strict lockfile, and optionally give each box its own kernel.
Added
Coding agents
sluice agent <name> [args]runs an agent in the sandbox; trailing args run it one-shot (e.g.sluice agent claude -p "fix the failing test"). No name lists every preset with its auth variable and whether that variable is set on your host.- Two new presets,
qwenandcrush, bringing the set to nine (claude, codex, gemini, aider, cursor, opencode, amp, qwen, crush). - Pre-run auth check warns when a preset's API-key variable is unset, and a multi-agent guard points you to
git worktreewhen a directory is already wired to a different agent.
Supply chain
sluice lock --scanruns a host-side Grype or Trivy vulnerability scan of the box, with--fail-on <severity>to gate the build.sluice lock --enforcemakes the lockfile a strict gate (build fails on package drift). Inventory now covers cargo alongside apk/npm/pip/gem/go, and lockfiles export as CycloneDX or SPDX via--format.- Base-image SBOM attestation: the published GHCR base image ships a CycloneDX SBOM, cosign-signed keyless.
Isolation
SLUICE_RUNTIME=kataruns a box as an own-kernel micro-VM instead of a shared-kernel container, where available.
Control plane
sluice -b/--box <name>targets any box from outside its directory;sluice lsgained a posture/orphan dashboard;sluice rm/pruneremove boxes;version --jsonandlearnpublic-suffix wildcards round out scripting support.- Egress receipts now report per-host byte volume, and opt-in TLS interception (SSL-bump) is available for scoped deep inspection.
Changed
- Shell completions install automatically via Homebrew and
install.sh(bash + zsh).
Full changelog: v0.6.0...v0.7.0
v0.6.0
Multi-box visibility and machine-readable output. See every sandbox on your machine at a glance, get JSON from the inspection commands for scripting and CI, and point boxes at a central egress allowlist.
Added
sluice lslists every built box on this machine - name, status (running/stopped/built), stack, project path, and description - with the box matching your shell's directory marked. Derived from Docker; no extra state to manage.sluice egress [--json]prints what a box actually reached vs. what the firewall blocked - an audit record you can pipe to a file or a collector.--jsonoutput forsluice lsandsluice doctor- machine-readable box inventory and posture, for scripting and CI.SLUICE_DESC- an optional one-line box description, shown insluice lsandsluice doctor.SLUICE_POLICY_URLpoints a box at a central plain-text allowlist (any http/https/file URL), fetched on the host at run and merged into the box's egress policy. Additive and host-trusted: it can only add allowed hosts, never weaken the sandbox.
Changed
- README: a "What it looks like" section with real
sluice doctor/sluice lsoutput, status badges, and a one-line note that sluice runs entirely on your machine (the only network call it makes is an opt-out update check).
Full changelog: v0.5.0...v0.6.0
v0.5.0
sluice learn --audit - a one-shot, open-egress discovery pass for the egress allowlist.
sluice learn proposes the allowlist from what the firewall blocked, without ever opening egress. --audit covers the one case enforce-mode can't: trusted code whose fetcher aborts on the first blocked host. It runs your command once in a throwaway, credential-stripped container with egress open to all HTTP/HTTPS hosts, then proposes the full allowlist from every host it reached.
Added
sluice learn --auditrunsSLUICE_RUN_CMDonce with egress opened to all HTTP/HTTPS hosts, then proposes the allowlist from everything it reached. Loudly warned and confirm-gated; the audit container is ephemeral and torn down after the run. Enforce-modelearnstays the default.- Credential-stripped by design. The audit run forwards no
SLUICE_ENV, runs noSLUICE_PRELAUNCH, and mounts no persisted state dirs, so nothing sensitive can leave while egress is open. Non-HTTP ports and IPv6 stay default-DROP throughout. SeeTHREAT_MODEL.mdfor exactly what it opens and keeps closed.
Changed
- Slimmer README layout - documented as role-based top-level directories rather than a per-file tree.
Full changelog: v0.4.0...v0.5.0
v0.4.0
[0.4.0] - 2026-06-01
Added
- Supply-chain:
sluice lock- write a committable inventory of the built image (every apk + global npm package with version + digest);sluice updatere-resolves and relocks.sluice lock --checkis a CI drift gate (fails if the image differs fromsluice.lock);sluice lock --sbomemits a deterministic CycloneDX 1.5 SBOM for scanners. - Agent session persistence (
SLUICE_STATE_DIRS) - a coding agent's history, sessions, and auth survive a rebuild,sluice stop, or reboot, via a per-project host store. sluice learn --print- emit the proposed egress allowlist to stdout (review / CI).sluice learn --apply- write the allowlist and rebuild in one step.- Nix gallery example +
SLUICE_SETUP_ROOT_CMDS(a build-time root hook) - run a reproducible, pinned Nix toolchain inside a sluice, contained at runtime. SLUICE_ALLOW_IPSdatabase-egress demo - reach a fixed-IP, non-HTTP service (Postgres/Redis/MySQL) through the firewall's escape hatch.- Codex and Gemini agent presets verified through the harness - all seven presets are now cred-free verified.
- Update check in
sluice version- flags a newer release when one is available (SLUICE_NO_UPDATE_CHECK=1to disable).
Changed
sluice helpis grouped into sections (Common / Build & lifecycle / Inspect / Meta).test/verify-runtimes.shruns the runtime fixtures in parallel.- README: an "Updating sluice" section, plus gallery and command-surface docs. The CLI surface is pre-1.0 and may still change before 1.0.
Full changelog: v0.3.1...v0.4.0
v0.3.1
A patch release: the cursor agent preset was broken — now fixed and verified — plus a new agent-verification harness and a security-showcase demo.
Fixed
sluice agent cursorwas broken. The preset installed@cursor/cli, which 404s on npm — cursor-agent ships via Cursor's own install script, not npm. Switched to the script + a PATH symlink, and verified it installs and runs.
Added
- Agent-preset verification harness (
test/verify-agents.sh+ a manualverify-agents.yml). For each preset it builds the image and checks, with no credentials, that the CLI binary installs and runs, every declared API host is reachable through the proxy, a non-allowlisted host is blocked, and the auth env var is forwarded; the live authenticated round-trip is the only cred-gated step (auto-runs if the key is present, else skips). cursor, amp, and opencode are now verified cred-free; opencode's full live round-trip passes too. - A firewall/exfil demo (
examples/firewall.config.sh) — self-contained and non-server: it reaches an allowlisted host, then is blocked trying to exfiltrate a fake secret to a non-allowlisted host and to a raw IP, surfaced bysluice doctorand the at-exit hint. The threat model, runnable.
Changed
- Curated the demo gallery into a capability matrix — firewall / strudel / jupyter each show a different slice — and elevated the coding-agent section from a footnote. Trimmed the vite/next/fastapi starters (redundant with
sluice init, which scaffolds them) to an init pointer. - De-staled the strudel and jupyter demos (
/home/node→/home/sluice, after the sandbox user rename).
Full changelog: v0.3.0...v0.3.1
v0.3.0
sluice is a sandboxed, firewalled, non-root container for any project: drop a sluice.config.sh in a directory and run sluice. This release adds a signed base image, fixes a Linux egress bug for rotating-CDN hosts, and verifies rootless Podman.
Added
- Cosign-signed base image. The generic sandbox core (proxy, firewall, dnsmasq, non-root user) is now published to GHCR as a multi-arch (amd64 + arm64) image, keyless-signed with cosign (GitHub OIDC). Opt a project into building FROM it with
SLUICE_BASE_IMAGE=ghcr.io/pyronewbic/sluice-base:0.3.0instead of rebuilding the core locally —sluiceverifies the signature when cosign is installed (SLUICE_REQUIRE_SIGNED=1to make a missing/failed signature fatal). The image carries no private key: the squid splice cert is generated per-container at runtime. Local-from-core stays the default this release.
Fixed
- Egress to rotating-CDN hosts on Linux. HTTPS to allowlisted hosts on large rotating IP pools (Google/Akamai/Fastly — e.g.
proxy.golang.org,static.crates.io) could fail with an opaque TLS error. squid's transparent-intercept Host-forgery check was rejecting a legitimate host when the client and squid resolved its name to different pool IPs milliseconds apart. A small in-box dnsmasq cache now pins one IP set per session, so both agree and the connection splices through. (Surfaced on Linux only; macOS Docker Desktop's resolver masked it.) - Eliminated
rm: Permission deniedcleanup noise in the test harnesses (chown the mount back to the host uid before teardown).
Changed
- The non-root sandbox user is now
sluice(wasnode; uid unchanged at 1000). A/home/node→/home/sluicesymlink keeps existingSLUICE_MOUNTSworking. Node + npm remain in the base as the agent runtime. - Rootless Podman verified. The acceptance harness now probes rootless Podman in CI; the full egress matrix passes in an unprivileged user namespace, so the
route_localnet/disable_ipv6sysctls and in-netns iptables the proxy needs work rootless too (no rootful requirement). - Docs:
sluice doctor, the at-exit visible-egress hint, the--HEADdev stream, and running any language viaSLUICE_EXTRA_PKGS+SLUICE_RUN_CMD.
Full changelog: v0.2.0...v0.3.0
v0.2.0
Minor release: adds sluice doctor and visible egress denials, plus SLUICE_NAME, and tightens the agent allowlists.
Added
sluice doctor- one-shot health check: engine, config, image freshness, effective allowlist, auth env, and the hosts the proxy blocked this run. Self-contained, so it works in the broken states it diagnoses (no engine/config/image, container not running).- Visible egress denials - after a default
sluice/sluice agentrun, a one-line hint lists any not-yet-allowed hosts the proxy blocked (fires even on Ctrl-C), so a silent TLS error no longer hides what to allow. SLUICE_NAME- override the per-project image/container name (defaults to the directory basename).
Changed
- Agent allowlists scoped to each CLI's documented API-key hosts, dropping browser-only OAuth/sign-in hosts that can't complete headless.
- Example runtime projects moved to
test/fixtures(thesluice initscaffold supersedes them).
Fixed
- Claude Code v2.x connectivity: allow
platform.claude.com,claude.ai, andstatsig.com(feature flags).
Full changelog: v0.1.1...v0.2.0