Trust boundaries
What never crosses a boundary. Your source code, your Actions secrets, your artifacts and your job logs never reach the control plane — the runner talks to GitHub directly. Your cloud credential never reaches a runner machine. Airship holds no SSH key for your machines, and there is no inbound network path to them.What Airship stores
Never stored: source code, artifacts, build output, Actions secrets or
variables, job logs, any cloud credential in plaintext anywhere including
logs, or cache contents — those live in your bucket, in your account.
Validation errors are shaped so they cannot echo the value that failed: the
API’s error details carry a location and a message only.
The cloud credential
The sharpest edge of the design, so it gets the most rules.
What the credential can do is your choice, and it should be the minimum.
The least-privilege policies are on AWS,
Google Cloud and
Azure. On AWS the terminate permission can
be conditioned on Airship’s own tag, so the credential cannot destroy
anything Airship did not create.
Job isolation
The GitHub registration
Who may spend your money
Control plane surfaces
Sign-in is GitHub OAuth only. There is no password to leak and no local
account to brute-force.
The boot script
The script runs as root. Anything interpolated into it would be remote code execution on your machine if it could break its quoting, so nothing is interpolated without validation: the runner version, the registration, the control plane URL, the cache token and the Windows paths and account names all match strict patterns, andenv_vars travels base64 and is decoded on the
machine, so nothing in it is ever shell or PowerShell.
Variable names starting with GITHUB_, RUNNER_ or ACTIONS_ are refused: a
config file must not be able to change how the runner talks to GitHub.
Cache security
Known exposures
These follow from the model. None is a surprise, and each has a mitigation.1. The single-use registration travels in instance metadata
1. The single-use registration travels in instance metadata
Anyone in your cloud account who can read an instance’s metadata or user
data can read the configuration until the runner registers. The window is
seconds, the configuration is single-use, and using it would steal one job
rather than grant access to anything.
provision_via: pull_from_api
avoids it entirely, at the cost of putting an API token in your image.2. The cache bucket is one namespace per organization
2. The cache bucket is one namespace per organization
There is no per-branch or per-repository isolation: a pull request’s job
can write an entry a main-branch job later restores, and one repository
can restore another’s keys.Keep public repositories with fork pull requests off cache runners, or
make their keys unguessable. Airship enforces the bucket, not the key
space.
3. Anyone who can push to an activated repository chooses machines
3. Anyone who can push to an activated repository chooses machines
Including an expensive one. It is the same authority they have over
workflow content, and
max_runners is the bound. If that is not
acceptable for a repository, do not activate it.4. An attached cloud identity is available to every step
4. An attached cloud identity is available to every step
If a definition attaches an instance profile or service account, every
step of every job on that runner can use it — including a fork pull
request’s code on a public repository activated for public access. Treat
it exactly as you would a repository secret.
5. Any image your account can launch is allowed
5. Any image your account can launch is allowed
There is no image allowlist. Architecture mismatches are refused, and so
are images a publisher has deprecated, but trustworthiness is not
something Airship can judge.
7. Losing the credential-sealing key loses every connected cloud
7. Losing the credential-sealing key loses every connected cloud
By design: it is the only thing that can open the sealed credentials.
Recovery is reconnecting each cloud. If you run your own control
plane, back that key up as
you would a root key and rotate it with the two-key procedure rather than
by replacement.
Tenancy
The tenant is the GitHub App installation — one organization or user account.- Every database query is scoped by installation ID.
- Every machine carries the installation as a tag or label, and every list filters on it.
- Every teardown reads the machine first and refuses when the tag is not the installation’s, so an ID recorded wrongly — or reused by the cloud for someone else’s machine — can never destroy the wrong thing.
- Cache buckets are named from a hash of the installation ID and owner-checked on every call.
- API tokens are scoped to one installation; runner tokens to one runner.
Straight answers
Job metadata in the control plane’s database. Job content — code, secrets,
logs, artifacts, caches — stays in GitHub and in your cloud account, in the
region your
airship.yaml names.Whoever administers the control plane deployment, as with any hosted
service. If that is not acceptable, run the control plane
yourself: the same code, your infrastructure, your
sealing key.
Yes — a credential you scope and can revoke at any time, held sealed and
opened per call. The least-privilege policies are the floor it can operate
on. On AWS you can condition its terminate permission so it can only ever
destroy Airship’s own machines.
Only what the GitHub App’s permissions allow:
airship.yaml,
airship.global.yaml, access.yaml, and job and runner metadata. Contents
is a read permission; write and pull-request permissions are optional and
used only by the access-control API, when you ask it to open a pull request.We do not claim any certification on this page. Ask us directly and we will
tell you exactly where we are rather than point at a badge.