airlock GitHub

airlock

Zarf moves the boxes. airlock proves the model inside is safe, genuine and unchanged.

A Go CLI that seals an AI model online and checks it again on the offline side, before it runs in an air-gapped network.

Seal online. Carry it across. Verify offline.

  1. Move

    Air gap · Zarf or USB

    • The bundle travels on its own. airlock does not ride this car.
    • Anything that changes a byte on the way shows up at the next stop.
    Car 2
airlock commands
CommandWhereWhat it does
airlock sealOnlineChecks formats and provenance, then signs a manifest.
airlock verifyOfflineChecks signature and every file with no network, writes a report.
airlock smokeOfflineAsks the running model server a question with a known answer.
airlock checkAnywhereRuns only the format checks.
airlock zarfOnlineWrites a Zarf package that runs verify during deploy.

Quick start

Build it, seal a model, verify it, then test the running server. Tested end to end with Qwen2.5 0.5B Instruct (Q4_K_M, commit 9217f5db).

Seal and verify
go build -o airlock .
cosign generate-key-pair
airlock seal ./bundle --key cosign.key --hf Qwen/Qwen2.5-0.5B-Instruct-GGUF --rev <40-char commit>
airlock verify ./bundle --key cosign.pub
Smoke test the server
llama-server -m bundle/qwen2.5-0.5b-instruct-q4_k_m.gguf --port 8080 --offline
airlock smoke --url http://127.0.0.1:8080

Watch it run

Seal, verify, serve with llama.cpp, smoke test, then chat with the model.
A pickle file is refused. A poisoned copy tells users to run an attacker's script. The same model in a signed Zarf package is stopped by airlock.

Stopped at the gate

Each car on this siding was turned back. The message under it is the one airlock prints.

Zarf moves the boxes

Zarf's signature proves the package is the one the packager built. It does not prove what went into it. A model swapped before packaging passes Zarf's checks.

airlock runs as a deploy step inside the package. It checks the model against its own seal, made earlier from the real files, so the swap is refused and the model server never starts.

Always sign the package and deploy with --verify=always. Tested with Zarf v1.0.0.

Package and deploy
airlock zarf ./bundle --key cosign.pub
zarf package create . -o out --signing-key cosign.key
zarf package deploy out/zarf-package-airlock-model-*.tar.zst --key /etc/airlock/cosign.pub --verify=always

End of the line

What airlock does not cover, so you can plan for it.

A stolen signing key
Keep cosign.key off shared machines and rotate through a trusted channel.
Harmful model behaviour
A safe format from the right commit can still be a bad model. Outputs are not evaluated.
Changes after verification
Running verify during the Zarf deploy keeps that window small.
A malicious upstream commit
Pinning stops later changes, not a bad commit.
Rollback
An older bundle signed by the same key still verifies.
Chat templates
Not inspected. Render them in a sandboxed loader.
Metadata values and tensor bytes
Read but not judged.
A compromised online machine
Seal trusts the machine it runs on.
Small upstream files
Matched by git SHA-1, since that is all Hugging Face publishes for them.
Transparency logs
Key-based signatures only, because air-gapped sites rarely reach Rekor.
The serving image
Scan it with Zarf's SBOMs or a scanner.

Full threat model in the README

Seal. Move. Verify.

View on GitHub