Skip to content

v0.5.11

Choose a tag to compare

@github-actions github-actions released this 24 Oct 01:53
· 5 commits to main since this release

Release v0.5.11

⚠ BREAKING: verification commands are now sandboxed

A verification command no longer runs as an ordinary subprocess. It runs as a node process under Node 22
--permission, with filesystem access scoped to the workspace and the OS temp directory, core
prototypes frozen, sockets and fetch severed, the environment scrubbed, and no shell — the command
is tokenised and spawned with shell: false against the host's own node binary.

What that means for a contract command:

  • Prohibited: node --test and node -t — refused with REFUSED_UNSANDBOXED_RUNNER. The runner
    forks a child process per test file, the permission model blocks that fork, and granting it would
    reopen the execution vector the sandbox closes.
  • Prohibited: relative or shadow binaries (./node, temp/node.exe) — refused with
    REFUSED_SHADOW_RUNTIME. The spawn always uses process.execPath.
  • Prohibited: shell chaining and redirection (&&, ;, |, >, <, backticks, $() — refused
    with REFUSED_SHELL_OPERATORS.
  • Prohibited: non-node runtimes (python, sh, bash, pwsh) — refused with
    REFUSED_UNSANDBOXED_RUNTIME. The sandbox reaches node processes only.
  • Required: run the contract directly as node <script>, assert its invariants, and exit 0 on pass
    or non-zero on failure.

If your verification command was node --test tests/…, it will fail on first run after upgrading. The
refusal names the direct form of your own command.


Security and hardening

  • Execution boundary. Verification is pinned to process.execPath; the preflight freezes Object,
    Array and Function prototypes, severs net.Socket.prototype.connect and fetch, and removes
    non-essential environment variables. Measured against four hostile leaves that all executed before this
    release.
  • Role and attestation integrity. A delegation whose contextFiles include its declared contracts is
    refused before dispatch (REFUSED_CONTRACT_AS_CONTEXT). The promotion gate reads staged index bytes
    (git show :<path>) instead of the working tree, and fails closed when git diff fails.
  • Egress and DLP. The outbound scanner now covers tool results — every role, nested output blocks,
    stdout and serialised objects — not just prompt text. Declarations mode is an allowlist: .d.ts,
    mappable source served as its declaration, and prose; raw .py, .sh, .json and .yaml reads are
    refused (REFUSED_NON_DECLARATION_READ), and glob reads are refused (REFUSED_WILDCARD_READ).

Compatibility

The tool surface, verdict vocabulary and attestation schema are unchanged. The breaking item is the
verification command contract above.

Full Changelog: v0.5.10...v0.5.11