AppThreat/chen
GitHub: AppThreat/chen
chen 是一款从 joern 分支而来的多语言代码属性图(CPG)构建与数据流分析工具包,旨在对应用程序源代码及其依赖层次进行深度结构化探索。
Stars: 29 | Forks: 4
# chen
代码层次探索网络 是一款用于应用程序源代码及其依赖层次的先进探索工具包。本仓库包含 chen 库的源代码。
[](https://github.com/cdxgen/cdxgen)
## 环境要求
- Java >= 23
- 至少 16GB RAM
## 支持的语言
- C/C++
- H (仅限 C/C++ 头文件和预处理过的 .i 文件)
- Java (需要编译)
- Jar
- Android APK 和拆分包 (.apkm, .apks, .xapk)。需要 Android SDK。请设置环境变量 `ANDROID_HOME` 或使用容器镜像。拆分包会被解包,并对包含 dalvik 字节码的 APK 进行分析。Android 标记器会将语义标签附加到可达流上,包括个人身份信息、受监管数据(如 `pci-dss`、`gdpr` 和 `phi-medical`)、机密信息、第三方 `tracker` SDK,以及网络方向标签(如 `service-egress`、`service-ingress` 和 `on-device-ai`)。
- JavaScript
- TypeScript
- Flow
- Python
- Python (支持 3.x 到 3.13)
- PHP (需要 PHP >= 7.4。支持 PHP 7.0 到 8.4,对 PHP 5.x 的支持有限)
- Ruby (需要 Ruby 3.4.7。支持 Ruby 1.8 - 3.4.x 语法)
## 数据流引擎
`dataflowengineoss` 提供了两种可互换的到达定义 求解器:
- **Flux** (`FluxSolver`,_Flow-Lattice Update eXecutor_) — 默认求解器。这是一种低内存分配、结合数组和原地位集 的工作列表求解器,
它生成的 `REACHING_DEF` 边与经典引擎相同,但在大型(例如打包/转译后的 JavaScript)方法上消耗的内存和 GC 时间要少得多。它使用写时复制的定义
集合,因此未更改的节点会共享状态,而不是每个节点都分配一个位集。
- **Classic** (`DataFlowSolver`) — 最初的基于映射的不动点求解器,保留作为过程内 内核以及用于 A/B 对比测试。
下游工具可以通过 `EngineConfig.useFluxEngine` / 数据依赖传递来选择引擎;
在 [atom](https://github.com/AppThreat/atom) 中,Flux 引擎和按文件片段缓存默认是开启的,
而 `--legacy-dataflow` 会切换回经典引擎。
## 性能调优 (系统属性)
这些运行时调节参数适用于任何基于 chen/overflowdb2 构建的工具 — 只需将它们作为 JVM `-D` 标志传入,
无需重新构建:
- **`-Dodb.storage.compression=none|lzf|deflate`** — 用于当图溢出堆内存时将节点转储到磁盘的压缩器。在大型代码库中,转储/保存路径是单线程的,因此这通常会主导生成和切片的时间。`deflate` (默认值) 生成的存储文件最小,但速度明显较慢;`lzf` 速度快几倍,但体积稍有增加;`none` 会跳过压缩。压缩器会按
数据块进行记录,因此用一种模式写入的存储可以用另一种模式正常加载。给 JVM 分配更多堆内存 (`-Xmx`) 可以完全减少转储现象。
- **`-Dchen.cache.disabled=true`** (或 `-Dchen.cache.disabled.=true`) — 禁用 AST / CPG /
摘要缓存,用于 A/B 对比测试或故障排除。
## 方法流摘要
`dataflowengineoss` 可以为每个方法计算与上下文无关的流摘要。
`MethodFlowSummary` 会记录哪些形参可以到达方法的返回值以及哪些可以到达其输出参数,同时记录返回值和每个输出参数是否可能被方法内部的原点所污染。由于这些事实是基于参数和返回位置而不是基于某次特定调用的节点来表示的,因此摘要可以在每个调用点被复用。
```
import io.appthreat.dataflowengineoss.queryengine.summaries.FlowSummaryComputer
// Build summaries for every internal method, callee before caller.
val summaries = FlowSummaryComputer.computeAll(cpg)
// Or reuse a cached set, recomputing only when a method body changed.
val cached = FlowSummaryComputer.loadOrCompute(cpg, cacheDir = ".")
```
摘要是在调用图上按照“被调用者先于调用者”的顺序构建的;相互递归的方法会形成一个强连通分量,并被迭代至不动点。该集合可以通过两种方式进行持久化:一是作为每个 `METHOD` 节点上的 CPG 原生 `flow-summary` 标签(使用 `FlowSummaryTagsPass` 写入,使用 `FlowSummaryTags.fromCpg` 读回),这样事实数据会随图一起序列化,并在重新加载时无需重新计算;二是使用 `FlowSummaryStore`(一个单一的 JSON 文件,以方法体和活动语义的指纹作为键),受 `CacheControl.Summary` 控制。
数据流语义会被严格遵守。声明了语义的方法将从该语义而不是其方法体中获取其摘要,因此,声明的净化器 (sanitizer,一种没有映射的语义) 在摘要中表现为不向其返回值传递任何内容,而直通 (pass-through) 语义会转发每一个非接收者 参数。
将 `Semantics` 传递给 `computeAll` / `loadOrCompute` 即可启用此功能 (atom 会传递其默认的语义)。
当设置了 `EngineConfig.useSummaries` 并提供了摘要映射时,后向查询引擎会消耗这些摘要:
```
val context = EngineContext(
semantics,
EngineConfig(useSummaries = true, summaries = summaries)
)
```
在此模式下,引擎会修剪掉那些经摘要证明无法携带污点的跨调用任务(例如,探索被调用者从未写入的输出参数,或者深入探究其返回值不可能携带污点的被调用者)。这种修剪只会移除可证明为空的工作,因此报告的流与禁用摘要时的运行结果完全一致。atom 会将摘要作为其默认 Flux 捆绑包的一部分开启(没有单独的标志;`--legacy-dataflow` 会同时禁用 Flux 引擎和摘要)。
## 通过验证器和净化器过滤流
`reachableByFlows` 会返回 `Path` 值,并且数据流语言层提供了两个节点谓词过滤器,它们比旧版的 `passes` / `passesNot` 遍历组合器要容易使用得多:
```
import io.appthreat.dataflowengineoss.language.*
flows.passesThrough(_.isCall) // keep flows touching a matching node
flows.doesNotPassThrough(n => sanitizerIds(n.id)) // drop flows touching a matching node
```
`ChennaiTagsPass` 可以对声明过的净化器/验证器的调用进行标记,以便这些过滤器有内容可匹配。该过程会从 `chennai.json` 中读取 `sanitizers` (和 `validators`) 部分,或者从传递给其构造函数的配置字符串中读取:
```
{
"sanitizers": [
{
"name": "owasp-encode",
"methods": ["org\\.owasp\\.encoder\\.Encode\\..*"],
"categories": ["http"]
}
]
}
```
每个匹配的调用都会被标记为 `sanitizer`,并且对于每个声明的类别都会加上一个 `sanitizer-` 标签。
在 [atom](https://github.com/AppThreat/atom) 中,这是通过 `reachables --validation-config` 暴露出来的,
该配置会丢弃那些经过了涵盖该流汇聚点 (sink) 类别的净化器的可达流。
## chen 的起源
chen 是流行的 [joern](https://github.com/joernio/joern) 项目的一个分支。我们在以下几个方面与 joern 项目有所不同:
- 保留基于原始论文的 1.0 版本的 CPG 实现。
- 实现更广泛的层次化分析 (应用层 + 依赖层 + 容器层 + 操作系统层 + 云层及以上)
我们不打算做到逐个 Bug 的完全兼容,并且经常会重写补丁以满足我们的需求。我们也不会引入那些对层次化分析没有价值的功能和处理过程。
## 许可证
Apache-2.0
## 企业支持
可通过 AppThreat Ltd. 获取企业支持,包括自定义语言开发和集成服务。
## 赞助商
YourKit 以其创新且智能的监控和分析 Java 及 .NET 应用程序的工具支持着开源项目。
YourKit 是 YourKit Java Profiler、YourKit .NET Profiler 以及 YourKit YouMonitor 的创造者。

代码层次探索网络 是一款用于应用程序源代码及其依赖层次的先进探索工具包。本仓库包含 chen 库的源代码。
[](https://github.com/cdxgen/cdxgen)
## 环境要求
- Java >= 23
- 至少 16GB RAM
## 支持的语言
- C/C++
- H (仅限 C/C++ 头文件和预处理过的 .i 文件)
- Java (需要编译)
- Jar
- Android APK 和拆分包 (.apkm, .apks, .xapk)。需要 Android SDK。请设置环境变量 `ANDROID_HOME` 或使用容器镜像。拆分包会被解包,并对包含 dalvik 字节码的 APK 进行分析。Android 标记器会将语义标签附加到可达流上,包括个人身份信息、受监管数据(如 `pci-dss`、`gdpr` 和 `phi-medical`)、机密信息、第三方 `tracker` SDK,以及网络方向标签(如 `service-egress`、`service-ingress` 和 `on-device-ai`)。
- JavaScript
- TypeScript
- Flow
- Python
- Python (支持 3.x 到 3.13)
- PHP (需要 PHP >= 7.4。支持 PHP 7.0 到 8.4,对 PHP 5.x 的支持有限)
- Ruby (需要 Ruby 3.4.7。支持 Ruby 1.8 - 3.4.x 语法)
## 数据流引擎
`dataflowengineoss` 提供了两种可互换的到达定义 求解器:
- **Flux** (`FluxSolver`,_Flow-Lattice Update eXecutor_) — 默认求解器。这是一种低内存分配、结合数组和原地位集 的工作列表求解器,
它生成的 `REACHING_DEF` 边与经典引擎相同,但在大型(例如打包/转译后的 JavaScript)方法上消耗的内存和 GC 时间要少得多。它使用写时复制的定义
集合,因此未更改的节点会共享状态,而不是每个节点都分配一个位集。
- **Classic** (`DataFlowSolver`) — 最初的基于映射的不动点求解器,保留作为过程内 内核以及用于 A/B 对比测试。
下游工具可以通过 `EngineConfig.useFluxEngine` / 数据依赖传递来选择引擎;
在 [atom](https://github.com/AppThreat/atom) 中,Flux 引擎和按文件片段缓存默认是开启的,
而 `--legacy-dataflow` 会切换回经典引擎。
## 性能调优 (系统属性)
这些运行时调节参数适用于任何基于 chen/overflowdb2 构建的工具 — 只需将它们作为 JVM `-D` 标志传入,
无需重新构建:
- **`-Dodb.storage.compression=none|lzf|deflate`** — 用于当图溢出堆内存时将节点转储到磁盘的压缩器。在大型代码库中,转储/保存路径是单线程的,因此这通常会主导生成和切片的时间。`deflate` (默认值) 生成的存储文件最小,但速度明显较慢;`lzf` 速度快几倍,但体积稍有增加;`none` 会跳过压缩。压缩器会按
数据块进行记录,因此用一种模式写入的存储可以用另一种模式正常加载。给 JVM 分配更多堆内存 (`-Xmx`) 可以完全减少转储现象。
- **`-Dchen.cache.disabled=true`** (或 `-Dchen.cache.disabled.标签:DNS重绑定攻击, JS文件枚举, WebSocket, 云安全监控, 代码分析, 依赖分析, 凭证管理, 静态分析