TL;DR
模式匹配扫描器(Semgrep / Snyk / CodeQL)能找出规则库里写过的漏洞,但很多真实 bug 是结构变体 ------ sink 和 source 之间隔了三层函数、污点被重命名过、CVE 的 pattern 稍微换了个马甲这种就漏了。
mythos-agent 是一个开源的 AI 代码安全智能体(MIT, TypeScript, GitHub),思路是在传统 SAST 之上加一层基于 LLM 的假设生成 stage,用"大胆假设、小心求证"去补规则库覆盖不到的盲区。

这篇文章聊一下这套 pipeline 是怎么设计的、能抓到哪些规则扫描器抓不到的 bug、以及哪些场景下它依然会翻车(这部分在第六章,想先看的话直接跳过去)。
bash
npx mythos-agent scan # 纯规则扫描,不需要 API key
npx mythos-agent hunt # 完整 AI 假设 + 验证流水线
一、为什么传统扫描器会漏掉结构变体
pattern 扫描器的规则集本质上是一组有限的 (sink, source, condition) 三元组。但人做代码审计时用的心智模型比这大得多 ------ 人会注意到这个 事务对同一行先读后写没加锁、这个 handler 把用户传的路径拼到 config root 上但没解析 symlink、这个 eval 接受了从三个函数外 stringify 过来的值。
举个具体例子。Semgrep 默认的 TypeScript 规则集能抓这个:
ts
app.get('/run', (req, res) => {
eval(req.query.code); // 会被标记:eval() 接受了请求输入
});
但抓不到下面这个,虽然这俩本质是同一个 bug:
ts
function normalise(input: unknown) {
return String(input).trim();
}
function buildPayload(raw: string) {
return normalise(raw);
}
app.get('/run', (req, res) => {
const payload = buildPayload(req.query.code as string);
new Function(payload)(); // 抓不到:sink 不是 eval,source 在两层函数外
});
规则在找的是字面的 eval(<污点>)。真实的 bug 其实是 <任意动态执行 sink>(<污点,可能已变形,可能已改名>)。你当然可以再写一条 Semgrep 规则覆盖这个变体 ------ 但你只能为已经想到的变体写规则。「和 eval 行为类似的 sink」这个集合是开放的,枚举不完。
二、思路:让 LLM 给每个函数"提假设"
mythos-agent 的 pipeline 分四个阶段:
Recon → Hypothesize → Analyze → Exploit(默认关闭)
最有意思的阶段是 Hypothesize 。对 parser 抽出来的每个函数,一个带特定 prompt 的 LLM agent 会产出针对这段代码 的、具体的安全假设 ------ 不是给一个笼统的 CWE 标签,而是对这个函数作出具体声明:
"这个 handler 读了
req.query.path并通过path.join(ROOT, userPath)传给fs.readFileSync,但没解析 symlink。如果文件系统里有指向 ROOT 外的 symlink,可能是路径穿越。"
"这个事务在第 42 行读balance,在第 51 行写balance - amount,没有包在SELECT ... FOR UPDATE或等价的锁里。并发请求下可能 TOCTOU 竞态导致双花。"
这些假设不是给用户看的输出,而是下一个阶段的输入。
三、Analyze 阶段:给假设打分
另一个 analyzer agent 会带着前一阶段生成的假设重新读这段函数,根据控制流、输入可达性、sink 特征判断假设是否真的成立。每条 finding 带一个 [0, 1] 的置信度;--severity high 只输出置信度超过阈值的结果。
两个阶段分开非常重要。 Hypothesize 阶段允许"大胆猜",允许它产出大量不一定成立的假设 ------ 生成假设的成本很低,analyzer 会帮着筛。Analyze 阶段反过来,允许它保守。
把这两步合成一个 prompt 会退化成"模型既出题又打分",实测的结果就是输出一堆看起来合理但其实不存在 的 FP。拆成两个 agent 之后,--severity high 这种阈值过滤才真的有意义。
实际输出样例(在一个测试仓库上跑出来的):
sql
✗ src/api/transfer.ts:38 [HIGH, conf 0.88]
Hypothesis: 对 balance 的读-改-写没加行锁,并发请求下可能双花。
Evidence: line 42 读 balance,line 51 写 balance - amount;
作用域内没有 FOR UPDATE / 事务隔离。
Suggested: BEGIN ... SELECT ... FOR UPDATE ... COMMIT,
或 SERIALIZABLE 隔离级别。
四、Structural Variant Analysis:找 CVE 的"亲戚"
给定一个参考 CVE(从 NVD 或者用户提供的 patch),variant analyzer 会在目标代码库里搜 AST 形态相似 的代码块,再对输入和 sink 做语义角色匹配。思路跟 Google Project Zero 公开的 Big Sleep writeup 里描述的那套类似,只不过是在一个开源 TypeScript 工具链里实现。
这个功能真正解决的场景是:「A 模块里的 X bug 我们已经 patch 掉了,代码库里还有没有长得像 patch 前 A 模块的地方?」在 git diff 上跑 regex 发现不了,因为变体可以改变量名、换语句顺序、拆 helper 函数出去。
五、目前是什么样
- 43 个扫描分类(15 个正式上线,28 个实验中):SQL 注入、SSRF、路径穿越、命令注入、XSS、JWT 算法混淆、session 处理、竞态、加密误用、secrets、IaC 配置错误、供应链、AI/LLM 安全、API 安全、云配置、零信任、隐私/GDPR、GraphQL、WebSocket、CORS、OAuth、SSTI 等
- 329+ 条内置规则 ,覆盖 8 种目标语言(TypeScript、JavaScript、Python、Go、Java、PHP、C/C++、Rust)。规则是可组合的 ------ "SQL 注入"不是一条 regex,而是 N 条更小的规则(字符串拼接到 sink、带污点插值的 template literal、带 raw-SQL escape hatch 的 query builder 等)
- 输出:SARIF 2.1.0(GitHub Code Scanning 直接能用)、HTML 报告、JSON(可以管道给下游工具)
- 后端 :Claude、GPT-4o、Ollama,以及任意 OpenAI 兼容的端点。纯规则模式完全离线,不需要任何 API key ------ Hypothesize stage 是可选的,按需开启
- 发布产物用 Sigstore (cosign) 签名,每次 release 都附带 CycloneDX SBOM
六、坦白讲,还有这些坑没填好
假设驱动的扫描不是免费午餐,以下是已知的局限:
- 动态类型语言(Python、JS)比静态类型语言 FP 多。类型信息是 analyzer 阶段的重要信号,没有的话置信度整体偏低,高置信阈值过滤掉的东西也更多。
- 跨第三方依赖的污点追踪会丢信号。污点流进了一个没源码的 dep,Hypothesize 阶段只能按 public API 推测,容易过度生成。
- 成本 。全仓跑假设生成,用 Claude 或 GPT-4o 一次不便宜。
--severity high过滤有帮助;增量扫描(只扫改动过的文件)帮助更大。建议 CI 里 scope to diff-only。
七、三条命令先跑起来
最低门槛,不装不配置,不需要 API key(pattern-only 模式):
bash
npx mythos-agent quick # 10 秒快速体检
npx mythos-agent scan # 完整规则扫描
npx mythos-agent hunt # AI 假设 + 验证(需要 LLM 端点)
npx mythos-agent fix --apply # 对高置信 finding 自动生成并应用 patch
- GitHub :github.com/mythos-agen...
- 主页 / 文档 :mythos-agent.com
- 发布产物:Sigstore 签名,附带 SBOM
MIT 协议,v4.0.0 今天刚发。如果你手头有想测试假设生成的代码库(公开的或脱敏过的片段都行),欢迎开 issue 我特别想收集 analyzer 产出的意外 FP 例子,这是目前微调 prompt 最有用的反馈。
问题
- "先出假设再验证"这套两阶段路子,你们在类似系统里有没有踩过坑?哪些假设类型特别容易翻车?
- 对动态类型语言的 AST-shape 归一化,你们有什么经验?有没有方法能在 Python / JS 上稳定地算 structural similarity?
- SARIF 2.1.0 除了 GitHub Code Scanning,你们见过哪些下游消费者能把字段完整渲染出来?哪些会 silently 吞字段?
谢谢阅读。觉得有用的话 ⭐ star 一下;发现 bug 或 FP 请带最小复现开 issue。