KirtashDev/dephawk

GitHub: KirtashDev/dephawk

一款 npm 依赖运行时行为监控与拦截工具,通过追踪依赖包对文件系统、网络、进程等敏感操作的实际调用来防范供应链攻击。

Stars: 1 | Forks: 0

# 🦅 dephawk ### 像老鹰一样敏锐地监控你的 npm 依赖。 **查看——并拦截——你的依赖在运行时的实际行为:** 读取你的 SSH 密钥、向外通信、启动 shell。 [![npm](https://img.shields.io/npm/v/dephawk.svg)](https://www.npmjs.com/package/dephawk) [![downloads](https://img.shields.io/npm/dm/dephawk.svg)](https://www.npmjs.com/package/dephawk) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/kellendir/dephawk/actions/workflows/ci.yml) [![license](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](#) [![stars](https://img.shields.io/github/stars/kellendir/dephawk?style=social)](https://github.com/kellendir/dephawk)
你安装了一个包。它有 40 个间接依赖。其中任何一个都可以读取 `~/.ssh/id_rsa`,获取你的 `NPM_TOKEN`,并将其 POST 到一个你从未听说过的服务器——而你根本不会察觉。 `dephawk` 在你的代码上空盘旋,**监控每一个依赖**。当某个依赖触及你的文件系统、打开 socket、启动进程,或从环境中读取敏感信息的那一刻,dephawk 就会将其记录下来,归属到确切的包,并且——如果你愿意——**拦截它**。 ``` npx dephawk run npm test ```
![dephawk 捕获恶意依赖读取你的 SSH 密钥、NPM_TOKEN 并向外通信的行为](https://static.pigsec.cn/wp-content/uploads/repos/cas/eb/ebe410b77b784d1955f249f36e339f101daa6dfade9c6fbb57f43f57d19e07df.svg)
这张截图本身就足以说明问题。如果一个包试图读取你的密钥并向外通信,这只“鹰”会在最初的几秒钟内发现它——而不是等你上了新闻之后。 ## 为什么需要 针对 npm 的供应链攻击现在已成常态:拼写劫持、维护者账号被盗、恶意的 post-install 脚本。静态扫描工具(Socket、`npm audit`)能起到一定作用,但它们无法看到混淆或动态加载的代码_在运行时的实际行为_。`dephawk` 是运行时的绊线:它不从源码猜测,而是监控实际行为。 ## 快速开始 **观察模式**(默认——记录一切,不拦截任何内容): ``` npx dephawk run npm test npx dephawk run node ./build.js ``` **强制模式**(拦截任何未明确允许的行为): ``` npx dephawk run --enforce npm start # 或者: DEPHAWK_MODE=enforce npx dephawk run npm start ``` 或者将其直接接入任何 Node 进程(遵循 `DEPHAWK_MODE`): ``` node --import dephawk/register ./your-app.js ``` 在退出时,dephawk 会打印上述摘要,并生成一个可分享、独立完整的 **`.dephawk/report.html`**。 ## 监控范围 | 能力 | 捕获示例 | | ---------------- | ------------------------------------------------------------------------------- | | `fs.read` | 读取 `~/.ssh`、`~/.aws`、`~/.gnupg`、`.env`、`.npmrc`、`/etc/passwd` | | `fs.write` | 覆盖 `~/.npmrc`、`authorized_keys` 及其他敏感文件 | | `net.connect` | `http`/`https`/`fetch`,以及原始 `net`/`tls` socket 和 UDP (`dgram`) | | `net.resolve` | `dns.lookup`/`resolve*` — 用于侦察和 DNS 隧道数据外泄(无需建立 TCP 连接) | | `process.spawn` | `child_process.exec`/`spawn`/`fork`,以及 `worker_threads`(例如 curl-pipe-sh) | | `process.native` | `process.dlopen` — 加载脱离 JS sandbox 的原生 addon (`.node`) | | `code.eval` | `vm.runInThisContext`/`Script`/`compileFunction` — 执行分阶段投放的 payload | | `env.read` | 依赖项读取 `NPM_TOKEN`、`AWS_SECRET_ACCESS_KEY` 等 | | `os.info` | `os.userInfo`/`networkInterfaces`/`hostname` 主机信息探查 | 每一个事件都会**归属到触发它的具体包**,让你确切知道是谁在搞鬼。 ## 策略 仅允许包合法需要的行为。dephawk 会在工作目录中寻找 `dephawk.config.js`(或通过 `--config ` 指定): ``` // dephawk.config.js export default { mode: 'observe', // or 'enforce' // applied to any package not listed below default: { net: { connect: [] }, spawn: false, env: false }, packages: { 'image-optimizer': { spawn: true }, // it genuinely shells out '@sentry/node': { net: { connect: ['*.sentry.io'] }, env: ['SENTRY_DSN'] }, bcrypt: { native: true }, // legitimately loads a native addon }, }; ``` - `net.connect` — 主机的允许列表。`*.sentry.io` 可匹配主域名及任何子域名;精确的主机名仅匹配自身。同样的列表也控制 DNS 解析(`net.resolve`):允许连接的主机,也允许解析。 - `spawn` — 设为 `true` 以允许子进程 **及** worker threads。 - `native` — 设为 `true` 以允许加载原生 addon(通过 `process.dlopen` 加载 `.node`)。默认关闭;针对 `bcrypt`、`sharp` 等包需开启此选项。 - `eval` — 设为 `true` 以允许通过 `vm` 模块执行动态代码。默认关闭——大多数依赖项永远不需要它。 - `env` — 设为 `true`(允许读取任何敏感信息)、`false`(禁止读取敏感信息),或设置为允许的变量名数组。非敏感变量(如 `NODE_ENV`)始终允许读取。 - `fs` — `{ read: [...], write: [...] }` 用于设置敏感路径的前缀匹配。 你自己的应用代码永远不会被标记——dephawk 监控的是依赖项,而不是你。 ## 工作原理(及其局限性) 在启动时(`--import dephawk/register`),dephawk 会对敏感的 Node 内置模块进行 monkey-patch —— 包括 `fs`、`http`/`https`/`fetch`、原始 `net`/`tls`/`dgram` socket、`dns`、`child_process`、`worker_threads`、`process.dlopen`、`vm`、`os` 以及 `process.env`。每一次被 patch 的调用都会捕获调用栈,追溯并找到第一个 `node_modules/` 帧,根据你的策略进行检查,并记录该事件。退出时,它会打印摘要并生成 HTML 报告。 **这是一个坦诚的威胁模型。** dephawk 是一个高信号的_绊线和策略层_,而不是坚不可摧的 sandbox: - 归属机制使用了调用栈,而意志坚定的攻击者可以掩盖其痕迹(例如重写 `Error.stack`、延迟执行、运行原生代码)。 - 原生 addon 运行在 JS sandbox 之外:dephawk 会标记 `.node` 的_加载_行为(`process.native`),但 addon 之后执行的操作是不可见的。 - `eval()` 和 `new Function()` 属于语言原语,无法被 patch;而 `vm` 模块——作为分阶段投放代码的专用路径——已在监控范围内。 - HTTP 在内部会进行解析和连接,因此一次请求可能同时触发 `net.resolve` 和 `net.connect`;在报告中会合并相同的记录行。 - 在启动前捕获的具名导入(如 `import { readFileSync } from 'fs'`)可能会绕过 patch;而通过命名空间或 `require` 方式的访问已在监控范围内。 - `process.env` 的拦截已尽力而为;部分原生读取操作仍可能漏网。 为了实现更严格的安全边界,你需要将其与操作系统级别的隔离机制(如 containers、`node --permission`、seccomp)结合使用。dephawk 的职责是让_常见的_攻击变得显眼且易于捕获。这足以阻止大多数现实世界中的安全事件。完整分析请参阅 [`docs/adr/0002`](docs/adr/0002-attribution-strategy.md)。 ## 编程 API ``` import { buildMonitor, resolveEnvPolicy } from 'dephawk'; const monitor = buildMonitor({ policy: resolveEnvPolicy(process.env) }); monitor.start(); // … run code … monitor.stop(); await monitor.report(); ``` 每个协同组件(拦截器、报告生成器、归属分析器、时钟、数据接收器)都可以被重写——你可以自由组合。 ## 运行时支持 在 Node 20 和 22 上构建并测试。Bun/Deno 提供了大部分相同的内置模块;当缺少某个内置模块时,dephawk 会优雅降级,但不保证在这些环境下提供完整覆盖。 ## 路线图 - [x] 可分享的 HTML 报告文件 (`.dephawk/report.html`) - [x] 异步配置加载 + 主机/路径 glob 匹配 - [x] `fs.write` 覆盖范围,以及 `os.userInfo`/`networkInterfaces` 拦截 - [x] DNS (`net.resolve`)、原始 socket/TLS/UDP、原生 addon (`process.native`)、`vm` 代码执行 (`code.eval`) 及 `worker_threads` 拦截 - [ ] `--record`/`--replay` 依赖行为,以便在 CI 中进行差异对比 - [ ] 基线模式:快照正常行为,仅在出现_新_能力时发出警报 - [ ] `postinstall` 脚本防护(在你的代码运行前捕获攻击) ## 贡献 欢迎提交 PR——特别是新的拦截器和用于测试套件的真实攻击样本。请参阅 [`CONTRIBUTING.md`](./CONTRIBUTING.md)。 ## 许可证 MIT
标签:GNU通用公共许可证, IP 地址批量处理, MITM代理, Node.js, npm, StruQ, 数据可视化, 暗色界面, 自动化攻击, 行为监控