RunnableLog in
An amber untrusted stream being filtered before joining a protected execution pathTrust boundariesHostile Input

AUGUST 31, 2026 · RUNNABLE TEAM

Fork Pull Requests Are Hostile Input

Engineering

A pull request from a fork is useful code from an untrusted authority. The contributor controls the branch, the files, and the commands those files may cause a build to execute. That is enough power to treat the event as hostile input even when the contributor is acting in good faith.

The CI policy cannot begin after checkout. It must decide which workflow definition is trusted, which credentials exist, and which outputs can cross into later jobs before the first untrusted command runs.

The base repository owns the execution plan

A RESULT YOU CAN ACT ON
RESULT 01Compatiblepilot in parallel
RESULT 02Review requirednamed assumption
×RESULT 03Unsupportedkeep on current CI
04 / BOUNDARY No score, no guesswork, and no silent fallback.

For a same-repository pull request, Runnable can use the workflow revision from the proposed branch. For a fork, it uses the base revision for workflow discovery and planning.

That distinction prevents a contributor from editing the workflow file that decides whether secrets, permissions, environments, or deployment steps are available. The proposed code can be tested without allowing it to rewrite the policy that surrounds the test.

Secrets disappear; write becomes read

Fork jobs receive no customer secrets from organization, repository, or environment scope. The absence is structural: the assignment builder does not query secret rows for a fork run.

Repository permissions requested as write are downgraded to read before the installation token is minted. OIDC issuance is denied outright, because a federated cloud credential would bypass the value of withholding stored secrets.

Artifacts are data from the untrusted side

A file produced by a fork job is not made trustworthy by calling it an artifact. Later jobs must treat archives, generated code, test reports, and workspace handoffs as attacker-controlled inputs unless a trusted boundary explicitly validates them.

Runnable keeps internal workspace handoffs scoped to declared dependencies and separate from ordinary artifact discovery. That limits accidental reach, but the receiving workflow still owns the semantic decision to consume untrusted output.

A useful fork build can still be narrow

JOB-SCOPED BY DEFAULT
short-lived credential
runner / job-7f2clean Linux x64
masked output
03 / ISOLATION Create for one job. Destroy at the terminal state.

Read-only checkout, deterministic dependency installation, compilation, linting, and tests can provide meaningful feedback without deployment authority. The clean runner and egress policy reduce persistence and lateral movement, while the base workflow controls exactly what executes.

Maintainers can move privileged work to a trusted post-merge or manually approved path. That is slower than pretending every pull request is internal—and much faster than rotating every credential after one was exfiltrated.

  • Trust the base planFork code cannot redefine the workflow authority that evaluates it.
  • Remove ambient authorityNo customer secrets, no OIDC, and requested writes become reads.
  • Validate outputsArtifacts and generated files remain untrusted until a trusted step proves otherwise.

RUN THE EVIDENCE

Your workflows are already runnable.

Scan one before you move it. The report names what runs, what needs review, and what stays put.

Check a workflow