上周一早上,我把 AI-Infra-Guard 的容器拉到服务器上,docker compose up -d一把跑起来,Web 控制台正常打开,任务列表也出来了。说实话,“Docker 一键起”这种体验确实爽——镜像拉下来、容器一启动、界面一点开,一套 AI 基础设施的技能扫描服务就在线了。但我还没来得及高兴,就在第一轮真实环境扫描里撞上一个问题:两个我明确知道“一定有风险”的扫描项,居然被漏报了。这个“漏报”不是工具不可用,而是我处理它的方式有问题。这篇文章会把部署过程、技能扫描的配置逻辑,以及那次漏报的完整排查链路都写清楚,对于正在做 AI 基础设施安全、想给大模型服务或 Agent 底座加一道“技能面扫描”的朋友,应该能省掉不少试错时间。
1. AI-Infra-Guard 到底是什么:一个“技能面”哨兵
1.1 它和传统漏洞扫描不是一个物种
很多刚接触 AI-Infra-Guard 的人会拿它和 Nessus、OpenVAS 这类漏洞扫描器对比,问“能不能扫出 CVE”。这个问题一出来,路子就走偏了。传统漏洞扫描关心的是“组件有没有已知漏洞、端口有没有异常暴露、版本有没有过旧”,它扫描的是基础设施的资产暴露面。而 AI-Infra-Guard 的核心定位,是扫描 AI 应用对外暴露的技能面(Skill Surface),也就是一个 AI Agent、大模型应用或智能体外化出来的“可调用能力”。打个比方:传统漏扫是检查你家门窗有没有锁好,AI-Infra-Guard 则是冒充访客,尝试看你能不能通过“对话话术”从家里骗出一件贵重物品,或者让保洁阿姨帮你打开保险柜。两者都重要,但解决的不是同一个问题。
“技能扫描”这个词拆开来看:技能,指 AI Agent 可以执行的原子操作或外部能力——比如查询数据库、调用第三方 API、读取文件、发邮件、访问内部系统;扫描,指用构造好的探测请求去探测这些技能是否存在、是否被异常调用、是否存在越权。AI-Infra-Guard 做的事情,就是把这些探测请求编排成可以重复执行的检查任务,并把命中结果汇总成可审计的报告。
1.2 它解决的核心场景
我自己接触到的场景有三类,比较典型:
第一类是平台方自查。你上线了一个大模型应用,或者基于某个 Agent 底座搭了一套内部助手,你需要知道“用户可不可以诱导它调用不该调的工具”。这个问题在传统安全测试里往往没人管,因为大家默认 LLM 对话是“内容安全”问题,却忽略了它背后的工具调用链路已经变成了真正的业务风险。
第二类是上线前的技能面回归。很多团队对新功能的测试停留在功能层面,而 AI 应用的新增技能往往意味着新增工具调用权限。技能扫描能帮你确认新增技能是否有配套的访问控制。
第三类是常态化审计。合规和内部审计要求安全团队定期给出“AI 服务暴露面”报告。手动测试很难形成持续覆盖,AI-Infra-Guard 这类工具的价值在于把扫描任务周期性固定下来,结果可对比、可留存。
1.3 总体架构与部署形态
AI-Infra-Guard 默认推荐容器化部署。整体架构可以理解成三部分:数据面(配置、Token、指纹库的存储)、控制面(Web 控制台和 API 服务)、扫描引擎(执行探测任务并收集结果)。三者可以在一个容器编排里同时拉起,也就是标题里说的“Docker 一键起”。这也让它很适合在测试环境或中小型团队的服务器上快速落地,不需要额外装数据库和队列。
部署层面最核心的一点是:它扫描的不是 AI 模型输出质量,而是 AI 服务可被调用的技能链路。所以它的探测目标不是“模型响应是否合理”,而是“对外 API 或 Agent 服务是否存在可被绕过、滥用、拖取数据的能力”。理解这一层,后面配置扫描策略时就不会抓瞎。
2. Docker 一键起:从镜像拉到服务跑通的完整过程
2.1 前置准备
部署前我列了一个简短的准备清单,避免中途反复:
- 一台 Linux 服务器,或者本机装好 Docker Desktop,内存建议至少 8GB(实测扫描任务并发上来之后,4GB 会紧巴巴的)。
- Docker 版本 20.10 以上,能正常拉取公共仓库镜像。
- 准备一块持久化存储目录,用来放配置、日志和扫描结果。容器一重启就丢数据是最烦的事,所以挂载目录一定要提前规划。
- 确认服务的默认端口没有被占用。不同的版本默认端口可能不同,我在文中按我实测的
8080来写,实际以你拉到的镜像元数据为准。 - 时间同步。这一点容易被忽略,但扫描任务的时间戳、调度计划、日志审计全都依赖准确时间。
2.2 docker compose 配置与启动步骤
我选择了 docker compose 而不是直接 docker run,是因为技能扫描涉及多个服务(控制面、引擎、存储),compose 可以把它们放在一个网络里管理,重启策略、资源限制、日志滚动也都一并解决了。
下面是一个参考用的docker-compose.yml:
version: '3.8' services: ai-infra-guard: image: your-registry/ai-infra-guard:2.3.1 container_name: ai-infra-guard restart: unless-stopped environment: - TZ=Asia/Shanghai - GUARD_LOG_LEVEL=info - GUARD_DATA_DIR=/data - GUARD_API_PORT=8080 ports: - "8080:8080" volumes: - /data/ai-infra-guard:/data - /data/ai-infra-guard/logs:/logs networks: - guard-net mem_limit: 4096M cpus: "2.0" guard-redis: image: redis:7-alpine container_name: guard-redis restart: unless-stopped command: redis-server --appendonly yes volumes: - /data/ai-infra-guard/redis:/data networks: - guard-net networks: guard-net: driver: bridge启动命令就三行:
mkdir -p /data/ai-infra-guard/logs /data/ai-infra-guard/redis docker compose up -d docker compose logs -f --tail=200 ai-infra-guard看到日志里出现类似API server started、redis connection ok的字样,基本就说明服务起来了。然后打开浏览器访问http://服务器IP:8080,能出登录页就算部署成功。
2.3 起完之后的健康检查别偷懒
很多教程到“打开 Web 界面”就结束了,但做安全扫描这一行,部署成功不等于监控链路可用。我自己的习惯是再做三个验证:
- 验证 API 端口能响应探测请求:
curl -s http://localhost:8080/health,确认健康检查接口返回 200。 - 验证数据持久化:往 Web 控制台里随便加一条资产记录,然后
docker compose restart ai-infra-guard,重启后确认记录还在。 - 验证扫描引擎的日志输出独立可查:执行一次最小化的单目标扫描,确认
/logs下有对应的扫描任务日志生成。
这三个验证做完,才算把“一键起”这件事真正闭环了。
2.4 部署踩坑记录:资源、网络、时区
这一节是真实操作中容易翻车的地方。
第一个坑是内存限制。我给 AI-Infra-Guard 设了mem_limit: 4096M,一开始线上实测跑多个技能包并发扫描时,OOM 直接把扫描引擎进程杀了,控制台看起来还活着,但任务状态一直卡在“运行中”。查了半天才发现是容器内存被杀。后来我提高了内存限制,并将并发数调低,才稳定下来。
第二个坑是 Docker Desktop 的挂载路径。在 Windows 上跑 Docker Desktop,/data/ai-infra-guard这类 Linux 路径很容易踩到文件共享的权限问题。建议直接用./data/ai-infra-guard:/data相对路径,让 Docker 自动处理映射。
第三个坑是网络模式。如果你所在环境里还有其他容器服务,不建议把 AI-Infra-Guard 和一堆业务容器混在同一个自定义网络里。我见过有人把 guard-net 和业务网络直接打通,导致扫描器探测流量能直接触达内部服务,扫描结果“全绿”但实际已经扩大暴露面。安全工具本身的部署边界,必须和业务网络隔离。
第四个坑是时区。不设TZ的话,扫描任务的时间戳默认是 UTC,和本地审计日志对时间的时候容易晕。compose 里加一行TZ=Asia/Shanghai就好。
3. 技能扫描的配置闭环:Token、策略与指纹
3.1 创建 API Token:别图省事一把梭
AI-Infra-Guard 的扫描任务需要 Token 来访问目标服务。这个 Token 不是你部署工具的登录密码,而是它去探测目标时使用的凭据。很多人图省事,直接塞一个管理员账号进去,结果就是扫描器可以用管理员权限调用任何接口——这等于你请了个保安,然后给了他万能钥匙。
我实际使用的配置原则是:
| 维度 | 推荐做法 | 原因 |
|---|---|---|
| 账号角色 | 专用只读账号 | 避免扫描器被反向利用时扩大权限 |
| 权限范围 | 按目标服务的最小权限开通 | 扫描只需要“读取+触发”能力,不需要写操作 |
| 存放位置 | 放进 secrets 文件挂载,不要写死进 compose 环境变量 | 防止镜像或配置泄露时凭据一起泄露 |
| 生命周期 | 定期轮换 | 长期不换的 Token 是最容易被忽略的泄露途径 |
这一步很关键:如果 AI-Infra-Guard 拿到的 Token 权限过大,那漏报还是误报都不重要了,工具本身就成了一个风险入口。
3.2 资产导入与目标路由:URL 写不对,扫描全白费
技能扫描的“目标”不是 IP,而是 AI 服务对外暴露的路由。常见的目标资产类型包括:LLM 服务接入点、Agent 工具调用网关、RAG 检索接口、Prompt 调试沙箱。
配置资产时最大的坑是 URL 路由。举例:某个服务实际接收技能调用的端点是POST /api/v1/tool/execute,如果你扫描时只填了POST /api/v1/chat,那 AI-Infra-Guard 只能探测到会话接口,真正的高危技能链路完全没被覆盖。我的建议是除了填服务地址,要把能确认的 API 文档或调用日志里的真实调用路径也录入资产描述中,扫描任务下发时会精确得多。
3.3 扫描策略与技能包:理解“匹配命中”的判定
创建扫描任务时,会看到多个“技能包”或“检测项”,例如:
- 提示词注入检测:构造引导型 Prompt,看是否能让目标输出异常指令或改变行为。
- 工具越权调用检测:尝试以低权限身份触发高权限工具。
- 敏感数据拖出检测:探测是否存在可被诱导返回内部数据或系统提示词的接口。
- 开放重定向检测:探测 AI 生成链接或跳转逻辑是否可劫持。
- 身份混淆检测:验证会话隔离是否可靠,能不能通过历史会话套取上下文。
这些检测项不是“发一个请求看返回包”那么简单。AI-Infra-Guard 的匹配逻辑我理解下来分为两层:第一层是请求层匹配——探测请求是否会引发目标产生某种可预期的行为(比如返回特定状态码或回调);第二层是响应层匹配——对返回内容做关键词、语义特征和结构特征的比对。配置扫描策略时,建议不要全选所有技能包一次性跑完。我吃过这个亏:全选跑完的结果看起来“扫描了很全面”,但生成的报告太大,筛选优先级反而要花很多时间。按目标服务的实际能力来聚焦技能包,效果更好。
3.4 结果审计口径:别把“异常”当成“风险”
第一次用这类工具的人很容易被报告吓到。扫描结果里大量“提示词注入疑似命中”看着吓人,其实很多是目标服务返回了通用错误信息,被关键词匹配误判为风险。我后来给自己定了一套结果处理口径:
- 高置信确认:响应中明确包含了工具调用返回内容,或出现了可验证的数据回显,这是真正的风险。
- 待人工复核:匹配到了特征词,但无法确认是否真实发生。
- 低置信误报:只有状态码异常或超时,特征命中但缺乏行为佐证。
每次扫描完成后,先按这个口径过一遍,再提工单或修漏洞,效率会高很多。
4. 一次“漏报”的完整复盘:从误报疑云到语义维度的真相
4.1 现象:两个“已知风险技能”没扫出来
我部署完 AI-Infra-Guard 后,在自建的大模型应用网关上跑了一轮技能扫描。我为什么要先跑这个网关?因为它底下挂了多个 Agent 技能,其中一个技能是“数据拖出”——本意是支持用户导出自己的对话记录,但接口设计上对角色判断不严格;另一个是“提示词注入”——接入了外部工具描述文本,存在被注入恶意指令的可能。这两个问题通过人工测试是可以复现的,属于内部已知待修复项。
结果扫描报告出来,这两项一个都没命中。第一次看到这个结果,我第一反应是“工具是不是没配置对”。这其实是很多安全工程师的默认心理:工具报错先怪工具。但我强迫自己从头查了一遍。
4.2 排查链路第一步:从激活状态与授权范围入手
先回控制台确认扫描任务用的 Token 是否有权限访问目标网关注册的接口。我看了下 Token 对应的角色范围,确实覆盖了目标服务的读取和调用权限。这一步排除了“Token 权限不足”导致探测请求被默默丢弃的可能。
4.3 排查链路第二步:扫描策略是否覆盖对应技能包
检查扫描任务配置,我确实勾选了“敏感数据拖出检测”和“提示词注入检测”。所以不是策略漏选。为了进一步确认这两个技能包本身有没有正常工作,我又拿一个我特意搭的危险测试页去跑,结果能正常命中。说明技能包本身是活的,问题出在目标网关上。
4.4 排查链路第三步:目标资产的路径路由是否存在偏差
这是我最开始怀疑的方向。因为我知道网关不止一个入口,其中一些内部接口是不经过统一鉴权的。检查 AI-Infra-Guard 里填的资产 URL,发现我录入的是外层统一入口,而不是真实触发“数据拖出”逻辑的内部路由。后面我通过网关访问日志确认,扫描器发出的探测请求全都打在了统一入口上,返回的是标准响应。
所以第一层原因浮出水面:目标资产录入没有覆盖到真实风险链路,导致扫描请求根本没到达有问题的技能模块。这是部署配置层面的疏漏,不是工具的问题。
4.5 排查链路第四步:即使路径对了,响应匹配也没命中
我没有停在第一步。把资产路由修正为真实调用路径后,重新扫描,我发现了一个更隐蔽的问题:即使探测请求到达了“数据拖出”接口,扫描结果依然没有标记为风险。抓包对比后发现,目标服务对这类异常的返回响应非常简短,只返回了{"code":200,"msg":"ok"},没有任何可疑关键词或错误信息。AI-Infra-Guard 的响应层匹配依赖“行为特征”,而该接口在异常调用时既没有报错,也没有泄露数据内容,只返回了一个看似正常的 JSON。这种情况下,关键词匹配和状态码匹配全部落空。
这就是“漏报”的技术本质:匹配链路没撞上风险行为的特征维度。工具认为“响应正常,未命中风险”,但实际上风险已经发生了——只是它没有在响应层暴露出来。
4.6 隐藏的干扰项:日志里那条“未授权”误报
复盘途中我还被一条日志干扰了一段时间。在扫描日志里,我看到一条unauthorized access detected的记录,第一反应是“扫描请求被网关拦截,权限不足”。于是我又去调了半天 Token 权限。最后才发现,这条“未授权”记录是另一个无关接口的正常访问控制日志,不是针对扫描探测请求的。
这就是安全工具实践的经典误区:日志里的关键词会诱导你走向错误的排查方向。看到unauthorized就以为是权限问题,实际上目标接口对异常请求的处理方式就是“不报错、不拒绝、返回 200”,这种“静默容忍”才是漏报的核心原因。安全排查时,不能只看日志关键词,要回到请求-响应全链路去验证。
4.7 复盘结论:漏报不是没扫到,是匹配维度没对齐
复盘下来,这次漏报由两个因素叠加:一是资产录入路径偏差,让扫描器只覆盖了外层入口;二是目标服务对异常请求的响应是“静默接受型”,扫描器的响应特征库没有覆盖这种场景。后者是最本质的原因——AI 服务不像传统 Web 服务,风险行为不一定会体现在响应码和响应体显性特征上,它有大量“行为发生了但表面上一切正常”的情况,所以技能扫描对行为的探测能力要求远高于一般漏扫。
之后我还做了一次对照实验:在同一目标服务上,我不使用工具的默认技能包,而是自定义了一个探测任务,在请求体中放入一段会触发数据拖出逻辑的参数组合,然后通过响应时间差异和后台日志确认该技能确实被触发。这才坐实了“技能存在但默认指纹没覆盖”。工具本身的检测能力不弱,只是它对“无声响应”类风险缺少先验知识。
5. 漏报复盘后我做的加固:从被动发现到主动防御
5.1 自定义指纹扩充:把漏报样本变成检测能力
既然漏报的根因之一是指纹库缺少对应特征,那最直接的加固方式就是扩充自定义指纹。AI-Infra-Guard 支持自定义检测规则,我把那次的“静默接受型”行为总结成两条规则加进去:第一条是关注请求参数中高危指令关键词是否成功传递到服务端执行链路,第二条是关注目标服务在异常请求后的响应延迟和后续日志行为。具体配置路径每个版本不太一样,核心思路是:当响应层无特征可依赖时,把检测重心前移到请求构造和后置行为验证上。
这一步是运维安全里很常见的闭环操作——把每一次漏报当作指纹库的输入样本,而不是只在报告里标记一句“未命中”就完事。
5.2 双人复核机制:别让自己的判断盲区持续存在
漏报复盘之后我意识到,单靠一个工程师的判断来校准工具,盲区太大。我在团队里推行了一个简单的复核机制:每次扫描任务结束后,安全负责人需要在报告上签字确认,重点不是“有多少命中”,而是“哪些已知风险点这次没有命中”。如果发现已知风险点未命中,必须给出解释——是已修复、已配置豁免,还是扫描链路存在问题。这个机制虽然只增加了一步人工动作,但把“工具输出”和“业务事实”之间的一致性给锁住了。
5.3 扫描频率与覆盖范围:从一次扫描变成持续基线
原先的扫描是“想起来才跑一把”,复盘后我改成了三档节奏:
- 新服务上线前:必须跑一次完整技能扫描,并确认资产路由覆盖到真实调用链路。
- 每周基线扫描:对整个 AI 服务暴露面跑一次标准技能包,重点看新增技能和变更路由。
- 每月深度扫描:用全技能包加自定义指纹,对高风险目标做一次彻底探测。
这样做的好处是,一旦出现漏报,至少可以在下一轮基线扫描里暴露出来,不会长期积压。安全这件事最怕的不是发现问题,而是问题一直不存在于你的视野里。
5.4 安全工具本身也要被管住
这一点我在复盘后感触特别深:AI-Infra-Guard 持有访问 AI 服务的 Token,如果你的 Token 权限过大、存储不当,那它就是一个新的被攻击面。我后面把 Token 存放方式从环境变量改成了单独挂载的 secrets 文件,并限制了控制台访问来源 IP。同时把扫描引擎所在的容器网络与其他业务网络隔离,尽量让安全工具保持“旁观者”身份。如果你部署的目的就是扫描业务网络,那低配置一个专用网络把扫描流量引到目标接口即可,别把扫描器直接放进业务网络里。
5.5 找回文档和实际的一致性是长期功课
这次漏报的资产路径偏差,本质上是因为实际网关路由配置更新了,但填写资产时还在用旧的统一入口。也就是说,不是工具扫描能力不行,是资产台账和线上事实脱节了。我后面的做法是让扫描资产清单直接从网关配置中心同步导出,而不是人工录入。自动化同步做不到的情况下,至少每次扫描前手动核对一遍目标路由是否有变化。资产台账跟得上变化,扫描的覆盖率才有基础。
6. 总结
说实话,部署 AI-Infra-Guard 只花了几十分钟,真正值回时间的是那次漏报带出来的整条排查链路。它让我更加确信一个判断:像 AI-Infra-Guard 这样的技能扫描工具,解决的是“看得见风险”的问题,但前提是你得把资产路径录准、响应特征做足、Token 权限收住,并且真的把每一次漏报当成升级检测能力的素材。如果你打算在自建的大模型服务或 Agent 底座上部署类似工具,建议先给自己提三个问题:目标真的把风险链路暴露给扫描器了吗?扫描响应特征库覆盖了“静默容忍”型接口吗?扫描结果有没有人定期对账和复核?这三个问题想清楚,部署效率会完全不一样。