You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement sealed probes: a lightweight way for the primary AWF agent to run agent-authored Python against one configured private repository without learning the repository contents or observing the computation.
The agent invokes a fixed local sealed-probe CLI through a generated skill. The CLI forwards a narrow request to a trusted offline probe proxy. The proxy gives each invocation a fresh writable copy of exactly one pre-staged repository, launches the script in a hardened no-network sandbox, validates a closed JSON result schema, and returns one of exactly four symbols: three caller-defined outcomes or fixed ERROR.
This replaces the heavier isolated-agent-group approach for v1. No secondary LLM, MCP session, mailbox, or long-lived child agent is needed.
Security and information-flow goal
A sealed probe is:
Lightweight: Python code, not another agent or LLM.
Deterministic and auditable: the exact script accessing private data is known.
Sandboxed: no network, credentials, host access, Docker control, primary workspace, or other repositories.
Sealed: the caller cannot observe repository contents, stdout/stderr, files, diffs, errors, exit status, or diagnostics. It observes only one of four predeclared symbols.
The three non-error symbols are known before execution. Selecting among them plus ERROR conveys at most log2(4) = 2 content bits per invocation. Completion timing remains an acknowledged v1 side channel. A bounded per-run invocation count is required to limit cumulative disclosure.
Configuration
Add a top-level sealedProbes block to the AWF standard configuration. It is a subsystem like apiProxy, not a primary-sandbox setting under security.
The block must behave identically from a file and AWF stdin config (--config -). No direct CLI configuration flags are required in v1.
Semantics
Absent or enabled: false: do not stage repositories, start the proxy, mount its socket, expose the skill, or change existing behavior.
privateRepos is the complete allowlist and each value is exactly normalized owner/repo.
Credentials come from the environment/existing resolution system, never config.
Credentials exist only in a separate trusted staging phase. They must never enter the agent, probe proxy, probe sandbox, arguments, logs, mounts, or /proc-visible state.
runtime selects the probe runtime independently of the primary agent runtime. Fail closed if unavailable; never downgrade.
maxInvocations bounds cumulative leakage/resource use. Exhaustion returns canonical ERROR without launching a probe.
Validation/preflight
Fail before the primary agent starts when:
enabled but privateRepos is empty;
a repo is unsafe, duplicated, or contains URL syntax, credentials, wildcard, query, fragment, or traversal;
runtime is unsupported/unavailable;
timeout, memory, or invocation limit is invalid/unbounded;
interpreter is unsupported;
staging credentials cannot be resolved;
any required seed snapshot cannot be produced and verified.
JSON Schema validates shape; credential/runtime/snapshot availability is a fail-fast preflight.
Agent-facing interface
Expose one generated sealed_probe skill, implemented through a fixed CLI wrapper following the existing agent-local gh wrapper to trusted cli-proxy pattern.
The skill lists configured repositories, instructs the agent to choose exactly three bounded outcome names, and explains the script/output contract. It is guidance, not a security boundary.
Local CLI
Install /usr/local/bin/sealed-probe only when enabled.
Accept only --repo, exactly three --outcome values, and bounded script bytes on stdin.
Do not accept executable, image, command, cwd, environment, URL, ref, path, mount, volume, socket, runtime, timeout, or credentials.
Forward a bounded/versioned request over a dedicated AWF Unix socket. Only that capability enters the agent.
Print exactly one canonical JSON result, no diagnostics, and use one exit status for all outcomes/failures (exit 0 recommended).
If the proxy is unavailable or invalid, emit canonical {"result":"ERROR"} locally with identical formatting/status and no stderr.
Do not copy cli-proxy's generic /exec API. The probe API must not permit arbitrary execution.
Do not accept arbitrary JSON Schema. V1 permits no free values, arrays, nested objects, optional/additional fields, $ref, combinators, regex, annotations, or caller-selected error symbol.
Script contract
The script may read/modify /probe/repo, then writes one JSON object:
importjsonfrompathlibimportPathrepo=Path("/probe/repo")
# Deterministic computation; repo may be modified locally.Path("/probe/out").write_text(json.dumps({"result": "YES"}))
The proxy:
reads /probe/out with a strict cap;
rejects malformed UTF-8/JSON, duplicate keys, trailing data, non-object roots, missing/extra fields, and values outside the enum;
validates the closed schema;
never returns script bytes directly;
canonically reserializes valid output itself.
Valid response example:
{"result":"YES"}
The failure response is always:
{"result":"ERROR"}
A script-written canonical ERROR is equivalent to proxy failure and adds no symbol.
Failure closure
Every failure returns identical canonical ERROR with the same transport shape and CLI status:
invalid request, repo, outcomes, or exhausted budget;
missing staging data or unavailable proxy/transport/runtime;
missing, malformed, oversized, duplicate-key, or nonconformant output;
cleanup failure or internal exception.
Do not expose status classes, error bodies/headers, exception categories, exit codes, sizes, commit metadata, or diagnostics. Protected audit logs may retain bounded details but are never agent/probe-visible.
Offline staging
Nothing in the probe proxy or probe sandbox may access the internet.
Before proxy/agent readiness, a separate trusted AWF setup phase:
resolves read-only credentials;
materializes one immutable seed per configured repo;
records its commit in protected audit state;
strips credential-bearing config/remotes/helpers, hooks, alternates, worktree links, and external references;
makes and verifies each seed read-only;
removes staging processes/containers and credentials before readiness.
Prefer pre-provisioned local clones. There is no proxy fallback clone/fetch.
Seeds use run-unique isolated storage. Do not share object stores, alternates, worktrees, writable parents, or credential metadata. Safest v1 submodule policy is reject/omit.
Trusted probe proxy
Implement a deterministic trusted host process or tightly controlled sidecar that:
has no DNS, Squid, awf-ext, mcpg, api-proxy, cli-proxy, host-network, or public-network path;
is reachable only through the narrow dedicated socket/API;
receives only repo selector, three outcomes, and script;
maps normalized repo IDs through an AWF-generated static map to opaque seeds;
never accepts caller paths, URLs, refs, mounts, images, commands, env, or runtime flags;
Use descriptor-relative/openat2-style beneath/no-follow access where needed. Reject symlink, hardlink, device, FIFO, socket, alternate, worktree, submodule, and parent escapes.
The trusted proxy may coordinate all seeds, but no probe receives their parent or multiple repos.
Per-invocation writable repository
For every valid request:
Resolve exactly one immutable seed.
Create a fresh private writable full copy or proven-isolated copy-on-write snapshot.
Mount only that copy at /probe/repo:rw.
Give it a distinct mount namespace, tmpfs/output, PIDs, identity, and limits.
Destroy it after validation, timeout, cancellation, or teardown.
The script may create, edit, delete, stage, and commit inside its assigned copy. Mutations are ephemeral: no diff, commit, artifact, file, metadata, or safe-output intent is returned/persisted.
A full copy is the safe fallback. Copy-on-write requires proof that data, metadata, object stores, and writes cannot cross repos/invocations.
Probe sandbox
Construct a fresh root containing only:
minimal fixed Python runtime/rootfs;
submitted script at a fixed read-only path;
selected writable repo at /probe/repo;
private tmpfs/output containing /probe/out.
The sandbox:
has network: none or runtime-equivalent isolation;
cannot reach public internet, DNS, host gateway, bridge peers, proxies, or external loopback services;
uses a read-only root except explicit repo/tmpfs mounts;
never mounts proxy/Docker sockets, primary workspace/home, credentials, host /tmp, seed parent, another repo, or prior invocation;
runs non-root with all capabilities dropped and no-new-privileges;
applies a minimal Python seccomp profile;
enforces wall-clock, memory, CPU, PID, file-size, inode, and storage limits;
supports Docker, gVisor, and sbx without downgrade;
contains no package manager/install path.
chroot may be defense in depth, but is not the security boundary. Chroot into the constructed minimal rootfs, not directly into a Git checkout.
AWF integration points
Config/schema/types
src/config-file.ts: top-level type.
docs/awf-config.schema.json: canonical schema.
src/awf-config-schema.json: regenerate; do not hand-diverge.
src/config-mapper.ts, src/commands/build-config.ts, and WrapperConfig: map stdin/file config without CLI flags.
docs/awf-config-spec.md: processing, validation, credentials, CLI/skill, result, and security semantics.
Lifecycle/services
Add trusted staging and proxy/launcher components.
Reuse optional-service patterns in src/services/optional-services.ts and src/compose-generator.ts where appropriate.
Inject only the dedicated socket and fixed CLI into the agent.
Gate agent startup on successful staging and proxy readiness after staging credentials/resources are removed.
Summary
Implement sealed probes: a lightweight way for the primary AWF agent to run agent-authored Python against one configured private repository without learning the repository contents or observing the computation.
The agent invokes a fixed local
sealed-probeCLI through a generated skill. The CLI forwards a narrow request to a trusted offline probe proxy. The proxy gives each invocation a fresh writable copy of exactly one pre-staged repository, launches the script in a hardened no-network sandbox, validates a closed JSON result schema, and returns one of exactly four symbols: three caller-defined outcomes or fixedERROR.This replaces the heavier isolated-agent-group approach for v1. No secondary LLM, MCP session, mailbox, or long-lived child agent is needed.
Security and information-flow goal
A sealed probe is:
The three non-error symbols are known before execution. Selecting among them plus
ERRORconveys at mostlog2(4) = 2content bits per invocation. Completion timing remains an acknowledged v1 side channel. A bounded per-run invocation count is required to limit cumulative disclosure.Configuration
Add a top-level
sealedProbesblock to the AWF standard configuration. It is a subsystem likeapiProxy, not a primary-sandbox setting undersecurity.The block must behave identically from a file and AWF stdin config (
--config -). No direct CLI configuration flags are required in v1.Semantics
enabled: false: do not stage repositories, start the proxy, mount its socket, expose the skill, or change existing behavior.privateReposis the complete allowlist and each value is exactly normalizedowner/repo./proc-visible state.runtimeselects the probe runtime independently of the primary agent runtime. Fail closed if unavailable; never downgrade.maxInvocationsbounds cumulative leakage/resource use. Exhaustion returns canonicalERRORwithout launching a probe.Validation/preflight
Fail before the primary agent starts when:
privateReposis empty;JSON Schema validates shape; credential/runtime/snapshot availability is a fail-fast preflight.
Agent-facing interface
Expose one generated
sealed_probeskill, implemented through a fixed CLI wrapper following the existing agent-localghwrapper to trusted cli-proxy pattern.sealed-probe \ --repo owner/repo \ --outcome YES \ --outcome NO \ --outcome UNKNOWN \ < probe.pyThe skill lists configured repositories, instructs the agent to choose exactly three bounded outcome names, and explains the script/output contract. It is guidance, not a security boundary.
Local CLI
Install
/usr/local/bin/sealed-probeonly when enabled.--repo, exactly three--outcomevalues, and bounded script bytes on stdin.0recommended).{"result":"ERROR"}locally with identical formatting/status and no stderr.Do not copy cli-proxy's generic
/execAPI. The probe API must not permit arbitrary execution.Request and result contract
Conceptual request:
{ "privateRepo": "owner/repo", "outcomes": ["YES", "NO", "UNKNOWN"], "script": "..." }Before creating a repo copy or launching a sandbox, validate:
ERROR;Invalid requests return canonical
ERRORwithout launching.Proxy-constructed schema
For outcomes
A,B, andC, construct exactly:{ "type": "object", "properties": { "result": { "type": "string", "enum": ["A", "B", "C", "ERROR"] } }, "required": ["result"], "additionalProperties": false }Do not accept arbitrary JSON Schema. V1 permits no free values, arrays, nested objects, optional/additional fields,
$ref, combinators, regex, annotations, or caller-selected error symbol.Script contract
The script may read/modify
/probe/repo, then writes one JSON object:The proxy:
/probe/outwith a strict cap;Valid response example:
{"result":"YES"}The failure response is always:
{"result":"ERROR"}A script-written canonical
ERRORis equivalent to proxy failure and adds no symbol.Failure closure
Every failure returns identical canonical
ERRORwith the same transport shape and CLI status:Do not expose status classes, error bodies/headers, exception categories, exit codes, sizes, commit metadata, or diagnostics. Protected audit logs may retain bounded details but are never agent/probe-visible.
Offline staging
Nothing in the probe proxy or probe sandbox may access the internet.
Before proxy/agent readiness, a separate trusted AWF setup phase:
Prefer pre-provisioned local clones. There is no proxy fallback clone/fetch.
Seeds use run-unique isolated storage. Do not share object stores, alternates, worktrees, writable parents, or credential metadata. Safest v1 submodule policy is reject/omit.
Trusted probe proxy
Implement a deterministic trusted host process or tightly controlled sidecar that:
awf-ext, mcpg, api-proxy, cli-proxy, host-network, or public-network path;Use descriptor-relative/openat2-style beneath/no-follow access where needed. Reject symlink, hardlink, device, FIFO, socket, alternate, worktree, submodule, and parent escapes.
The trusted proxy may coordinate all seeds, but no probe receives their parent or multiple repos.
Per-invocation writable repository
For every valid request:
/probe/repo:rw.The script may create, edit, delete, stage, and commit inside its assigned copy. Mutations are ephemeral: no diff, commit, artifact, file, metadata, or safe-output intent is returned/persisted.
A full copy is the safe fallback. Copy-on-write requires proof that data, metadata, object stores, and writes cannot cross repos/invocations.
Probe sandbox
Construct a fresh root containing only:
/probe/repo;/probe/out.The sandbox:
network: noneor runtime-equivalent isolation;/tmp, seed parent, another repo, or prior invocation;no-new-privileges;chrootmay be defense in depth, but is not the security boundary. Chroot into the constructed minimal rootfs, not directly into a Git checkout.AWF integration points
Config/schema/types
src/config-file.ts: top-level type.docs/awf-config.schema.json: canonical schema.src/awf-config-schema.json: regenerate; do not hand-diverge.src/config-mapper.ts,src/commands/build-config.ts, andWrapperConfig: map stdin/file config without CLI flags.docs/awf-config-spec.md: processing, validation, credentials, CLI/skill, result, and security semantics.Lifecycle/services
src/services/optional-services.tsandsrc/compose-generator.tswhere appropriate.runAgentCommand; the primary agent controls the AWF job exit.Agent image/skill
containers/agent/gh-cli-proxy-wrapper.sh, with the narrower API.Required tests
Config/unit
Lifecycle/service
Security integration
Using local fixture repos where possible:
ERRORis reserved.ERROR, uniform exit status, and no stderr.Acceptance criteria
ERROR; all failures are identicalERRORwith uniform status/no stderr.Out of scope for v1
gh, GitHub MCP, or probe/proxy internet;