A GitHub Actions workflow. The deploy job sets DATABASE_URL — prod — at the start to run a migration. Three jobs later, a developer adds a new test step. The test step calls a helper utility. The utility, three function calls deep, runs a database migration. Against production. Nobody passed DATABASE_URL to it. It was ambient — set earlier, never cleaned up, inherited into every subprocess. The tests passed. The migration ran on prod. Nobody noticed for a week.
This isn't a breach. It's not a misconfiguration you can grep for. It's a structural property of how CI runners work: authority is ambient by default.
The band-aids that don't work
`env:` blocks in CI config — scoped at declaration time, but any subprocess inside that step inherits the full environment. The block is intent documentation, not runtime enforcement.
Cleanup steps that unset variables — they run after the job finishes. If the damage happens during the job, cleanup doesn't help.
Policy docs saying 'don't use prod secrets in test jobs' — policies are not runtime checks. The runner doesn't read the runbook.
Separate jobs for prod and test — reduces the surface, doesn't eliminate it. Cross-job env inheritance via `needs:` is still a vector. And humans still make mistakes configuring which secrets go where.
None of these change the fundamental model: in a standard CI runner, every process can see everything in the environment. You're managing exceptions to ambient access. That's backwards.
CellOS: declare what you need, receive nothing else
CellOS models execution as ephemeral cells. A cell is a unit of execution with a declared authority contract — exactly what environment variables it can see, what filesystem paths it can write, what network it can reach. The contract is verified at cell launch, not at review time. If DATABASE_URL isn't in the contract, the cell doesn't have DATABASE_URL, regardless of what the parent environment contains.
The test cell can't reach prod because it was never given it. Not because a policy says it shouldn't. Because the execution model doesn't provide it.
What changes
You stop writing cleanup steps to remove ambient access. You start writing contracts that declare what each execution unit actually needs. The audit surface becomes explicit: read the contract, know the scope.
Ambient authority in CI runners isn't a misconfiguration you can audit your way out of. It's a structural property of the execution model. CellOS changes the model.