Most ML runtimes assume connectivity somewhere in the stack. Inference can be local while the surrounding software still expects a network. That assumption is rarely declared. It lives in tokenizer loading, telemetry defaults, license validation, driver tooling, configuration paths, or a transitive library that only fails once the host is isolated.
Teams usually find this when the network is gone — not when they package the model.
Dependencies that surface offline
Common failure modes from practitioner environments and ecosystem trackers:
- License validation. Commercial libraries or enterprise endpoints that phone home at startup. Without a network, initialization fails. The error often does not mention licensing.
- DNS during model load. Components that resolve hostnames as part of startup even when no payload is transferred. On an air-gapped host, DNS timeouts stretch startup or trigger silent fallbacks.
- Telemetry defaults. Usage reporting baked into default configs. Calls may fail quietly — until they block a thread or flood logs with connection timeouts.
- Model-format side loads. Local weight files that still fetch tokenizer files, configs, or version-check URLs from a public hub. The weights are local; the load path is not.
- Driver and tooling probes. Utilities that check for updates before loading. Quiet on most systems; on some, a multi-second hang or a monitoring false positive.
None of these is a security vulnerability in isolation. They are availability failures that compound when you cannot “just restart and see.”
Dependency control as architecture
In a connected deployment, an unmanaged dependency is an inconvenience: retry, fall back, restart. Offline, it is a deployment failure.
Shipping weights and inference code is not enough. Every transitive dependency in the runtime stack needs offline verification across four layers:
- System. Kernel modules, GPU drivers, firmware. Not application dependencies in the usual sense, but they sit on the inference path and some still touch the network.
- Framework init. Startup sequences probe hardware, open CUDA contexts, and load shared libraries in platform-specific order. Each step can encode an environment assumption.
- Transitive libraries. Framework → cuDNN → cuBLAS → CUDA runtime. Each layer has its own init path, defaults, and failure modes.
- Configuration defaults. Cache paths that point at network locations, HTTP log transport, health checks that probe external services. Defaults must be found and overridden before deployment.
Offline operation is a dependency property before it is a deployment property.
Updates without a network
A connected system receives patches continuously. An offline system receives them when someone delivers them.
That creates two concrete problems. Staleness: the gap between disclosure and fix is measured in maintenance windows, not hours. Acceptable staleness is a policy decision and should be written down — same issue framed in the offline threat model. Integrity of the delivery path: updates arrive on physical media rather than over authenticated TLS. Who built the package? How was it validated? What is the rollback if the update regresses? Connected environments answer those with signed packages, canaries, and automatic rollback. Offline environments need the same answers designed deliberately.
A dependency inventory
For an offline AI deployment, inventory at least:
- Every shared library loaded during inference, with version and provenance
- Every file touched during model load, including tokenizer configs and auxiliary data
- Every network call attempted during init, steady-state, and shutdown — measured by running the full stack on a network-isolated host
- Every environment variable or config that references external paths, URLs, or services
- The exact GPU driver, CUDA, and cuDNN versions required, checked against hardware determinism constraints for that deployment
This is not a one-time checklist. Framework, driver, and model changes introduce new edges. Re-verify on each change.
Connection to the threat model
Dependency control is load-bearing for the offline threat model. Every unmanaged dependency is either an availability failure waiting for the wrong moment, an unintended network path that violates the air-gap claim, or a config assumption that breaks when the stack moves from the build host to the deployment host.
Teams that treat dependency control as packaging — “put it in a container and ship” — find the edge cases in production. Teams that treat it as architecture find them in testing, while there is still time to fix them.