「AiSOC 拆解」开源AI安全运营中心实测:833条检测规则+可审计AI分诊,自托管怎么搭
原创
句芒安全实验室
句芒安全实验室
句芒安全实验室
2026年9月26日 12:07
上海
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
凌晨两点,告警队列还挂着三百多条没处理。值班的人做的其实是同一件事:一条一条点开,看主机名、看进程名、看命令行,判断\"这是真的还是误报\",然后写一句结论关掉。真正该动手的那两三条,就埋在这三百条里。
这几年所有人都在说\"让 AI 来分诊\"。但真到了现场,问题不在它会不会判,而在——它给你一个\"真阳性,置信度 80\",你敢照着它直接关告警吗?它凭什么这么判、判错了谁负责、事后怎么复盘?
GitHub 上有个项目把这个问题正面回答了。它叫 AiSOC,一个开源、可自托管的 AI 安全运营中心。
先核身份
按老规矩,发布前用 GitHub API 当天核实。仓库 beenuar/AiSOC,2368 颗星、259 个 fork;主语言 Python,协议 MIT;2026 年 5 月 2 日建仓,最近一次推送就是今天(2026 年 9 月 26 日)。README 徽章上的最新版本是 v11.0.0(2026-09-25)。文档站在 beenuar.github.io/AiSOC。
先记一个细节:三个月前它还是 v7.x,现在已经到 v11.0.0。版本跳得这么快,说明功能在猛堆。也正因为这样,下面要讲的\"它自己承认哪些没做好\",才是这个项目最值得看的部分。
一条告警进来,会走完九步
它的 README 把整条链路拆得很清楚,我照着官方架构文档顺一遍:
第一步,遥测进来。 要么是连接器按计划轮询厂商 API,要么是工具直接推到 ingest 的 HTTP 接口(POST /v1/ingest/batch)。
第二步,归一化。services/ingest 把厂商的原始载荷映射成一份 OCSF 形状的通用信封。有厂商专用 profile 的走厂商映射;没有的落到一份厂商中立的通用 profile,按固定顺序去猜 actor.user.name、device.name、src_endpoint.ip 这些字段——注意它认的是 user / username / actor 这种各家写法,不是只认一种。
第三步,进事件脊柱。 归一化后的数据发到 Kafka 主题 aisoc.raw_events。这一步是整个系统的解耦点:下游谁要消费都行,ingest 不需要知道有谁在听。
第四步,fusion 消费并跑检测。services/fusion 拿这条事件去跑 833 条可执行规则,同时独立判断它是否\"可提升\"——厂商发现类(OCSF 类别 2)或者严重度 ≥ high 的,才变成告警;日常遥测不会。
第五步,关联。 新告警拿关联键 {tenant}:{entity}:{tactic} 去比对未关闭事件,要么并进已有事件,要么新开一个。十条相关告警,最后变成分析员要看的一件事。
第六步,落库并广播。 写进 Postgres,同时发到 aisoc.alerts.fused。
第七步,两个消费者接手。services/realtime 通过 WebSocket 推到控制台;services/agents 用 LLM 自动分诊,给结论、置信度和建议动作。
第八步,AI 的每一步都写进 Investigation Ledger。 提示词、工具调用、引用、结论、token 成本,全部留痕。
第九步,响应仍然受管。 没有任何东西自动执行。动作先被提议,由有对应权限的人批准,结果还要回厂商那边核实,而不是看到 HTTP 200 就当成功。
官方在这里加了一句我很喜欢的话:第九步没有自动触发器,仓库里没有任何一条代码路径可以绕过人直接下发响应。这是故意的,也是这个项目里\"自主\"二字的诚实边界。
它自己写了一篇\"现实审计\",而且写的是自己怎么翻车的
这是我看完整个仓库后,觉得最该拿出来讲的部分。
docs/audit/REPOSITORY_REALITY.md 是一份 2026-09-23 对 v8.1.0 的审计,开头就写明:下面每一条都是读实现、跑栈得出的,不是看文件名和文档猜的;验证不了的,就直接写验证不了。
它承认了一件很难堪的事:在此之前,README 的快速开始根本没跑过这条管线。 老的 install.sh 会交给一个九服务的 compose 文件,里面没有 ingest 服务、没有 fusion 服务,还写着 AISOC_DISABLE_KAFKA: true,唯一的内容来自 seed_demo.py 直接往 Postgres 里写的 15 条编造事件。新用户照着 README 走,看到的是一个满屏数据的控制台,于是得出结论\"这平台能跑\"——其实他从头到尾没跑过这个平台。
它还把自己\"只跑起来才看得见\"的四个缺陷列了出来:
- 每条告警的
connector_type都读成了\"crowdstrike crowdstrike\"——厂商和产品名拼在一起没去重,同样的错误在同一个 helper 的两份拷贝里各有一处。 - 告警的
description是str(raw_data)序列化出来的原始事件,控制台本该显示一句话的地方,显示的是{\"command_line\": \"powershell.exe -nop ...,把厂商自己写的描述丢了。 - Kafka 的 healthcheck 在一个写不了盘的 broker 上照样报
healthy:Docker 虚拟机磁盘满了,Kafka 写不了meta.properties,拒绝一切请求,compose 还是说它健康。 - CrowdStrike 的告警进到 fusion 时没有 actor。它第一次记的结论是\"缺 normalizer profile\",这是错的:真正的原因有两个,连接器从没读过 Falcon 放在
behaviors[].user_name里的身份,而 canonical 字段映射只认actor这一种写法——68 个 canonical 连接器里 40 个用actor,另外 11 个用username或user,全都映射不到地方。因为 fusion 的关联键是{tenant}:{entity}:{tactic},缺 actor 不只是空一列:所有受影响的告警会全部关联进同一个unknown桶。
这段为什么重要?因为它同时说明了两件事:一,这个团队愿意把\"我们的 README 曾经是假的\"写进仓库;二,这套\"先跑起来、再写结论\"的做法,本身就是做安全的人该有的姿势。
AI 分诊怎么做到可审计
回到最开头那个问题:AI 给你的结论凭什么信。AiSOC 的答案是三条被写进代码的约束。
第一,提示词合同在请求发出之前就跑。 一份即将带上原始 OCSF、厂商原始日志行或者密钥形状值的提示词,会被直接拒绝,而不是事后打码。注意这个顺序:是\"拒绝\",不是\"脱敏后照发\"。
第二,引用要对着证据核对。 一个结论如果引用了一个证据里从来没出现过的指标,会被降级到人工复核,而不是自动关闭。
第三,审批是\"授权\"而不是\"记录\"。 审批人必须持有这个动作要求的权限层级,而且不能是提出这个动作的人——职责分离。
它自己的说法是:agent 可以读告警、它的关联兄弟、实体上下文和同一签名下的历史结论;它可以调类型化工具——lake 查询、图遍历、情报查找——模型选工具、传参数,但它永远不写 SQL;而提示词、工具调用、引用、结论、token 成本,全部写进 Investigation Ledger。
对做 AI 安全的人来说,这三条比\"我们支持 MCP\"重要得多:它把\"AI 被提示注入之后拿去干坏事\"的收益面,直接从\"能不能骗过模型\"挪到了\"能不能拿到权限\"。
真实数据和合成数据,它分得很开
这一点我觉得比任何功能都重要,所以单独说。
它把数据分成四类,而且给了你在界面上自己分辨的方法:
真实的——你自己的连接器和 ingest 接口,is_synthetic = false,这是默认值。
真实但不属于你的——Threat Intelligence 页面上的 CISA KEV 数据,1,725 条,来自公开的 CISA 已知被利用漏洞目录,原样不动,不需要 key。上面那张图就是它。
Demo 的——make demo 灌进去的数据,每一行在数据库里标 is_synthetic = true,控制台里也标出来。
基准测试的——services/agents/tests/eval_data/,每一行标 substrate: true。
这里有个我很欣赏的设计:出处是数据库里的一列,不是一句约定。 迁移 054_alert_provenance.sql 给 alerts 表加了 is_synthetic、synthetic_source、synthetic_scenario 三个字段,默认是\"非合成\",所以真实管线不可能被误标成合成。而在此之前,唯一的标记是 tags 数组里的一个 \"demo\" 字符串——最像真数据的那些 seed 行,恰好把它漏掉了。
还有一个细节:seed_demo.py 原来没有任何护栏,DATABASE_URL 指向哪它就往哪写。现在它在非开发环境下会拒绝执行,除非显式设 AISOC_ALLOW_SEED=1。
它的基准测试分数表也很有意思。公开的 scoreboard.json 里,最新一行是 2026-09-25、v11.0.0,substrate: true:MITRE 准确率 0.97、告警降噪 0.753、调查完整度 0.942、响应质量 1.0、剧本完成率 0.505。但同一行里 mtc_p50、mtc_p95 是 null,token 和美元成本都是 0。
为什么?因为它自己写得很清楚:这一行是确定性档,没有调 LLM,所以 token 和成本当然是 0;substrate: true 的行不能当作带 LLM 的实时 agent 表现来引用。 换句话说,这个项目把\"能证明的\"和\"还没测的\"分开放,而且明确告诉你别把前者当成后者。
上手:三条命令
它的上手比想象中简单,但门槛在内存和磁盘,不在凭证:
git clone https://github.com/beenuar/AiSOC && cd AiSOC
make up # CORE 档:14 个常驻服务,约 8 GB 内存
make up 会自己创建 .env、生成三个密钥(凭证库密钥、会话签名密钥、服务间 token),再创建一个管理员并打印密码。这个密码只在你机器上生成、只显示一次、不存任何地方,要么在终端滚走之前复制,要么用 make bootstrap ARGS=--reset-password 重新签发。
CORE 档不需要任何凭证就能跑通。原因有两个:本地模型随网关一起装——Ollama 跑一个固定的 llama3.2:3b-instruct-q4_K_M,约 2 GB,纯 CPU 推理,所以 make up 产出的就是真实的分诊结论和真实的 token 计数,不是桩;另外 services/threatintel 轮询 CISA KEV 目录,公开、不需要 key,是全新安装里唯一一个\"既不合成、也不属于你\"的东西。
然后是关键的一步——证明它真的能跑:
$ make smoke
[PASS] raw telemetry accepted by ingest
[PASS] event traversed the spine and became an alert
[PASS] alert is retrievable by id from the API
make smoke 往 ingest 接口发一条真实事件,跟着它穿过 Kafka、fusion、检测、提升和 Postgres,再从公开 API 读回来。它不绕过任何一层,每一段单独报 PASS 或 FAIL,所以一旦坏了,它会告诉你坏在哪个边界上。
make up-full 是 22 个服务、约 12 GB,多出来的是事件湖(ClickHouse)、实体图(Neo4j)、全文检索(OpenSearch)、富化和定时连接器。
该避的坑
第一,别把本地模型当能用的分析师。 官方实测:19 次自动分诊里,只有 7 次返回了 schema 合法的输出,另外 12 次回落到确定性路径——这条 rail 会标出来是哪个回答的。它自己写得很直白:本地模型不是前沿模型,差别看得出来。想升级就自己配 OPENAI_API_KEY 或者换别的推理厂商。\"AI 给结论\"和\"AI 给可信结论\"之间,差的不是提示词,是这一行数字。
第二,别把基准分数当实时表现。 上面那行 0.97 是确定性档,没有 LLM,官方明确要求不能引用成带 LLM 的实时 agent 表现。真正带 LLM、带真实 token 和美元成本的行,要等它每周的评测任务跑起来才会有。
第三,它自己说了不是什么。 不是 SIEM 的平替——它做关联和调查,不替代长期日志留存和合规检索;看不见你没接的遥测——它不做发现;默认不自主——响应要显式策略授权加人工审批;demo 的事件不是真实事件,基准语料不是客户遥测。
第四,内存和磁盘是硬门槛。 官方数字是 Docker 虚拟机里 8 GB 内存、20 GB 空闲磁盘,make doctor 会先查磁盘、再探端口、每个数据存储都真去查一次而不是问容器起没起,然后打印你下一步该跑什么。
它适合谁
如果你在中小团队里自己扛 SOC,想搞清楚\"AI 分诊到底能不能信、怎么留痕、怎么在自托管环境里跑通\",这个项目值得拉下来跑一遍 make smoke——它最大的价值不是功能列表,而是那篇把\"我们曾经哪里是假的\"写下来的审计文档。
如果你要的是开箱即用的商业 SIEM 平替、或者一个能自动处置告警的自主 agent,它不是——它自己也这么写。
最后
回到凌晨两点的告警队列。AiSOC 没有承诺\"AI 帮你看完三百条告警\",它承诺的是另一件事:AI 判的每一条,你都能查得到它凭什么这么判;查不到的,它自己会降级到人工。
对做安全的人来说,这个承诺比\"准确率 99%\"值钱得多。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。












评论