跳到正文
runtly

macOS · Node、Bun、Deno、pnpm、yarn

你的哪些项目跑在已停止维护的运行时上?

任何版本管理器都能告诉你当前用的是哪个版本。runtly 还会告诉你:哪些版本已收不到安全补丁,哪些项目跑在上面,以及其中哪些还有人在做。

下载 macOS 版 — 免费Universal · Apple Silicon 与 Intel · macOS 10.15+

或者只要命令行

$curl -fsSL https://runtly.flatium.com/download | sh
rt audit
$ rt auditruntly audit7 projects, 1 runtime versions examined · data fetched 3 minutes agoactive project, unsupported runtime  node 18.20.4    EOL 502d ago medium      medium CVE-2025-23085 GOAWAY HTTP/2 frames cause memory leak outside heap      https://nodejs.org/en/blog/vulnerability/january-2025-security-releases/      /Users/you/code/billing-worker      /Users/you/code/checkout-api      /Users/you/code/docs-site      and 4 more      4 of 7 committed to in the last 90 days, 4 inherit the global defaultrt install node@18.20.6rt use node@18.20.6  (4 project(s) inherit the default and are fixed by this alone)runtly audit examines the runtime, not your dependency tree. It does not replace `npm audit`.

01问题

版本管理器知道号码,不知道风险。

nvm use 和它的同类只回答一个问题:此刻哪个版本是激活的。这个问题问出口的瞬间就已经有了答案,而它对这个版本是否还在收补丁只字不提。

于是答案通常从外面来:一份合规问卷、一次客户方的安全审查、一张问你生产环境跑着哪些 Node 版本的供应商表格。到那时,清单只能靠手工拼出来——逐个打开仓库,逐个读 .nvmrc,逐个拿版本去对支持周期表。

runtly 一直留着那份清单。它知道装了哪些版本、哪些项目会解析到它们、每个项目最后一次提交是什么时候,以及已公开的安全公告对每个版本说了什么。

02审计

审计

rt audit 会检查它扫描过的每个项目,报告它们背后的运行时版本。

结果按该先看哪个排序

这些就是工具实际打印的标签,顺序也和它打印的一致。

  1. 01

    active project, known vulnerability

    最近 90 天内有提交的项目,跑在一个已有公开安全公告的版本上。

  2. 02

    active project, unsupported runtime

    仍在开发的项目,跑在一个不再收安全补丁的版本上。

  3. 03

    critical vulnerability

    机器上任何位置出现的 critical 级安全公告,无论项目是否活跃。

  4. 04

    losing security support soon

    即将结束支持的版本——趁还有时间规划迁移。

  5. 05

    dormant project on an old runtime

    90 天以上没动过。仍会报告,但默认折叠:这不是你今天下午该修的东西。

能清掉全部安全公告的最小升级

给出的建议是一个具体版本,不是一个大版本号。对于还挂着 2025 年 1 月公告的 Node 18.20.4,那就是 18.20.6,而不是"升到 22"。被客户合同锁在 Node 18 上的人做不了后者,但今天下午就能做前者。

如果项目并未固定版本、而是继承了全局默认值,runtly 会说明这一点,并附上一条能一次修好全部的命令。

它以非零码退出,所以它属于 CI

当结果达到阈值时,rt audit --fail-on=critical 会返回失败的退出码。--fail-on 还接受 highmediumloweolnever--json 会输出完整报告,供任何想读它的东西使用。

$ rt audit --fail-on=eol$ echo $?1

能离线跑,也不隐瞒这件事

安全公告数据会缓存 24 小时,所以在飞机上也能做审计。每份报告都会在第二行写明它的数据有多旧——data fetched 3 minutes ago,或者 9 hours ago

数据从哪里来

endoflife.date
支持周期与生命周期终止日历。
Node.js Security WG
Node.js Security Working Group 的漏洞数据库。
OSV.dev
开源漏洞数据库。

03解析

解析

runtly 从当前工作目录逐级向上查找,采用找到的第一个答案。规则是近者胜:近处一个低优先级的文件会压过远处一个高优先级的文件,所以工作区成员会覆盖 monorepo 根目录,而不是反过来。

同一目录内的优先级,从高到低
1.runtlyrcruntly 自己的文件,由 rt pin 写入。
2.nvmrc原样读取,现有仓库不需要任何改动。
3.node-version / .bun-version单一运行时的惯例写法。
4.tool-versionsasdf 和 mise 的项目。
5package.json → packageManagerCorepack 的字段,用于 pnpm 和 yarn。
6package.json → engines范围会对照已安装的版本解析,匹配到的最高版本胜出。

满足不了的约束是错误,绝不是回退

如果项目要求一个没装的版本,runtly 会停下来并说明。它不会默默去跑 PATH 上碰巧存在的那个。正是这种无声的替换,一周后会变成"本地能过,CI 挂了"。

$ node --versionerror: this directory requires node `20.99.0`, and no installed version satisfies it.  Declared in: /Users/you/code/bad/.nvmrc (.nvmrc)  Install one: rt install node@20.99.0

rt current 会指出是哪个文件决定的

"我为什么在错的版本上",答案是一个路径,而工具会把这个路径打出来。

$ rt current/Users/you/code/mono/packages/web  runtime  version  source  node     18.20.4  /Users/you/code/mono/packages/web/.nvmrc (.nvmrc)

04速度

速度

shim 在每次调用 node 之前都会先跑一遍,所以它必须不花钱。用 hyperfine 测量,500 次运行。

每次调用 node 的增量
一个什么都不做、只调用 exec 的 Rust 二进制1.9 ms
runtly 的 shim,先解析再调用 exec1.9 ms

解析这部分是免费的。剩下的是 macOS 自己启动一个进程的开销,谁也去不掉。

扫描一台真实的机器不到一秒扫完 136 个项目

05应用

应用

CLI 和 GUI 共用同一个内核,所以两者对装了什么、什么有风险不会各说各话。菜单栏里的一项可以不开窗口就切换版本。

安全

安全

正在使用的每个版本、它的支持状态,以及它背后的项目。

运行时

运行时

Node、Bun、Deno、pnpm、yarn 已安装的版本,以及上游可用的版本。

项目

项目

每个扫描到的项目解析到什么,以及是哪个文件决定的。

06边界

它不做什么

把安全覆盖范围说大了,比什么都不说更糟,因为那会制造没有根据的放心。三条边界,直说。

  • 它审计的是运行时,不是你的依赖树

    runtly 报告的是你的项目跑在哪些 Node、Bun、Deno 版本上。它对 node_modules 里的包只字不提。它不能替代 npm audit,跑它也不等于跑了那个。

  • 对 Bun 和 Deno,"没有发现"意味着"没人公开这类数据"

    这两个项目都没有维护 Node 那样的公开安全公告数据库。runtly 会报告它们的生命周期状态,并主动打印这条警告,而不是让一份干净的报告去暗示它其实无从知晓的事。

  • 仅限 macOS

    Apple Silicon 与 Intel,macOS 10.15 及以上。没有 Windows 版,没有 Linux 版,也不作任何承诺。

07免费

免费,且闭源

一个免费的闭源开发者工具,会立刻引出一个问题。所以这里写清楚这个软件到底做了什么。

无账号、无注册、无许可证密钥
下载了就能用。没有什么要注册,也没有什么要激活。
无遥测,也没有任何形式的分析统计
这个应用从不上报关于你或你机器的任何信息。
shim 从不碰网络
每次调用 `node` 之前先跑的那部分,完全不发起任何网络请求。
下载的文件在解包前会先校验
每个运行时都会与发布方自己公布的 SHA256 比对。应用本身经过 Apple 签名与公证,并以通用二进制的形式发布。

它发起的全部网络请求

  • nodejs.org/distNode 发行版下载
  • api.github.comBun 与 Deno 的发布信息
  • GitHub release downloadsBun 与 Deno 的二进制文件
  • registry.npmjs.orgpnpm 与 yarn
  • endoflife.date支持周期日历
  • raw.githubusercontent.com/nodejs/security-wgNode.js 安全公告数据库
  • api.osv.dev开源漏洞数据

就是你自己动手也会去取的那些地方。除此之外,哪里都不去。

08安装

安装

三条路径,它们装到你机器上的东西并不相同。

下载应用

应用和命令行

拖进 Applications,打开它,按下 Set up now。应用会自己安装 shim 并配置好你的 shell——全程不需要终端。

下载 macOS 版Universal · Apple Silicon 与 Intel · macOS 10.15+

Homebrew

取决于你运行哪一行

应用和 CLI

$brew install --cask hieuhuynh93/tap/runtly-app

只要 CLI

$brew install hieuhuynh93/tap/runtly

Shell 安装脚本

只有命令行——给窗口毫无意义的服务器和 CI 用

CLI

$curl -fsSL https://runtly.flatium.com/download | sh

CLI 和应用

$curl -fsSL https://runtly.flatium.com/download | RUNTLY_WITH_APP=1 sh

它下载同样经过签名的二进制,在解包前与公布的 SHA256 比对,并替你跑一遍 runtly setup

它实际运行的脚本,想先读一遍的话: https://dl.runtly.flatium.com/install.sh

无论走哪条路径,最终状态都一样:~/.runtly/bin 在 PATH 上,rt doctor 报绿。