返回 REA 专题 →

可复现实战 · 源码静态分析

REA 实战:找出 Electron 的 CSV 导出通道

用 REA 6.5.0 分析自建 Electron 源码样例,识别 preload 接口和 IPC 通道;附可下载样例、复现脚本、真实结果与失败记录。

实测日期

实测日期:2026-10-17。我们写了一个五文件的 Electron 源码教学样例,用 npm 发布的 REA 6.5.0 做静态分析,再从 notes:export-csv 通道发起追踪。本文提供样例、复现脚本与真实结果摘录。

本次完成的是源码静态分析,不是启动应用后的点击测试。 没有打包 ASAR、安装 Electron、连接原生分析引擎,也没有验证 CSV 实际写入。你不需要拿第三方商业软件来跟做。

下载教学样例与复现脚本(ZIP)。解压后先读 README;results-excerpt.json 是删去宿主路径的结果摘录,不是完整 REA Evidence。

先看这次找到了什么

检查点 本次实际结果 能说明什么
目标材料 5 个相关文件,解析 3 个 JavaScript 文件 这是小型源码样例,不代表大型打包应用的覆盖率
preload 桥接 notesApi,成员 exportCsv 静态语法中存在这个暴露接口
IPC 配对 1 个字面量通道,1 次 renderer 发送,1 个 main handler;发送配对数为 1 分析器把同名发送与处理函数关联起来
通道追踪 匹配 1 个 seed,返回 29 个节点、40 条边 得到该 seed 可达的图关系,不等于 29 个文件或 40 次真实调用
解析失败 0 本轮未报告解析失败,不代表所有行为均已证明

REA 的图中既有语法观察,也有推断。追踪摘要记录 26 个 observed facts、45 个 inferred facts;unknown_facts: 0 只属于这个追踪结果,不能解读为程序已经没有未知行为。

第一步:看清样例的三层分工

下载包的 app 目录包含 package.json、main.js、preload.js、renderer.js 和 index.html。这是 FollowAgents 自建教学材料;依赖没有打包在 ZIP 中。

源码设计的路线是:

导出按钮(index.html)
  → 点击处理(renderer.js)
  → window.notesApi.exportCsv()
  → preload.js 的 ipcRenderer.invoke('notes:export-csv')
  → main.js 的 ipcMain.handle('notes:export-csv', ...)
  → handler 中的 fs.writeFile(...)

这张路线来自对样例源码的阅读;下面再用 REA 返回的接口和通道证据核对。不要把这张图当成已经捕获的运行时轨迹。

preload.js 的关键部分是:

contextBridge.exposeInMainWorld('notesApi', {
  exportCsv: () => ipcRenderer.invoke('notes:export-csv')
});

主进程注册同名通道,在 handler 中拼接教学用的固定行并调用 fs.writeFile。示例省略了生产级的调用方验证等设计,不适合作为生产 IPC 安全模板。

第二步:固定版本,保存完整分析结果

本次环境是 macOS arm64、Node.js 24.19.0、REA 6.5.0。REA 当前文档支持 Node.js 22.19+ 的 22 系列、24.11+ 的 24 系列及 26+;不要把系统已有 Node 等同于版本满足要求。Windows、Linux 未在本案例中实测。

在解压后的 rea-csv-lab 目录运行:

node -v
npm -v
npx -y [email protected] analyze-javascript-application ./app --json > application-evidence.json

-y 允许 npm 下载并执行固定版本的官方包。这里不运行 setup,不修改助手的 MCP 配置,也不用在 app 中安装 Electron。REA CLI 与助手接入是两条不同的使用入口。

成功输出是 Evidence 记录,operation 为 analyze_javascript_application,分析结果在 normalized_result 内。先确认没有返回 error,再继续;不要只因生成了 JSON 文件就判成功。

第三步:用真实通道构造追踪输入

下载包的 make-trace-input.mjs 读取刚生成的完整 Evidence,创建如下请求:

{
  application,
  seed: { kind: 'channel', value: 'notes:export-csv', match: 'exact' },
  direction: 'both'
}

依次运行:

node make-trace-input.mjs
npx -y [email protected] trace-application-feature ./trace-input.json --json > trace-evidence.json
node verify-results.mjs

verify-results.mjs 检查实际输出中的桥接成员、IPC handler、静态配对和匹配 seed。它不会启动应用,也不会把 CSV 是否存在当作静态分析的验收条件。

第四步:把结论落回文件与证据

本次 Evidence 在 preload.js 第 3–5 行记录到 notesApi 和 exportCsv;在 main.js 第 16–22 行记录到 notes:export-csv 的 handler。renderer 发送与 main handler 的配对数是 1。

这支持“样例的桥接接口与同名 IPC handler 在静态图中被识别并关联”。继续阅读 handler,可以看到代码尝试把 CSV 写向 Documents 下的 rea-notes.csv;但路径解析是否成功、文件是否写入、按钮是否实际可达,都需要另做运行时验证。

完整 Evidence 会包含本机输入路径。分享前先检查内容;下载包只提供经核对的摘录,不能把摘录当成完整追踪输入。

这次实际遇到的两个问题

macOS 辅助程序编译失败。 第一次在受限沙箱内运行时,REA 报 execution_failure,诊断指向通过 xcrun 编译进程归属辅助程序失败。改在允许正常本地编译的环境运行后,同一份样例分析成功。静态分析不需要 Ghidra,并不意味着完全不需要宿主工具链;遇到这类报错应检查诊断和命令行编译工具,而不是反复重装 MCP。

seed 类型填错。 初次追踪把类型写成了 ipc-channel,6.5.0 返回 invalid_request。该版本接受的请求写法是 kind: 'channel'。这是本次请求构造错误,不是 REA 无法识别 IPC;本文脚本已经修正。

怎样继续,而不扩大本次结论

先改一下样例里的通道名,同时更新追踪请求,再重新分析,观察配对与 seed 匹配如何变化。修改文件后要生成新的 Evidence,不要拿旧结果解释新源码。

本案例仅覆盖自建小型源码目录。混淆代码、动态通道、原生插件和打包 ASAR 应另选目标验证;“静态图覆盖完整”也不等于行为覆盖完整。

如果助手看不到工具,先读 REA 安装与连接排错。要判断不同分析路径和工具需求,返回 REA 专题;项目能力与评审见 REA 详情。

官方依据:REA 仓库、CLI 与 Evidence、JavaScript 应用工作流、安装前提。官方 main 分支可能领先本文固定的 npm 版本。