The checked-out payload
A pull_request_target workflow that checks out PR content hands the author’s code your OIDC token and your runner. The exploit is a one-line workflow edit away.
Galactic Outpost is the admission, idempotency, and authority boundary between GitHub pull requests and sandboxed AI review. It admits the event, mints the identity, caps the spend, brokers a single-use read lease, and validates every byte of returned evidence before a human sees a finding. There is no checkout on the runner, no GitHub write API, and no token downstream.
REVIEW-ONLY PILOT · 158 LOCAL TESTS PASS · NOTHING HAS RUN LIVE
The model is rarely the dangerous part of an AI reviewer. The checkout, the write token, and the rendering that teams bolt on around it are.
A pull_request_target workflow that checks out PR content hands the author’s code your OIDC token and your runner. The exploit is a one-line workflow edit away.
Webhook redelivery, a reopened PR, an Actions rerun — naive bots dispatch again each time. You pay twice and race yourself.
A bot that comments needs a write scope. A write scope in a prompt-injectable system is a lateral-movement kit with a friendly avatar.
Model output pasted into comments, checks, or ::workflow-commands is attacker-reachable markup executed with your bot’s authority.
Outpost’s answer is a perimeter rather than a prompt. The runner never checks out PR content, nothing holds a GitHub write scope, and no reusable token exists to steal, because none of that was ever installed.
Everything Outpost enforces hangs off two small, verifiable objects: a task identity that makes retries converge, and a read lease that makes access expire.
Identity is derived from the event, not generated at dispatch:
Duplicate delivery and Actions reruns reuse the same dispatch. A different head SHA is deliberately a different task.
The sandbox’s only path to repository content — and it barely qualifies as access:
Intent persists to SQLite before the network call. While dispatch_pending, the workflow re-POSTs the identity-equivalent event; after the 180-second dispatch claim expires, the durable intent is reclaimed and the identical key reissued. Ambiguity reconciles by reissuing the identical key, never by minting a new task. The same key with different material input gets a 409 conflict.
pull_request_target is dangerous when the job checks out pull-request content. Outpost keeps the workflow file on the protected default branch and gives the job no way to touch PR content.
A contract test rejects forbidden primitives in the template itself, and the threat model states the residual: this path is safe only while it never checks out or executes PR content. A test fails if the template ever gains such a step. There is no hosted CI, so the local suite is that gate.
Every stage is derived from durable state, so duplicate deliveries, reruns, and crashed processes land on the same execution. The status vocabulary is five words.
PR event, trusted base. opened / synchronize / reopened fires the trusted-base workflow; the runner parses $GITHUB_EVENT_PATH only.
Tailnet identity, metadata in. SHA-pinned Tailscale action, workload identity federation, one POST of normalized PR metadata. GITHUB_TOKEN has no repository API scope.
Admit, quota, persist. Repository ID and owner/name allow-list, approved base ref, approved head-ref prefix, head repo = base repo; atomic active + rolling-hour quotas; immutable intent to SQLite; lease issued.
Idempotent dispatch. One POST with the deterministic key; the first sc: workflow ID and first non-null run ID are bound, and drift is rejected forever after.
Attested sandbox review, on the StarColony side and not yet built. The design has the sandbox prove run, workflow, and attempt identity, redeem the lease, review base_sha..head_sha read-only with default-deny egress, and route inference through LiteLLM on a run-scoped key.
Validate everything, fail closed. Every evidence artifact fetched by content digest; size, digest, and media type verified; every repository-task-result/v2 invariant enforced.
A job summary, and only a job summary. Escaped, bounded findings to GITHUB_STEP_SUMMARY; the job fails on error / critical. No comments, no checks, no statuses.
None of these is enforced by a prompt. Each is a server-side check with a test in the local suite.
Repository content never supplies policy.
Retries converge; they don’t multiply.
Spend is capped before the task exists.
Access is a ticket, not a credential.
Absence is never success.
Retries beyond the first attempt are not exposed in the pilot. The requirement for when they are: maxima only decrease, allow-lists only shrink, deny-lists only grow. policy_digest is already immutable per task.
Outpost accepts exactly one result shape, repository-task-result/v2, and rejects everything else. Open a row to read the evaluation.
Model output is untrusted data end to end: schema-validated, byte-bounded, control characters rejected, unnormalized paths rejected, Markdown escaped — never shell source, never a GitHub expression, never a workflow command.
These are requirements with contract tests, not configuration defaults, except where a row says otherwise.
Never executes PR content on the runner. No checkout, fetch, download, import, build, test, source, or execution of pull-request content — and the contract suite proves the template contains no such step.
Never calls a GitHub write API. No PR reviews, no inline comments, no commit statuses, no check runs. The renderer has no write path to invoke.
Never hands StarColony a GitHub token. No Actions GITHUB_TOKEN, no Tailscale credential, no write token — by requirement, not configuration.
Never lets a patch masquerade as a review. Forbidden fields or a nonzero workspace change count, and Outpost rejects the result as invalid_repository_task_result.
Never treats absence as success. Missing evidence, missing cleanup, or an unknown status all become failed, never an empty “clean” review.
Never puts a reusable credential in the sandbox. No source-control write credential, no raw provider key; the pilot redeems to an anonymous HTTPS clone descriptor.
Never lets repository content steer the system. Policy, prompts, budgets, tool grants, adapter selection, callback URLs, egress rules — none can come from repo content; model output can change none of them.
Never bypasses LiteLLM. A result reporting any other inference gateway is invalid.
Never widens a grant on retry. A requirement not yet exercised, since retries are not exposed in the pilot. policy_digest is immutable per task today.
Never exposes dispatch to the sandbox. Separate control and broker listeners. The broker has no task-start or status route, so a compromised sandbox cannot fabricate events or spend budget. Which routes sandbox egress can reach at all is set on the StarColony side and is a live hold point.
What a prompt-injected model is designed to reach: the repo clone, LiteLLM, one lease-redemption endpoint, and the scoped evidence store. No GitHub API, no public internet, no credentials. That egress rule lives in StarColony and the tailnet, and it has not been exercised live.
Galactic Outpost is a review-only pilot built contract-first. Present tense on this page describes the contract. Here is what the local suite proves, what has been built since, and what is held.
The review is advisory. It does not approve or merge code; it writes one job summary, and the job’s pass/fail, which your branch protection may or may not enforce, is its only signal.
The pilot is one approved public synthetic repository. No forks, no private repos, no arbitrary branches.
The local suite proves Outpost’s side of the contract. The other side is StarColony’s, and StarColony has not built the repository-task workflow, the evidence API, or attestation introspection yet. Nothing has run live.
Outpost is a reference build and a dogfood tool today, run by one operator against one synthetic repository. If you want AI review on your pull requests with the authority questions settled first, we would like to hear what your repositories look like.
A conversation about your repositories and our hold points. No signup exists yet.