
airgap-check:检测AI应用在离线环境中静默发起的网络请求
来源标题:Show HN: Airgap-check – find what your AI app silently downloads offline
airgap-check 是一款零依赖 CLI 工具,可发现 Python/TypeScript AI 应用在离线部署时仍会静默请求外部网络。实测中 fastembed 在无网络环境下会重试并卡顿 39.2 秒后崩溃,huggingface_hub 卡顿 23.5 秒,请求目标包括 huggingface.co 和 storage.googleapis.com。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
把现代 Python 或 TypeScript AI 应用部署到隔离网络的 VPC、SCIF、医院内网,或者 --network none 的容器里,会发生什么?
即便你的应用指向本地 LLM(vLLM、Ollama)或企业内部网关,流行的 AI 库仍会在运行时偷偷回连外网,去拉取 tokenizer 词表、ONNX 嵌入权重、语料 zip 包、价格表,或者后台上报 OTLP 遥测——结果就是立刻抛出 ConnectError 崩溃,或者每个请求卡在 23s–39s 的重试等待里。
airgap-check 是一个独立、零依赖的 CLI,它可以:
为了避免把静态规则过拟合到单一代码库,我们分两个阶段评估了 airgap-check:
库 / 调用
在 --network none 下的表现
隐藏的外连目标
实测失败耗时
fastembed (TextEmbedding())
3 次指数退避重试(3s + 9s + 27s)后卡住,最终抛出 ValueError: Could not load model
huggingface.co:443 / storage.googleapis.com
39,200 ms(卡住 + 崩溃)
huggingface_hub (hf_hub_download())
带退避重试 HTTP 元数据检查,最终抛出 LocalEntryNotFoundError
huggingface.co:443
23,523 ms(卡住 + 崩溃)
chromadb (collection.add())
默认嵌入函数通过 httpx 下载 all-MiniLM-L6-v2(onnx.tar.gz)
chroma-onnx-models.s3.amazonaws.com:443
581–662 ms(ConnectError 崩溃)
tiktoken (get_encoding("cl100k_base"))
首次分词调用时通过 HTTPS 拉取 .tiktoken BPE 词表文件
openaipublic.blob.core.windows.net:443
343–557 ms(ConnectionError 崩溃)
nltk (nltk.download("punkt"))
运行时尝试拉取 XML 索引和语料 zip
raw.githubusercontent.com:443
477 ms(返回 False / LookupError 崩溃)
playwright (chromium.launch())
如果无头浏览器二进制没有预置到 PLAYWRIGHT_BROWSERS_PATH,会立即失败
playwright.azureedge.net:443
702 ms(Error: Executable doesn't exist)
litellm (get_model_cost_map())
除非设置 LITELLM_LOCAL_MODEL_COST_MAP=True,否则从 GitHub 拉取实时模型价格 JSON
raw.githubusercontent.com:443
234 ms(回退警告 / 延迟)
crewai / chromadb 遥测
除非通过环境变量禁用,否则启动时拉起后台 OTLP / PostHog 线程
telemetry.crewai.com:4319, us.i.posthog.com:443
后台线程超时
样本外留出评估(10 个未见过的 AI 仓库,规则冻结)
冻结规则集之后,我们对 10 个未见过的仓库(chat-langchain、docling、gpt-engineer、gpt-researcher、litellm、llama_index、mem0、pydantic-ai、quivr、vanna)运行了 airgap-check,并把静态预测与人工核查 manifest 的 ground truth 以及 docker run --rm --network none 实际执行结果做对比:
仓库级离线崩溃检出:9 / 9 个含离线运行时下载器的仓库被识别(仓库级召回 100%),1 / 1 个真阴性(chat-langchain)。
组件级真阳性(TP):在 10 个未见仓库中共验证到 35 个运行时下载器 / 遥测组件。
组件级假阳性(FP):4 个(精确率 89.7%)。
4 个 FP 的根因:package.json 会被解析成 AST 以剔除 devDependencies,但 pyproject.toml 只被当作文本扫描,导致 dev/test 依赖组(docling 和 pydantic-ai 中的 playwright)或可选 extras 名称(posthog = ["pydantic-ai-slim[mcp]"])触发了静态告警。
组件级假阴性(FN):5 个(组件级召回 87.5%)。
5 个 FN 的根因:OCR 权重下载器(easyocr、rapidocr、paddleocr)、FlagEmbedding,以及 LiteLLM 启动时从 GitHub 拉取 JSON(model_prices_and_context_window.json)不在冻结的静态规则表里——这也说明,除了静态扫描,动态 --run 验证(UDP:53 DNS 捕获)是必不可少的。
安装
方式 1:一行命令安装二进制(macOS 与 Linux——无需 Go)
curl -fsSL https://raw.githubusercontent.com/humanethq/airgap-check/main/install.sh | sh
方式 2:用 Go 1.22+ 直接安装(零外部依赖)
go install github.com/humanethq/airgap-check/cmd/airgap-check@latest
方式 3:从源码构建
git clone https://github.com/humanethq/airgap-check.git cd airgap-check make build ./bin/airgap-check --help
用法
- 静态审计 + 可直接粘贴的 Dockerfile 修复方案(
--fix)
airgap-check --fix /path/to/your/repo
生成一份完整报告,涵盖运行时下载器、服务端与浏览器遥测的区分(前端的 posthog-js 与 Python 中的 posthog/chromadb)、.env 凭据分类(wire_api_key、local_signing_or_internal 如 JWT_SECRET_KEY、signed_request_flow 如 CLOUDINARY_API_SECRET),并打印一段 100% 可独立使用的 Dockerfile 代码块:
--- BEGIN AIR-GAP & TELEMETRY REMEDIATION (paste into your Dockerfile) ---
1. Silence background SDK telemetry & enforce writable offline cache paths
ENV DO_NOT_TRACK=1
NEXT_TELEMETRY_DISABLED=1
ANONYMIZED_TELEMETRY=False
CHROMA_TELEMETRY_IMPL=none
SCARF_NO_ANALYTICS=true
HF_HUB_DISABLE_TELEMETRY=1
HF_HUB_OFFLINE=1
TRANSFORMERS_OFFLINE=1
LANGCHAIN_TRACING_V2=false
CREWAI_DISABLE_TELEMETRY=true
OTEL_SDK_DISABLED=true
STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
XDG_CACHE_HOME=/app/.cache
TIKTOKEN_CACHE_DIR=/app/.cache/tiktoken
HF_HOME=/app/.cache/huggingface
NLTK_DATA=/app/.cache/nltk_data
PLAYWRIGHT_BROWSERS_PATH=/app/.cache/ms-playwright
RUN mkdir -p /app/.cache/tiktoken /app/.cache/huggingface /app/.cache/nltk_data /app/.cache/ms-playwright
Pre-warm Python tiktoken BPE encodings (cl100k_base & o200k_base) at build time
RUN TIKTOKEN_CACHE_DIR=/app/.cache/tiktoken python3 -c "import tiktoken; [tiktoken.get_encoding(e) for e in ('cl100k_base', 'o200k_base')]"
Pre-warm ChromaDB default ONNX embedding model (all-MiniLM-L6-v2) at build time
RUN HOME=/app XDG_CACHE_HOME=/app/.cache python3 -c "from chromadb.utils.embedding_functions import ONNXMiniLM_L6_V2; ef = ONNXMiniLM_L6_V2(); ef(['airgap-warmup'])"
--- END AIR-GAP & TELEMETRY REMEDIATION ---
- 在
docker run --rm --network none中做动态验证(--run)
使用默认生态镜像运行,或传入你构建好的应用镜像:
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。