【Code with SOLO】用 SOLO 构建跨语言 FFI 安全分析器 OmniScope — 10+ 真实项目,独立发现高危 CVE

【Code with SOLO】用 SOLO 构建跨语言 FFI 安全分析器 OmniScope — 10+ 真实项目,独立发现高危 CVE

1. 摘要

作为一名算法工程师,日常使用 Rust + C + CUDA 进行 GPU 加速计算开发,跨语言 FFI 交互是最高频也是最危险的环节。我借助 TRAE SOLO 构建了 OmniScope——一个基于 LLVM IR 的跨语言 FFI 资源安全静态分析框架。

v0.1.5 版本引入了 Zone Classification 架构——只分析语言安全保障失效的地方(unsafeextern "C"@cImportcgo),默认信任语言自身的安全机制。在 10+ 个真实开源项目上完成验证,覆盖密码学、WebAssembly、FFI 密集型等场景,wasmtime 可疑点从 4023 降到 9(-99.8%),并独立发现高危沙箱逃逸漏洞 GHSA-4pww-gw9q-vvvh。项目完全开源(Apache 2.0)。

2. 背景

我是一名算法工程师,日常工作涉及 GPU 加速算法开发,技术栈以 Rust + C + CUDA 为主:

Rust(业务逻辑)→ C(FFI 桥接层)→ CUDA(GPU 计算)
 ↑ ↑ ↑
 所有权模型 裸指针传递 设备内存管理
 最严格 最危险 最容易泄漏

每一层都有自己的内存管理哲学,拼在一起的时候,bug 不是"有没有"的问题,而是"什么时候炸"的问题。

我踩过这些坑:

  • Rust Box::into_raw() 把内存交给 C,C 侧 free() 后 Rust 侧 Drop 再跑一遍 → double free

  • CUDA cudaMalloc 的设备指针传给 C wrapper,C 又 malloc 了中间缓冲,哪个该谁释放?

  • Rust borrow 的指针传给 C,C 存进全局变量,Rust 以为借用结束了 → use-after-free

编译器不管、运行时不报、单元测试过得了、上线才炸。 现有工具(Clang SA、CodeQL、MIRI、Valgrind)都是单语言或运行时的,无法解决跨语言静态分析问题。

所以我决定在 LLVM IR 层 做统一分析——不管 Rust、C、Zig、Go,最终都编译到 LLVM IR。

3. 实践过程

架构图

任务拆解

  1. 设计三层资源状态机架构(Core Engine → Semantic Adapter → Boundary Analyzer)

  2. 实现数据驱动的语义映射规则系统(14 条规则覆盖 5 种语言)

  3. 构建 Pass 管线(CFG → DFG → Alias → Taint → Ownership),从 9 个扩展到 15 个

  4. 用合成测试集(Rust/C++/Zig/Go FFI)验证基础检测能力

  5. 用 5 个真实开源项目做大规模验证

  6. 【v0.1.5 新增】 实现 Zone Classification——识别语言安全域的逃逸点,只对 unsafe/FFI 边界深分析

  7. 【v0.1.5 新增】 密码学项目压测(ring、blst、zkcrypto 等)+ WebAssembly 运行时分析(wasmtime)

SOLO 的使用方式

  • 架构讨论伙伴 :讨论三层架构设计和资源状态机模型

  • 代码生成加速器 :核心分析 Pass 的 Zig 代码生成

  • 深度调试助手 :排查 LLVM C API 调用问题(见下方)

  • 安全审计员 :对 OmniScope 自身进行代码审计,5 轮审计发现并修复 15+ 个问题

  • 文档生成 :README、架构图、测试报告、Release Note

开发模式

约 20-30% 的代码为手敲 (核心架构设计、关键算法逻辑、AI 生成代码的 bug 修复),其余 70-80% 由 SOLO 辅助生成 。AI 负责大量重复性编码和文档工作,人类负责架构决策和质量把关。

踩过的坑

坑 1:LLVM C API 调用方式错误

CFG 构建时 crash,我以为是 LLVM 的 bug。给 SOLO 以下指令:

  1. 总结当前遇到的问题,节选出对应的代码片段

  2. 列出你认为存在的问题,是设计问题还是 LLVM 本身的 bug

  3. 输出为 markdown 供我分析

SOLO 信誓旦旦地告诉我"这是 LLVM 的 bug"。我让它把猜测输出成 markdown,然后自己去查 LLVM 文档和源码,发现其实是我的参数传递方式不对——LLVMGetOperand 返回 LLVMValueRef,而 bb_id_map 期望 LLVMBasicBlockRef。确认应使用 LLVMGetSuccessor() 后,一次修复。

教训:SOLO 给了方向,但验证还得靠自己。AI 会犯错,而且犯错时很自信。

坑 2:SOLO 误删项目文件(真实事故 )

让 SOLO 安装 LLVM 工具链时,操作失误导致项目文件被系统移到回收站 ,workspace 瞬间清空。万幸我提前做了 git 备份 ,完整恢复。

教训:用 AI 操作项目目录时,一定要有版本控制。AI 会犯错,而且犯的错可能很致命。 这也是为什么 OmniScope 的 README 反复强调"单一所有权"和"资源安全"——因为我自己就被"所有权丢失"坑过

坑 3:C++ 误报风暴

v0.1.3 分析 jsoncpp 产生 37 个内存泄漏误报。C++ 的 RAII 模式(智能指针、STL、异常处理)在 IR 层表现为 alloc 无显式 free。实现了 8 层 C++ 误报消除系统 (STL 过滤、RAII 检测、ABI 运行时过滤、Meyers 单例检测、引用计数容器检测等),jsoncpp 误报从 37 降到 0

坑 4:__memcpy_chk 噪音

glibc fortified 函数被误报为 FFI RISK,SQLite 中 278 处调用。添加 skip list 修复。

坑 5:噪音太多,找不到真 bug 【v0.1.5 关键转折】

v0.1.4 分析 wasmtime 产生 4023 个可疑点,实际有用的不到 1%。想明白了一件事:我不需要理解语言的安全规则,我只需要知道代码在哪一行开始不再安全。 于是实现了 Zone Classification——Rust safe code 跳过、Zig 普通 slice 跳过、Go 非 cgo 跳过,只盯着 unsafeextern "C"@cImportcgo 这些逃逸点。wasmtime 可疑点从 4023 降到 9

附与Solo 交互截图

附:我和solo的商业互吹

4. 成果展示

v0.1.5 Zone Classification 验证(10+ 项目)

项目 语言 函数数 跳过率 Issues 说明
ring Rust + C/asm 278 100% 0 Google 密码学库,零噪音
wasmtime Rust 619 74.3% 96 WebAssembly 运行时
blst Rust + C 267 64.0% 48 以太坊 BLS12-381 签名库
zkcrypto/bls12_381 Rust 259 66.4% 0 ZK 密码学原语
SQLite 3.47.2 C 3,237 - 8 基础验证
jsoncpp 1.9.5 C++ 1,537 - 3 C++ RAII 验证
zlib-binding Rust FFI 12 0% 14 FFI 密集型
openssl-wrapper Rust FFI 12 0% 7 FFI 密集型
gnark-crypto Go 838 29.8% 1 Go ZK 库
其他 - - - - ripgrep, rust-sqlite, ark-ff, libsodium 等

噪音消除效果

指标 v0.1.4 v0.1.5 变化
wasmtime 可疑点 4,023 9 -99.8%
UAF 误报 (blst) 185 48 -74%
分析耗时 (blst) 3100ms 836ms -73%
分析耗时 (ring) 793ms 269ms -66%

独立发现真实 CVE

用 OmniScope 分析 wasmtime IR 时,在 wasmtime_fiber_switchoccupy_next_slots 两个函数上标记了栈操作异常和边界检查缺失。去源码验证,对应 GHSA-4pww-gw9q-vvvh——一个真实的高危沙箱逃逸漏洞:

Continuation Control-Context Overwrite → Arbitrary Native Control-Flow Redirection → Sandbox Escape

攻击路径:Guest 代码创建小容量 continuation → trap/return 混淆 → cont.bind 越界写入 → 覆盖 saved RIP/RBP → 控制流劫持 → 沙箱逃逸。

这个漏洞是 OmniScope 从 IR 层面独立发现的模式,然后我去源码里定位确认的。

v0.1.4 基础验证(5 项目,5,180 函数)

项目 语言 函数数 Issues 泄漏误报 耗时
SQLite 3.47.2 C 3,237 8 0 5.8s
libcurl 8.14.0 C 68 1 0 0.05s
libuv 1.50.0 C 145 1 0 0.07s
jsoncpp 1.9.5 C++ 1,537 3 0 1.4s
abseil-cpp 2024 C++ 193 0 0 0.37s

版本迭代对比

指标 v0.1.3 v0.1.4 v0.1.5 变化
C++ 泄漏误报 37(jsoncpp) 0 0 -100%
RC 容器误报 9(abseil) 0 0 -100%
wasmtime 噪音 - 4,023 9 -99.8%
真实项目数 5 5 10+ +100%
分析 Pass 数 9 15 15+ -

支持的跨语言边界检测

调用方 被调用方 状态
Rust C Stable
C Rust Stable
Zig C Stable
Go C Experimental
C++ C Stable

项目规模(顺带宣传自己的开源项目)

项目 主要语言 代码量 状态
OmniScope Zig / C / Rust ~35,000 行 v0.1.5 已发布
MemScope-rs Rust ~100,000 行 已上线使用
GoAgent Go / Python ~63,000 行 已上线使用
合计 5 种语言 ~200,000 行 全部 Apache 2.0

项目地址

  • * OmniScope— 跨语言 FFI/Unsafe 安全分析器

  • MemScope-rs — Rust 内存分析与可视化工具

  • GoAgent — 多 Agent 协作开发框架

5. 效果与总结

OmniScope 是我构建的开发者工具集的一部分。从 MemScope(Rust 内存分析)到 OmniScope(跨语言 FFI 分析),再到规划中的 PloyScope,我在系统性地覆盖开发者最痛的安全分析环节。GoAgent 则是 AI 工程化实践——多 Agent 协作 + 记忆蒸馏 + 向量检索 + 长期记忆存储。

v0.1.5 的核心思路转变:不重建语言的安全语义,只识别语言在哪一行代码开始失效。 这让 OmniScope 从一个"什么都能扫但噪音爆炸"的工具,变成了一个"只扫危险地带且精准打击"的工具。

SOLO 在开发中扮演了三个角色:

  1. 架构讨论伙伴 :帮我理清三层架构和资源状态机设计

  2. 代码生成加速器 :核心 Pass 的 Zig 代码生成效率提升显著

  3. 深度调试助手 :CFG crash 时 SOLO 信誓旦旦说是 LLVM 的 bug,我自己查文档发现是参数传递方式不对。SOLO 给了方向,但验证还得靠自己。

当然,SOLO 也翻过车——它误删过我的项目文件,幸好有 git 备份。AI 是强大的工具,但开发者自身的工程素养(版本控制、独立验证、代码审查)才是底线。

所有工具均以 Apache 2.0 开源,因为我踩过的坑,不想让别人再踩一遍。

附图,对于sqlite3.ll 的分析图

3

1 个赞

高端玩家,牛逼

1 个赞

欢迎使用体验,及反馈 :grinning_face:

1 个赞

这个想法不错啊,试了一下,查询速度快,要是能改进误报率就好了

2 个赞

立意不错,有时间试试

2 个赞

架构做的很好,后续可以继续扩展,增肌更多的使用场景。加油

2 个赞

好的,我正在相关的事情,目前在测试多个zkp的repo,对项目进行改进,预计下周发布v0.1.5 版本

1 个赞

好的,谢谢体验和反馈

1 个赞

收到,正在做多语言多项目支持,目前支持了go←—> C(beta),rust ←—> C

1 个赞

蛮有新意的,加密算法库有没有测试数据呢?

1 个赞

高玩啊!!!

1 个赞

你说的那几个坑我都精准踩过 :sweat_smile:

1 个赞

欢迎使用,以及反馈

1 个赞

基础研发,很给力

2 个赞

给大佬跪一个!

1 个赞

互相学习,不敢当大佬 :rofl:

2 个赞

这么有想法的吗?

1 个赞

性能不错啊,正式上线了吗?

1 个赞

初版上线了,正在做架构调整,以及TP 提升

1 个赞

太专业了。:clap:

1 个赞