Guide 02 / Untrusted code · 2026-08-21

Run the pull request before you trust the pull request

A diff shows the final tree. It cannot show what an install script attempted, what the branch contacted, or whether the tests ever ran. A detached box lets you find out without giving the branch your machine.

Boundary first. A pull-request box gets its own repository, drops the inherited origin, and cannot be applied or rebased into the parent. External code leaves only through export.
A malicious repository runs inside an h5i box with no host API key, default-deny network, and workspace-only filesystem access
The assumption is deliberately hostile: repository hooks and package scripts may execute. Their authority is the box's authority, not the developer account's.

A pull request is executable input long before you run its application. Package manifests select install hooks. Build files select plugins. Test fixtures feed parsers. Editor and agent configuration can alter startup behavior. “I only want to read the diff” stops being true the moment a realistic review builds the branch.

1. Create a detached box

repository root
$ h5i box create review-1234 --pr 1234 --profile agent-claude
$ h5i box status review-1234

--pr accepts a number, #number, or pull-request URL. h5i fetches the head on the host, pins it, then gives the box an independent repository with no inherited network remote.

The host-side fetch uses access you already have, then ends. The box receives Git objects and a pinned revision—not the SSH agent, GitHub token, or a remote it can push to. This split lets private repositories be reviewed without turning repository access into a standing capability inside untrusted code.

2. Read the boundary before the branch

Confirm three things in status: the box is detached, the requested isolation tier is enforced, and network access is no broader than the review needs. Do this before running a package manager; install hooks are code execution.

host
$ h5i box capabilities review-1234 --json
$ h5i box secrets review-1234

secrets shows declared grants and dry-run resolution, never secret values. A review that needs no authenticated service should have no grant.

Also verify that origin is absent inside the box. Dropping the remote is not a complete network control, but it removes a ready-made authenticated handle and makes the detached shape obvious to tools that inspect Git configuration.

3. Build and test inside the box

host, then box
$ h5i box shell review-1234
box$ npm ci
box$ npm test
box$ npm run dev
# In another host terminal: h5i box view review-1234
box$ exit

Use the project's real install and test commands. If it is a web change, start the server in the same session and drive the isolated browser. The app, browser, and agent then agree on what localhost means.

Test the claim the pull request makes, not merely the command its author suggests. A dependency change deserves an install from the pinned lockfile. A migration deserves a disposable database. A browser fix deserves console and failed-request evidence, not only a screenshot. The box makes destructive setup cheap enough to reproduce instead of infer.

4. Review evidence in the right order

host
$ h5i box export review-1234 --out ./review-1234
$ less ./review-1234/report.md
$ less ./review-1234/patch.diff

Read the report before the prose supplied by the author or agent:

  1. Denied egress attempts. Unexpected destinations deserve an explanation first.
  2. Commands and exit codes. Check that the meaningful tests ran.
  3. Browser errors and failed requests. A visually plausible page can still be broken.
  4. The patch. Now read the code with the execution history beside it.
  5. The proposal. Treat it as testimony, not evidence.
Absence needs a label. The microvm network stack can enforce an allowlist without producing a per-request egress tally. A missing summary at that tier does not mean no connection was attempted.

5. Keep the bundle, discard the box

host
$ h5i box rm review-1234
$ h5i box gc

You can apply an accepted patch wherever you choose with git apply --3way. h5i refuses box apply for this detached box by design.

Signals that deserve a second look

SignalBenign explanationReview question
Denied telemetry hostA dependency phones home by defaultDoes this dependency belong in the change?
Test exits zero unusually fastCache hit or focused test targetDid the meaningful suite actually execute?
Generated file outside expected treeBuild tooling creates metadataIs it required, reproducible, and safe to apply?
Browser has no captured evidenceNo browser was startedWas the user-visible behavior exercised at all?
Agent proposal omits a failed runThe agent retried and summarized the final stateWhat changed between failure and success?

None of these is a verdict. They are attention routing. A useful report helps a reviewer spend time where the branch's behavior diverged from its story.

Why detached is stronger than “remember not to merge”

The command surface itself refuses apply and rebase for external sources. That turns repository origin into a type-level lifecycle decision. An agent or hurried reviewer cannot accidentally use the convenient local landing path on code that arrived from somewhere else.

Export remains available because review still needs an outcome. Its patch passes path validation before leaving: symlink escapes, nested Git repositories, and agent-introduced gitlinks are rejected. You can inspect the bundle, move it elsewhere, or discard it with no mutation to the parent repository.

Common review failures

If the pull-request ref cannot be fetched, use the full URL and confirm the host—not the box—has repository access. If dependency installation is denied, add the exact registry hosts to a review profile rather than switching to host networking. If the application needs a service, declare or start it inside the same session so the review does not silently depend on a host database.

Reference

Questions that come up

Do GitHub credentials enter the box?
No. The host fetches the pull-request head. The detached box receives the code, not the host's SSH key, GitHub token, or inherited origin remote.
Why not check out the branch in a normal worktree?
A worktree separates checkouts, not authority. Package scripts would still run with your user's filesystem, network, sockets, and credentials unless another boundary removes them.
Can an agent perform the review?
Yes. Run it inside the box and ask it to build, test, inspect the browser, and write findings. The execution record remains separate from the agent's self-report.
Next guide

Write the boundary down

Turn filesystem, network, and resource assumptions into a checked-in profile.

Review behavior, not just text

Give untrusted code somewhere safe to execute before you decide whether to take it.