fix: enforce sandbox execution boundary
Some checks failed
ci / validate (push) Has been cancelled

This commit is contained in:
tegwick 2026-08-21 10:40:29 +02:00
parent 1cd890d871
commit f773b5c101
19 changed files with 865 additions and 181 deletions

View file

@ -5,6 +5,16 @@ Acceptance task for both profiles: change one `README.md` status value from
used a separate temporary initialized repository and `profile.bwrap-local`.
No credential value, prompt transcript, or raw model output is recorded here.
> **Correction recorded 2026-08-21 (GLAS-WP-0005):** these runs proved profile
> resolution, rein dispatch, normalized evidence, commit detection, and
> sand-boxer lifecycle teardown. They did **not** prove that the rein process ran
> inside bwrap. The gateway passed the source checkout to the adapters and the
> adapters launched ordinary host subprocesses instead of entering the reported
> namespace. The commit and model results below remain valid execution facts;
> the earlier isolation implication is withdrawn. GLAS-WP-0005 changes the
> runtime to use only reachability-derived workspaces and transports and requires
> a new boundary proof.
## `harness.agent-dev-local@1.0.0`
- Result: succeeded.
@ -54,7 +64,8 @@ rotation.
Both explicit profiles resolved and dispatched distinct rein/model
constellations, completed the same semantic task with a real commit, returned
the common Glas evidence envelope, and destroyed their local sandboxes. No
the common Glas evidence envelope, and destroyed their local sandbox lifecycle
records. Per the correction above, this is not isolation evidence. No
alternative workload credential was borrowed.
Rollback for consumers is to repin to the last approved Glas profile. The old

View file

@ -35,12 +35,14 @@ enabled revision exists. Inline secrets and token-looking values are refused.
Use `glas-harness profiles` as the catalog/packaging validation command.
Catalog validation proves schema/compatibility, not host installation. An
execution host must install `glas-harness` with sand-boxer support and each rein
used by its enabled profiles. The Claude-backed rein also needs its documented
`rein-aharness[llm]`/sibling `llm-connect` adapter dependency. Missing runtime
dependencies surface as startup/execution failure evidence and still trigger
sandbox teardown.
Catalog validation proves schema/compatibility, not transport installation. An
execution host must install `glas-harness` with sand-boxer support and make each
selected rein plus its dependencies available *inside* the sandbox transport,
not merely on the host. Same-host bwrap execution enters the descriptor's
namespace; remote execution crosses its SSH endpoint. The Claude-backed rein
also needs its documented `rein-aharness[llm]`/sibling `llm-connect` adapter
dependency in that environment. Missing runtime dependencies fail closed at
session start and still trigger sandbox teardown.
## Consumer request

View file

@ -30,13 +30,15 @@ from the State Hub detail.
class Rein(ABC):
def start_session(
self, profile: HarnessProfile, inputs: dict[str, str], sandbox: SandboxHandle
) -> dict[str, str]: ...
) -> dict[str, Any]: ...
def dispatch_tool(
self, session: dict[str, str], tool_call: ToolCall
self, session: dict[str, Any], tool_call: ToolCall
) -> ToolResult: ...
def end_session(self, session: dict[str, str]) -> ExecutionSummary: ...
def end_session(self, session: dict[str, Any]) -> ExecutionSummary: ...
def cleanup_session(self, session: dict[str, Any]) -> None: ...
```
```text
@ -44,13 +46,24 @@ Glas rein sand-boxer
---- ---- ----------
resolve profile + rein descriptor
create sandbox ------------------------------------------> create
start_session(profile, inputs, handle) -> rein setup
dispatch_tool(session, call) -> inner loop
derive workspace + transport from handle
start_session(profile, inputs, handle) -> sandbox-local setup
dispatch_tool(session, call) -> inner loop across transport
end_session(session) -> normalized facts
cleanup_session(session) -> remove ephemeral task material
destroy sandbox -----------------------------------------> destroy
publish compact ExecutionEvidence
```
After sandbox creation, the caller's source checkout is no longer an execution
path. A same-host descriptor must contain `pid` plus `workspace_dir` and every
rein command is wrapped with `nsenter`; a remote descriptor must contain `ssh`
plus `remote_dir` and every command crosses SSH. Incomplete, mixed, or unknown
reachability refuses at session start. The transport also bounds the outer rein
subprocess with the profile timeout. A host must make the selected rein command
and its dependencies available inside that transport; host-only installation is
not treated as sandbox availability.
There is no production default rein. Direct `Rein` injection remains a narrow
library/test seam but still requires a valid profile so profile, sandbox,
model, tool policy, and evidence are explicit.
@ -86,8 +99,9 @@ The gateway returns evidence for every normal refusal/failure path:
- `teardown`.
Profile resolution happens before sandbox creation. Once a sandbox exists,
teardown is attempted on every path. `refused` means governed execution did not
proceed; `failed` means an attempted lifecycle did not complete successfully.
rein cleanup and sandbox teardown are attempted on every path. `refused` means
governed execution did not proceed; `failed` means an attempted lifecycle did
not complete successfully.
## Deliberate non-goals

View file

@ -36,3 +36,38 @@ description: |
commit b0600b25066731c6e1fc458409429f76a844f959, and sandbox 220482bc was
verified destroyed. The AppRole directory is now the code default.
```
## GLAS-IN-0002 — Provide executable sandbox runtime reachability
```yaml
id: GLAS-IN-0002
kind: intake
title: "Make bwrap reachability executable for governed Glas reins"
lane: red
status: todo
priority: high
owner: sand-boxer
repo: glas-harness
origin: residual
origin_ref: GLAS-WP-0005
description: |
GLAS-WP-0005 corrected the gateway so a rein command must execute through
the sand-boxer reachability descriptor and can no longer operate on the
caller's source checkout. The existing profile.bwrap-local environment does
not yet carry an executable rein runtime: ext.bwrap mounts /usr, /bin, /lib,
/lib64, and resolv.conf, while rein-aharness/rein-openweights and their
dependencies live outside those mounts. The open-weight profile also needs a
governed egress/credential-delivery answer rather than the current empty
network allow-list.
A 2026-08-21 managed-agent probe also found direct consumer nsenter denied on
the reported pid (IPC/UTS setns operation not permitted). Determine whether
sand-boxer should expose an owner-implemented exec operation instead of
requiring each consumer to call nsenter, and provide the runtime mount/image,
identity, and network contract needed by both local profiles. Do not restore
host-side execution as a workaround.
Done when a non-secret probe and one real rein command execute inside the
namespace, the source checkout is not visible/mutable, required egress is
explicit, and teardown removes the sandbox workspace.
```