Skip to content
هذه الصفحة غير متوفرة بلغتك بعد. يتم عرض النسخة الإنجليزية.

How to Run Annotation on an Air-Gapped Network

What "offline" has to mean for an annotation tool, why an @import in a stylesheet defeats most air-gap audits, and how to get models onto a machine with no route out.

An annotation tool that "works offline" usually means the annotation page renders. That is not the same as the deployment making no outbound requests, and the gap is where the privacy problems live. If you are deploying into a secure research environment, a clinical setting or a government network, this is what to check.

Audit the rendered page, not the source

The only reliable test is a live one. Open the annotation interface with DevTools' network panel filtered to third-party requests and count.

Reading the templates is not sufficient, and this is not a hypothetical distinction. Potato's own styles.css opened with an @import of Google Fonts, which survived three previous air-gap audits because every guard checked <script src> and <link href> in templates — and an @import inside a stylesheet is neither.

Beyond breaking offline, it sent every annotator's IP address and User-Agent to a third party on every page load, from a tool people self-host precisely so their data does not leave their infrastructure.

Check every page, not the main one

Login, signup, password reset and error pages are audited least and matter most. A third-party favicon on a login page is a request to another company's servers from the page where users type their credentials.

Potato now serves all 14 templates locally. Verified live: 62 requests, zero external.

What has to be local

Every stylesheet, script, font and icon. In Potato's case that is Fabric.js, jQuery, Bootstrap, Font Awesome, the interface typeface, three.js, OpenSeadragon, d3, Peaks.js and PDF.js.

Two of those are required rather than cosmetic: without jQuery, span annotation does not work; without Fabric.js, the image canvas never initializes, so drawing tools render but nothing can be drawn. An air-gapped deployment that renders but silently cannot annotate is the worst outcome, because it looks fine.

Verify vendored files

Vendored files are committed, so an unverified download ships to every user of that release. Check each against the hash its CDN publishes and refuse on mismatch.

Keep guard allowlists empty, and make the guard fail when an entry stops matching anything. Otherwise a temporary exemption quietly becomes permanent.

Models are a separate transfer

The application needing no network is not the same as the models being present.

bash
# On a connected machine
potato download-models --list
potato download-models mobile_sam
potato download-models grounding_dino_tiny
 
# Then copy the model directory to the air-gapped machine

So the accurate claim is "air-gapped once the weights are on the machine", not "air-gapped with no setup". Any hosted AI endpoint you configure obviously needs a route out, and should be off in this deployment.

Check the licences before you transfer

Do it while you still have a browser. download-models --list marks non-commercial models, and download-models refuses to fetch one without --accept-licence. Discovering a licence constraint after building a dataset on an isolated network is an expensive way to find out.

Further reading