AIRLOCK

Overview / Trust

TRUST

Airlock makes a claim about a repository, so the model behind that claim has to be readable. This page states what it trusts, what it refuses to guess, and what it does not cover.

[ 01 ]

Hard rules

Never broken

Never execute, import or evaluate scanned content. The tree under scan is untrusted input, and nothing in it is run to find out what it does.

Never run scanner code from the scanned checkout. The tool comes from a pinned path or the installed package, not from the repository it is judging.

Read policy from the trusted base. In pr and push modes, policy, suppressions and the Wasm manifest come from the base commit, never from HEAD.

No network and no telemetry during a scan. A scan that needs to fetch is a scan that can be told what to see.

No runtime dependencies. Python 3.11 and the standard library. A wheel with no rules cannot scan, so the rules travel inside the package.

Never skip a file silently. Every skip is a finding with a rule id, a severity and a path.

No default directory skips. Vendored directories are read like any other path.

No inline suppression markers. Suppressions are fingerprint-keyed, occurrence-aware and carry a reason.

Never return 0 after an error. A detector exception, an invalid configuration or an unresolvable base is a failure, not a clean run.

Match raw text. There is no comment or string masking, because the line a reviewer reads and the line the matcher sees have to be the same line.

[ 02 ]

Fail closed

State findings

These ids are decisions about the scan itself rather than matches inside a file. A skip is reported, and a setting that changed inside the change is judged by the base copy.

Scanner-state findings
Rule idSeverityWhat it means
skipped-oversizeHIGH in a sensitive role, WARN otherwiseThe file is over max_file_bytes and was not read in full.
skipped-unreadableHIGHThe file could not be read, or changed size while it was being read.
skipped-symlinkINFOA tracked symlink is recorded; its target is never read.
skipped-unmergedHIGH in a sensitive role, WARN otherwiseThe path is unmerged in the index, so there is no agreed content to scan.
submodule-presentINFOAn embedded repository; its contents belong to its own pipeline. Task 7.2 decides whether this rises.
nul-in-textHIGHA NUL byte after BOM handling: the file is not the text its extension claims.
non-utf8-textHIGH in a sensitive role, WARN otherwiseThe bytes are not valid UTF-8 even after BOM handling.
cfg-long-lineHIGH in a sensitive role, WARN otherwiseA line over line_cap. The regexes deliberately do not run on it, so its length is the finding.
detector-errorHIGHA detector raised. Findings it produced before raising are kept.
history-rewrittenHIGHThe pushed before is not an ancestor of HEAD, so the base policy cannot be trusted.
no-trusted-baseWARNA push created the branch. The shipped defaults apply, and the scan still runs at full strength.
policy-changedWARNThe policy changed inside this change. The base copy is what ran.
policy-unknown-keyWARNA key this build does not read. The setting stays at its default.
untrusted-policy-sourceINFOfull mode read policy from the working tree, which the change can edit.
suppression-invalidHIGHA suppression entry matches no applicable finding, so it is hiding nothing and claiming otherwise.
suppression-expiringWARNAn entry expires within 30 days. Renew it with a reason, or let the finding return.
[ 03 ]

The seven bypasses

Appendix B / Measured

Five public Soroban repositories shipped the same scan step. On 2026-10-27 each shape below was committed to a scratch repository and the real script was run the way the workflow runs it. All seven exited 0.

Six are now regressions under tests/bypass, and they assert rule ids and severities rather than a bare exit code so an unrelated HIGH cannot make them pass. The seventh waits on the Cargo detector, and its test is skipped with that reason in the fixture rather than deleted.

The probe that measured the old script and the tests that judge this package import the same case table, so the harness and the regression cannot drift. The payloads are assembled from fragments at run time, which is why no live-looking string is committed here.

Appendix B in PRD.md ↗

Each case, the old gate, and Airlock
CaseShapeOld gateAirlock
B-01A .wasm file of any contentEXIT 0CAUGHT wasm-unlisted, HIGH
B-02A NUL byte in the first 4 KB of a text fileEXIT 0CAUGHT nul-in-text, HIGH
B-03A payload line ending in the old inline allow markerEXIT 0CAUGHT the marker changes nothing
B-04An allowlist file containing a single wildcardEXIT 0CAUGHT no allowlist exists, the payload is read
B-05A decode-then-evaluate line in a tooling configEXIT 0CAUGHT cfg-dynamic-code, HIGH
B-06A .cargo/config.toml runner invoking a shellEXIT 0PENDING Cargo vectors, task 6.4
B-07A payload under a directory the old script skippedEXIT 0CAUGHT pat-decode-eval, HIGH
[ 04 ]

What it does not do

Limits

It is not an antivirus and not a dependency-advisory tool. It does not resolve lockfiles, compare package versions or read a vulnerability database. It does not unpack archives, and it does not parse JavaScript with a lexer.

It does not fetch wasm from a chain, validate SEP-58 metadata, or check a contract size limit. Those are Phase 6 work and they stay unclaimed until the detectors exist.

A clean report means nothing matched the rules that ship. It is a narrower and more honest claim than "no compromise found", and it is the only claim a rule set of this size can support.

SARIF output and the composite Action are not shipped. There is no signed release, so no commit before the first attested tag carries a release guarantee.

[ 05 ]

Residual risk

Stated, not hidden

Whoever can push a workflow file can remove the scan. A required status check covers pull requests, because a pull request that deletes the step never reports the check. It does not cover a direct push by a stolen credential.

The control for that is an external watcher that clones a repository and compares its last seen commit (backlog D-04), plus hardware-key two-factor authentication on the accounts that can push.

A required check also does not help if the check is not required, and branch rules are repository settings rather than files. The roadmap tracks those tasks separately from the code, because neither can be verified by a test in this tree.

Report a vulnerability in Airlock itself ↗