A runner label chooses a machine. It does not authorize a repository action.
GitHub Actions can route a job to a self-hosted runner. A label answers one useful question:
Which machine is eligible to receive this job?
It does not answer the question that matters for a heavier repository action:
Is this exact publish, migration, deployment, or other non-routine task authorized to run now?
Those are different boundaries. A workflow must not be able to create its own approval merely by asking for a more privileged runner.
Ota's first signed crossing-authority carrier is designed around that separation. The repository declares the governed lane. The workflow asks GitHub to schedule a protected runner. A separately managed authority source decides whether the exact lane may cross its boundary. Ota verifies that decision immediately before effects start and emits a fresh transaction record after it does.
We pressure-tested that model on a pre-provisioned Linux/x64 VPS runner. One live authorization executed and produced a retained archive. Three invalid-authority cases refused before the task ran. The result is not a general approval system. It is concrete evidence for a deliberately bounded carrier.
The flow under pressure
Repository contract selects governed lane
|
Workflow requests a protected runner label
|
Protected runner invokes `ota run ... --grant <id>`
|
Ota verifies fixed authority state and exact semantic scope
|
One fresh crossing transaction begins
|
Selected task runs, then receipt and archive bind admission to outcome
Each layer retains its own job:
| Layer | Owns | Does not own |
|---|---|---|
| Repository contract | Which lane requires a crossing | Trust keys, grants, bundle paths, or revocations |
| GitHub workflow | Scheduling, checkout, credentials, and provider policy | Authority issuance |
| Authority provisioner | Signed bundle, revocation, sequence state, and signing key | Repository task selection |
| Ota on the runner | Admission, scope verification, transaction, receipt, and archive | Issuing its own authority |
That separation is the product value. GitHub still owns scheduling and platform controls. Ota adds repository-specific governance: a way to bind independently issued authority to the complete action the repository is about to execute.
What we tested
The pressure workflow verified the exact administrator-installed Ota binary against a root-owned full-commit and SHA-256 manifest before it checked authority. It then ran Ota's read-only hardening diagnostic as the unprivileged job user. Required observations had to pass: Linux/x64, non-root execution, no declared Docker host or common Docker socket, and valid fixed trust, bundle, and sequence records.
The four hosted scenarios ran against the same merged workflow revision:
| Scenario | Result | What the evidence proves |
|---|---|---|
| Live grant | Passed | Exact-scope admission created a completed crossing transaction; the retained artifact contains the verified receipt archive and valid receipt history. |
| Expired grant | Passed | Dry-run and real execution refused with crossing_grant_expired; before/after checkout manifests matched. |
| Revoked grant | Passed | Dry-run and real execution refused with crossing_grant_revoked; before/after checkout manifests matched. |
| Out-of-scope grant | Passed | Dry-run and real execution refused with crossing_grant_out_of_scope; before/after checkout manifests matched. |
The refusal cases are important. A green validate result or a rejected command alone would not establish the boundary. The pressure workflow retained typed refusal JSON, the human refusal output, and complete checkout manifests before and after both dry-run and real refusal. The selected scaffold
task never started.
What Ota verified before the live task ran
The repository contract names only an authority identifier:
governance:
crossing_authority:
authority_id: platform-release-authority
It does not contain the signing key, bundle location, trust-store path, or revocation state. Those live outside the checkout at fixed protected system paths:
/etc/ota/crossing-authorities.json
/var/lib/ota/crossing-authority.json
/var/lib/ota/crossing-authority-sequence.json
Before Ota admits the selected lane, the first carrier verifies the fixed authority binding and the signed bundle, then checks the grant's exact contract identity, complete selected execution scope, crossing family, classification, actor posture, expiry, revocation, and sequence/high-water state.
The scope is not a friendly task name. Changing dependencies, hooks, task effects, target platform, or execution selection changes the semantic scope identity. A standing grant for yesterday's publish lane cannot silently authorize a changed closure that happens to keep the same label.
Why the archive matters
A successful run needs more than an approval-looking log line.
For the live scenario, Ota created a fresh crossing transaction before the governed scaffold action, recorded its terminal success, and retained the receipt archive in the hosted artifact. Receipt history revalidated that archive rather than merely reporting that a file existed.
That gives a reviewer a linked chain:
declared governed lane
-> verified signed authority and semantic scope
-> fresh crossing transaction
-> selected task outcome
-> archive that re-derives the recorded scope
This is the gap Ota is intended to close. A provider can tell you that a workflow ran. Ota can preserve which repository action crossed a declared boundary, what authority admitted it, and what happened afterward.
What this does not prove
The correct claim is intentionally narrow:
The authority files were protected from the current Ota process under the observed filesystem
boundary, and Ota verified the selected crossing against them before work started.
The carrier reports this as current_process_filesystem_guarded. It does not prove:
- provider-attested isolation between the job and an administrator;
- absence of every possible escalation path, mount alias, metadata credential, or host-control endpoint;
- a verified human, CI, or platform identity;
- one-use authority or atomic broker consumption;
- repository-global safety, application correctness, or prevention of raw-shell bypasses.
The runner's local inspection is diagnostic evidence. It cannot independently attest the whole provider boundary. A signed image or a protected label alone would not change that fact.
What came next
The VPS matrix closed the pressure gate for Ota's first signed-file carrier. V11.7 later added the separate broker-backed carrier, available in Ota v1.6.26 and later, and completed its bounded OSS
slice.
The completed broker path binds launcher attestation to the job, consumes a short-lived one-use work-unit lease atomically, retains terminal cleanup and archive evidence, and proves recovery on an independently administered hardened launcher. Provider attestation remains optional stronger hardening rather than a V11.7 completion requirement.
The useful and honest statement remains narrow: Ota can verify separately issued, exact-scope authority on a protected runner and produce transaction-bound evidence of execution or refusal. It does not call that provider isolation, verified human identity, raw-shell prevention, or a complete enterprise control plane.
For the operator layout and verification procedure, see the canonical Prebound Crossing Authority reference.
Originally posted here: https://ota.run/blog/a-protected-runner-is-not-an-approval-system-4q8m
Top comments (0)