Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
93 lines
5.2 KiB
Markdown
93 lines
5.2 KiB
Markdown
# Bind native exec delivery to its reviewed recipient
|
|
|
|
SECRETS-WP-0009-T03. Implemented 2026-09-10. This constrains delivery; it is not
|
|
an approval or proof of native credential access.
|
|
|
|
Previously `exec` consumed approval for a catalog/action/field, then accepted an
|
|
arbitrary child command and copied the invoking engine's full environment. The
|
|
factory recipient is now a pinned metered owner outside the sandbox. A different
|
|
command or inherited engine credential would violate that boundary.
|
|
|
|
Catalog `delivery_config.exec_owner` is optional for existing lanes. The Claude
|
|
factory lane explicitly requires it and currently declares `status: pending`,
|
|
`owner` and `reason`. Pending means no exec: refusal precedes approval consumption,
|
|
backend opening and secret retrieval. Routing stays unready even if custody exists.
|
|
|
|
A reviewed binding uses exactly these keys:
|
|
|
|
| Key | Required content |
|
|
| --- | --- |
|
|
| `status` | `configured`; this describes configuration, not authorization |
|
|
| `owner` | Named trusted recipient |
|
|
| `command` | Exact argv; absolute executable, no caller-selected additional arguments |
|
|
| `cwd` | Exact private owner directory |
|
|
| `environment` | Complete non-secret environment; no inheritance from the engine |
|
|
| `files` | Absolute path → `{sha256: <64 lowercase hex>, private: <boolean>}` |
|
|
|
|
The executable and every absolute file argument require pins. Include the exact
|
|
owner JSON and all immutable files it references, such as the spend-policy and
|
|
accepted profile/descriptor configuration. Mutable ledgers are private state,
|
|
not immutable file pins. The runtime owner retains whole-artifact and operational
|
|
profile verification; hashing an interpreter alone does not verify its packages.
|
|
|
|
File checks refuse symlinks, nonregular inputs, untrusted owners, group/world
|
|
writable paths and ancestors, changed bytes and exposed private inputs. Root-owned
|
|
sticky temporary ancestors are allowed for contained proof. The working directory
|
|
is private. The engine and configured owner UID remain trusted: this does not
|
|
protect against that same trusted UID replacing files between checks and launch.
|
|
Runtime and native service admission must preserve this trust boundary.
|
|
|
|
Only exec-env is allowed with this binding. The child receives the fixed environment
|
|
plus the selected declared field; loader overrides and engine/provider auth
|
|
variables cannot be supplied as fixed environment configuration. No values belong
|
|
in the catalog. Queue/service credentials, if needed by the owner, require their
|
|
separate admitted custody path. Child stdin is closed; stdout/stderr retain the
|
|
existing value redactor. An arbitrary encoding by a malicious recipient is not
|
|
made safe by redaction; the recipient itself must be trusted and admitted.
|
|
|
|
SHA-256 of the complete canonical binding is carried as
|
|
`context.exec_owner_sha256` on the `exec` CheckRequest. The existing producer digest
|
|
and approval join bind it without introducing another decision type. Changing
|
|
command, file pins, environment, cwd or owner changes the request and requires new
|
|
exact-action approval. Local checks run before approval/backend, again before
|
|
retrieval, and after retrieval before launch; the admitted digest must still match.
|
|
Configured bindings still pass existing approval, consume, lane-state and scoped
|
|
backend checks. Other actions and lanes without this opt-in retain their contracts.
|
|
|
|
## Factory activation input
|
|
|
|
Use the installed artifact and paths in
|
|
`prj-helixforge-factory/evidence/2026-09-10-runtime-placement.json`. The intended argv:
|
|
|
|
```text
|
|
<protected-runtime>/bin/python3 -I -B -m rein_aharness.cli metered-once --owner-config <private-owner-config>
|
|
```
|
|
|
|
Do not use the rolling CLI alias or a persistent claim loop. Complete and pin the
|
|
private owner configuration, profile and spend inputs under HFACT-WP-0001-T01/T04;
|
|
bind the required worker environment explicitly. Then review the MessagesOwner
|
|
holder under this task and the existing native action/reader gates. The provider
|
|
key stays in the metered owner; the workload receives the opaque local route token.
|
|
The historical sandbox-helper child-key route is not this holder admission.
|
|
|
|
## Verification
|
|
|
|
The full suite passed 361 tests, including a real child with a synthetic key,
|
|
fixed environment, closed stdin, redaction and substituted/config-changed refusal.
|
|
The disposable integration exercise passed 18 checks using the pinned KeyCape
|
|
image, actual Approval Engine and compiled Flex Auth, including five new owner
|
|
checks: substituted argv refusal before consume/backend, changed-environment
|
|
replay refusal, consume-before-backend, isolated child environment and preserved
|
|
recipient digest. OpenBao and recipient are fixtures in this exercise. The
|
|
historical combined operator identity is a synthetic test issuer fixture, not a
|
|
request to restore CCR-2026-0020 or evidence of real human approval.
|
|
|
|
```bash
|
|
uv run --extra dev --with 'PyJWT[crypto]>=2.7,<3' python tools/exercise_approval_identity.py \
|
|
--keycape-source ../key-cape --approval-engine-source ../approval-engine \
|
|
--flex-auth-source ../flex-auth --exec-owner --receipt /tmp/<new-receipt>.json
|
|
```
|
|
|
|
Receipt: `docs/evidence/2026-09-10-exec-owner-approval-exercise.json`.
|
|
Native custody, exact operator group/file delivery, real human/audit/service path,
|
|
accepted factory configuration and paid execution remain open.
|