Code from someone else's pull request should not see your credentials or your network. This recipe runs an outside contributor's PR (jshttp/cookie #289, pinned to its head commit) in a sandbox and narrows what the sandbox can reach before any of that code runs:

  1. The fetch gets the credential in that one command's environment, as GIT_CONFIG_COUNT, GIT_CONFIG_KEY_0 and GIT_CONFIG_VALUE_0. git reads them as runtime config: the value is not written to .git/config and, unlike git -c, is in no process's argv. The recipe sends a random canary in place of a token, then looks for it.
  2. POST /v1/sandboxes/{id}/egress narrows the sandbox to registry.npmjs.org, and npm ci --ignore-scripts installs the lockfile's packages without running their install scripts. github.com is now refused, by name and by address.
  3. The same call narrows egress to deny, and the PR's tests run with no network at all.
  4. Outside the sandbox, the io.b3os/deps-dev/get-version action looks up each direct dependency at the version the lockfile pins, and the model turns the test result and the dependency facts into a three-sentence note. The recipe reads the lockfile right after the install, before the tests: the PR's code could rewrite it.

The sandbox has no api grant, so code inside it cannot call B3OS. The sandbox starts with public egress for the fetch: fetching runs no code from the PR, and git runs no hooks from the repository it fetches.

Check

Verified 2026-11-01: this recipe's last run passed against https://beta-api.b3os.org, label live-recorded (recorded from production), from commit cebfa5fc. The recipe harness runs it again, and a failed run takes this page out of the cookbook.

Run it

bash
API=https://beta-api.b3os.orgAUTH="Authorization: Bearer $B3OS_API_KEY"HEAD=f1d76f52b68f9161cc2b6d3093f151e774c6748brun() { jq -n --arg cmd "$1" '{cmd: $cmd, timeout_ms: 60000}' \ | curl -s "$API/v1/sandboxes/$SBX/exec" -H "$AUTH" -H "Content-Type: application/json" -d @- \ | jq -r '.stdout, "exit \(.exit_code)"'; }SBX=$(curl -s "$API/v1/sandboxes" -H "$AUTH" -H "Content-Type: application/json" \ -d '{"template": "base", "vcpu": 2, "memory_mib": 2048, "timeout_s": 600}' | jq -r .id)# The credential only in this command's env (a token would go where the canary is).jq -n --arg cmd "git init -q pr && cd pr && git remote add origin https://github.com/jshttp/cookie.git && git fetch -q --depth 1 origin $HEAD && git checkout -q --detach FETCH_HEAD" \ '{cmd: $cmd, timeout_ms: 60000, env: {GIT_CONFIG_COUNT: "1", GIT_CONFIG_KEY_0: "http.extraHeader", GIT_CONFIG_VALUE_0: "X-Canary: replace-me"}}' \ | curl -s "$API/v1/sandboxes/$SBX/exec" -H "$AUTH" -H "Content-Type: application/json" -d @- | jq .exit_codecurl -s "$API/v1/sandboxes/$SBX/egress" -H "$AUTH" -H "Content-Type: application/json" \ -d '{"mode": "allowlist", "allow": ["registry.npmjs.org"]}' | jq .egressrun "cd pr && npm_config_cache=/tmp/npm npm ci --ignore-scripts --no-audit --no-fund 2>&1 | grep '^added'"curl -s "$API/v1/sandboxes/$SBX/egress" -H "$AUTH" -H "Content-Type: application/json" \ -d '{"mode": "deny"}' | jq .egressrun "cd pr && NO_COLOR=1 npm_config_cache=/tmp/npm npx --no-install vitest run 2>&1 | grep -E 'Test Files|Tests '"run "cd pr && git config --get-all http.extraheader || echo 'no http.extraheader in the clone'"curl -s "$API/v1/actions/call" -H "$AUTH" -H "Content-Type: application/json" \ -d '{"ref": "io.b3os/deps-dev/get-version@1", "input": {"system": "npm", "name": "vitest", "version": "4.1.9"}}' \ | jq '.output | {licenses, advisories}'curl -s -X DELETE "$API/v1/sandboxes/$SBX" -H "$AUTH" | jq .status

What the run checks, besides the tests passing: the canary is in neither the clone's git config, nor any file in the guest (a search of the whole filesystem as root), nor the next command's environment, nor the API's answers about the sandbox (GET /v1/sandboxes/{id}, its logs and its request log). A canary is not a token: a real token stays valid until it expires, whoever fetched with it, so give the fetch the narrowest token there is, for one repository and read only.

Owner: Docs. Products: Docs, Sandboxes, Actions and triggers, Infer.

Output of the last green run

bash
$ node run.mjs# exit 0

The outputs this recipe publishes (its recipe.json publish.outputs), with workspace identifiers redacted. The run's stdout, stderr and other outputs are not published.

Captured 2026-11-01 from commit cebfa5fc , label live-recorded (recorded from production). Case recipes/untrusted-pr-tests .

Ask a question... ⌘I