Node.js 20.18.2(Iron LTS)安全版本深度解析:CVE 修复清单、下载校验与发布机制
【免费下载链接】nodejs.orgThe Node.js® Website项目地址: https://gitcode.com/GitHub_Trending/no/nodejs.org
本篇基于 nodejs.org 官方仓库中的 v20.18.2 发布公告,完整还原该安全版本修复的 4 个 CVE 漏洞(含 1 个 High 级别)、4 个修复提交、全平台发行文件与 PGP 校验和,并结合仓库内的发布自动化脚本(scripts/release-post)、版本状态生成器(next-data/generators/releaseData.mjs)与漏洞数据生成器(next-data/generators/vulnerabilities.mjs)源码,解释这类安全发布公告从"上游 changelog"到"官网博客页"的完整链路。读完本文,你将能快速评估 20.18.2 对自身部署的影响、按规范下载并校验二进制,并理解该版本在 Node.js 20 LTS 生命周期中的位置。
一、版本概况:一次针对 LTS 主线的纯安全发布
发布公告的元数据明确标注了本次版本的基本属性:
| 属性 | 值 |
|---|---|
| 发布日期 | 2025-01-21 |
| 版本号 | Node.js 20.18.2 |
| 发布线 | 'Iron' (LTS) |
| 发布类型 | 安全发布(security release) |
| 公告作者 | Rafael Gonzaga (@RafaelGSS) |
| 仓库位置 | apps/site/pages/en/blog/release/v20.18.2.md |
公告第一行明确写着 "This is a security release."(这是一个安全发布)。这意味着本次版本不引入任何新特性,而是针对已披露的安全漏洞做最小化修复,将修复代码回移植(backport)到仍然处于维护中的 LTS 主线。
在仓库的版本状态逻辑中,"LTS" 是一个有明确判定规则的动态状态。查看 next-data/generators/releaseData.mjs 中的getNodeReleaseStatus:
const getNodeReleaseStatus = (latest, eol) => { const now = new Date(); if (eol && now >= new Date(eol)) { return 'EOL'; } if (latest.lts.isLts) { return 'LTS'; } return 'Current'; };从源码结构看,一个主版本的状态按以下优先级判定:若已过 EOL 截止日期则为EOL;否则若最新版本被标记为 LTS(latest.lts.isLts为真)则为LTS;其余为Current。Node.js 20 系列在 20.18.x 时期正处于Active LTS / Maintenance LTS阶段,因此安全修复会被持续回移植到该主线,这也是本次 20.18.2 能以 "Iron (LTS)" 名义发布的原因。仓库中对应的 releaseData.test.mjs 通过模拟时间与 nodevu 数据,分别验证了EOL、LTS、Current三种状态的判定分支,可作为理解该逻辑的测试佐证。
二、安全公告详解:四个 CVE 的成因与影响
本次发布共修复 4 个安全问题,其中 3 个来自 Node.js 核心,1 个来自依赖组件 undici:
| CVE | 组件 | 严重级别 | 一句话描述 |
|---|---|---|---|
| CVE-2025-23083 | 权限模型 / worker | High | 启用权限模型(permission model)时,内部 Worker(InternalWorker)使用未按预期抛错 |
| CVE-2025-23085 | HTTP2 / src | Medium | 连接提前关闭与ERR_PROTO场景下的 HTTP2 内存泄漏 |
| CVE-2025-23084 | path(Windows) | Medium | Windows 平台上normalize()存在路径遍历(path traversal)问题 |
| CVE-2025-22150 | undicifetch() | Medium | 依赖更新:fetch()中使用了随机性不足的值(Insufficiently Random Values) |
2.1 CVE-2025-23083:权限模型下 InternalWorker 的越权风险(High)
这是本次发布唯一的高危漏洞。Node.js 从 v20 起引入了实验性的权限模型(permission model,通过--permission系列命令行标志启用),用于限制文件系统、子进程与 worker 等敏感能力。修复提交389f239a28触及src,loader,permission三个模块,行为是:当权限模型启用时,对 InternalWorker 的使用直接抛错(throw on InternalWorker use)。
从修复范围可以推断,此前权限模型对内部 worker 的管控存在缺口——内部 worker 的创建绕过了权限校验,可能被利用来突破权限模型设置的边界。因此修复策略不是"放开白名单",而是"启用权限模型时直接拒绝"这种更保守的处理。该提交对应私有安全仓库 PR(nodejs-private/node-private#652),属于典型的"先披露后公开"流程。
2.2 CVE-2025-23084:Windows 平台normalize()路径遍历(Medium)
修复提交42d5821873针对path模块,问题限定在Windows 平台的path.normalize()。路径遍历(path traversal)意味着攻击者可以通过构造特殊路径(如包含..、盘符分隔符、反斜杠变体等)让normalize()产生预期之外的规范化结果,进而可能逃逸出目录边界,配合文件读写 API 构成越权访问。
该修复来自私有安全仓库 PR nodejs-private/node-private#555,作者 Tobias Nießen。中危定级说明触发该问题通常还需要其他前置条件(例如将用户输入直接传入文件操作),但任何在 Windows 上对用户输入路径调用normalize()再拼接做文件访问的应用,都建议尽快升级验证。
2.3 CVE-2025-23085:HTTP2 内存泄漏(Medium)
修复提交8187a4b9bb位于src(C++ 核心层),由本次发布负责人 RafaelGSS 直接提交。问题场景是 HTTP/2 连接在**提前关闭(premature close)**以及出现ERR_PROTO错误时存在内存泄漏(mem leak)。
HTTP/2 多路复用的连接生命周期管理本就复杂,流(stream)与连接被异常中断时,若内部缓冲区或对象引用未被及时释放,长时间运行的 Node.js 服务会逐步累积内存。虽然该问题定级为中危,但对于长期驻留的 HTTP/2 服务端进程,内存泄漏的累积效应不容忽视,建议生产环境及时跟进。
2.4 CVE-2025-22150:undicifetch()随机值不足(Medium)
此项不是核心代码修复,而是依赖更新:将 undici 升级到v6.21.1(提交df8b9f2c3e,作者 Matteo Collina)。undici 是 Node.js 内置的 HTTP 客户端实现,fetch()即由它提供。该 CVE 描述为 "Use of Insufficiently Random Values in undici fetch()",即fetch()在某些内部操作中使用了可预测/随机性不足的值,可能被攻击者猜测利用。升级依赖是唯一修复手段,因此公告将其单列为 "Dependency update" 小节。
提示:由于
fetch()是全局 API,即使你的应用不直接 import undici,只要使用了全局fetch、Headers、Request、Response等,就同样受到影响。
三、提交清单与修复落点
公告的 Commits 小节完整列出了本次发布合并的 4 个提交:
| 提交哈希 | 涉及模块 | 关联 CVE / 说明 | 作者 |
|---|---|---|---|
df8b9f2c3e | deps | CVE-2025-22150,undici 升级至 v6.21.1 | Matteo Collina |
42d5821873 | path | CVE-2025-23084,Windowsnormalize()路径遍历 | Tobias Nießen |
8187a4b9bb | src | HTTP2 提前关闭与ERR_PROTO内存泄漏 | RafaelGSS |
389f239a28 | src, loader, permission | CVE-2025-23083,权限模型下 InternalWorker 抛错 | RafaelGSS |
其中三个安全修复经由nodejs-private/node-private私有安全仓库协作完成(PR #663、#555、#652),这是 Node.js 项目遵循的"负责任披露(responsible disclosure)"流程:漏洞细节先由安全团队与受信任维护者确认并准备修复,随安全版本发布后再向公众披露。8187a4b9bb未标注 CVE,属于伴随该次安全发布的常规修复。
对照 Node.js 20 系列的发布节奏,上一版 20.18.1(v20.18.1.md,2024-11-20)是常规维护版本,而 20.18.2 是紧接其后的安全修复版本,两者间隔约两个月,符合"安全公告按需发布"的惯例。
四、发行文件与下载指引
公告末尾给出了完整的发行文件清单。所有文件均位于官方发行目录(nodejs.org/dist/v20.18.2/),按平台与格式划分:
Windows 32-bit Installer : node-v20.18.2-x86.msi Windows 64-bit Installer : node-v20.18.2-x64.msi Windows ARM 64-bit Installer: node-v20.18.2-arm64.msi Windows 32-bit Binary : win-x86/node.exe Windows 64-bit Binary : win-x64/node.exe Windows ARM 64-bit Binary : win-arm64/node.exe macOS 64-bit Installer : node-v20.18.2.pkg macOS Apple Silicon Binary : node-v20.18.2-darwin-arm64.tar.gz macOS Intel 64-bit Binary : node-v20.18.2-darwin-x64.tar.gz Linux 64-bit Binary : node-v20.18.2-linux-x64.tar.xz Linux PPC LE 64-bit Binary : node-v20.18.2-linux-ppc64le.tar.xz Linux s390x 64-bit Binary : node-v20.18.2-linux-s390x.tar.xz AIX 64-bit Binary : node-v20.18.2-aix-ppc64.tar.gz ARMv7 32-bit Binary : node-v20.18.2-linux-armv7l.tar.xz ARMv8 64-bit Binary : node-v20.18.2-linux-arm64.tar.xz Source Code : node-v20.18.2.tar.gz4.1 发行文件清单是如何生成的
这份清单并非人工维护,而是由仓库中的发布自动化脚本根据版本号动态推导。查看 apps/site/scripts/release-post/downloadsTable.mjs:
- 每种平台文件对应一条模板 URL(
templateUrl),其中的%version%占位符会被真实版本号替换; - 脚本依据 semver 范围决定哪些平台文件出现在清单中:
if (semVer.satisfies(version, '< 16.0.0')) { // 排除 macOS Apple Silicon } if (semVer.satisfies(version, '< 19.9.0')) { // 排除 Windows ARM 64-bit Installer / Binary } if (semVer.satisfies(version, '>= 23.0.0')) { // 排除 Windows 32-bit Installer / Binary } if (semVer.satisfies(version, '>= 24.0.0')) { // 排除 ARMv7 32-bit Binary }对照 v20.18.2(20.18.2 >= 19.9.0且< 23.0.0),因此清单同时包含 Windows ARM 64 位与 32 位安装包,但尚未触发 32 位/ARMv7 的移除规则——这解释了为什么公告中 15 类平台文件齐全。该脚本也是官网 DownloadsTable 与下载按钮(DownloadButton)背后数据链路的源头。
4.2 各平台选择建议
- Windows 用户:优先选择
.msi安装包(x86/x64/arm64 按系统位数),或便携场景使用win-x64/node.exe免安装二进制; - macOS 用户:Apple Silicon 选择
darwin-arm64,Intel 选择darwin-x64,也可使用通用.pkg安装器; - Linux 用户:绝大多数服务器选择
linux-x64.tar.xz;ARM 服务器选择linux-arm64;PPC64LE、s390x 等企业级架构有对应专属包; - 源码构建:下载
node-v20.18.2.tar.gz自行编译。
五、SHASUMS 与 PGP 完整性校验
发布公告中最重要的安全实践部分是SHASUMS:一个经 PGP 签名的 SHA-256 校验和清单。以下为公告中的完整内容:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 efcddeb91b189b02706d1a75a67b4a111253ec8f64cc30cc3dc4649744abd52b node-v20.18.2-aix-ppc64.tar.gz 40c5a72564b8667342bec84aab50d2af1503af2b274f1a7a09d2d929461988b6 node-v20.18.2-arm64.msi fa76d5b5340f14070ebaa88ef8faa28c1e9271502725e830cb52f0cf5b6493de node-v20.18.2-darwin-arm64.tar.gz 32dc17147054df9cdf96d03103f4661b4cb0bb9b4ca4b70e34fe632f1bab189c node-v20.18.2-darwin-arm64.tar.xz 00a16bb0a82a2ad5d00d66b466ae1afa678482283747c27e9bce96668f334744 node-v20.18.2-darwin-x64.tar.gz 184c9b8e246a3fd139caf2456510dc99ec548ad2e5203fbc5fc56ba48104e8eb node-v20.18.2-darwin-x64.tar.xz d74c718976adc308991fb8784f0b3f82845436bf8f04d2c982ab5cab5115289f node-v20.18.2-headers.tar.gz 05819d72dcc0aa788baab1066e18ede5f1ab6730a1925cd6b15c131b55fd4272 node-v20.18.2-headers.tar.xz 319789e8a055ff80793a05e633c8c5c9226050144a09da3747225b4ec56a2a99 node-v20.18.2-linux-arm64.tar.gz 5c1437aa16e7e6a2e0687a42c4d3f0a8f8a2039cda8880cb3be8cd983aeefb44 node-v20.18.2-linux-arm64.tar.xz 65397a4a63960bda94718099698d2961623e9ef400f60f4c3a71add2268bccfb node-v20.18.2-linux-armv7l.tar.gz 63d4df56fb2e34a5077345f78941094204d2223ce03b8ebc9c1500e6e2aae68d node-v20.18.2-linux-armv7l.tar.xz 9b2f0fd3b02d8b59bde3e2a251e4df501e755c99cfc4886b0bdf85fa4d0bc538 node-v20.18.2-linux-ppc64le.tar.gz 828a2635261ca225cd4a8a4b1a914003cdc7b30656c2e9092ac7aab02ac361db node-v20.18.2-linux-ppc64le.tar.xz 7e52e03823feaa2483a7cbcf85767790776f87a2c7112d87600c3d9d3b1ae6e9 node-v20.18.2-linux-s390x.tar.gz bcf3680e111f1d24e403db3d5600315266ae1f8d9d1f69f39c61dbf8d8c9036e node-v20.18.2-linux-s390x.tar.xz eb5b031bdd728871c3b9a82655dbfa533bc262c0b6da1d09a86842430cef07d4 node-v20.18.2-linux-x64.tar.gz 4e50f727ae09bdafecf2322c72faf7cd82bf3b8851a16b8bb63974e0d8d6eceb node-v20.18.2-linux-x64.tar.xz 87d10db681bca2a39fcadcc908d5e5b2c7effa16370c4ca555373b85e25275b1 node-v20.18.2.pkg cf3ef49fafbfee3cdcd936a0d6031341b73bfa6b26a484ea0a4936c26d24b829 node-v20.18.2.tar.gz 69bf81b70f3a95ae0763459f02860c282d7e3a47567c8afaf126cc778176a882 node-v20.18.2.tar.xz d28d21e000ebed8b6131201b727d1998d4dbc4dbdb6e5ad07679552e4c75fa4d node-v20.18.2-win-arm64.7z b89d196a2d9dc3dac87c268aac9a983fa2fd1881c14884bc848312783ccf7d2f node-v20.18.2-win-arm64.zip 06e72c0f78cc1bf1819eb0a0a37001d2917f19ad46a149c2f923c901f599ba52 node-v20.18.2-win-x64.7z ed790b94570518a7dce67b62485e16bc4bffecee4ec3b6df35ed220ae91117a5 node-v20.18.2-win-x64.zip fa561ebff3f52667228f9fcd9e67ce22a86e5c28c8e3782e01a95c90b6ed114d node-v20.18.2-win-x86.7z 25f00a77843accc098561a35ce3ed923357f0127b8e5db594cb62188e3290b88 node-v20.18.2-win-x86.zip f3ad2d799e1645281d22d71b447f3899e569da87fea78bef9571b0c2b53288d6 node-v20.18.2-x64.msi 783c4041ceb69226184a1b26177b5d9dc85e502d0f124c64d2b2c6f8ab12e5d5 node-v20.18.2-x86.msi 83e7ad1b8c4d4d9c5e06849c3e8f3a5948a5eb6aa34c5bd973ba700e0386f42c win-arm64/node.exe 58795bcd44e8023ff443dedabf7f9af928732a51befc5324082aafe56e0f5eb0 win-arm64/node.lib 83fdda5fb5869c18f5d5d3dc4d0479f6bdad16f0888c95b8008f03654593afdd win-arm64/node_pdb.7z 4049c1e7c2fc82c4d43c9d8567e7d20f20c0d360c281fcb924ce9cd4b9ce8dc3 win-arm64/node_pdb.zip 8487a277e92282904dfe0f860dbd5d229543e97a858a223fbe9c9b8670bbe170 win-x64/node.exe 5a16801c62c34c8056744ac339950c970b2b76f39b2d02afef4112ff51b74f1a win-x64/node.lib 6ff19d51a762405717f7dff33811ba6371334de95946efbccf6f8dd786ec93e8 win-x64/node_pdb.7z 07ef9641b5a339de2f43f698dc3b1aeb321e851645b199cbeb0f378674263bf1 win-x64/node_pdb.zip ab4b6beaaa170cfed83a2c9c71d8d5032ac514a5ebd7a5aa0553731267964f5e win-x86/node.exe fcc6ab34ebd4ad3a44de12376c3822c2ebc41febaa1ed4c4221ddc239f79f61c win-x86/node.lib ab74677f28b517eee9f745930541d02a870ae2d3f29a5ac91fe630813a1cd987 win-x86/node_pdb.7z 6080ab7b513194510c8938c276b7fd4379eb0ed69cfa09dbb21da8a4eeddd75f win-x86/node_pdb.zip -----BEGIN PGP SIGNATURE----- iQGzBAEBCAAdFiEEiQwI24V5Fi/uDfnbi+q0389VXvQFAmeP0VcACgkQi+q0389V XvSVVAv9Gqyi4i2K2vHIKo7Pe/ZQB4BLg5nmzDtd6SNqtcSgTM+oR3u1vOeFdeTL tXpIFaqUh0uYTYBpE4aJWajwXPnKWYu+uJO8Z1PtfUitM9PiZT5w2Ko69QPxIt7K 4BmRxFhCVAH87R2SKiXWWzhDBQDQKboQFBtVG4G16HfOXp9leKSxUTKQ8B0fU+4L qbiCk9EvaBAmEJdrzT8Od/GjMdcBFXzllNRlROVu5hhAv6+HHlMuxR3RgaN5wml+ zFFQeQk+lY1YZeA0DpslwB5raCrsLehkEywlXsJHF3wmRKOhsrFaQlTDLtzZuyoN BY6LQqkmY5hJGiCOeiXSCNHAXUpqmOLvUJQgXSW0jaEh41o66yXk7MGthUegYo5o AekiwYEZE50K4QLE9xdIFjQ5GeSp0iK81wxGgPLjVS0DBe0sw+sDWMep+yisHmhP Ttf0cY501JvjbdaBB40ug5LFpABuKQJgzmbTmrU8Edf+apbJa35OZRt2bNg7xoYs SzUkh4yR =eALp -----END PGP SIGNATURE-----5.1 为什么要做 PGP 签名
SHA-256 校验和本身只能保证文件在下载传输过程中未被篡改,但无法防止"攻击者同时替换文件与校验和"的中间人攻击。PGP 签名的作用在于:只要验证者信任 Node.js 发布密钥(public release keys),就能确认这份校验和清单确实由 Node.js 官方发布团队签发,从而间接保证二进制文件的真实性与完整性。
5.2 建议的验证流程
在 Linux/macOS 终端中,可参照以下步骤完成标准的三段式校验:
- 导入 Node.js 官方发布密钥(信任链);
- 使用 GPG 验证
SHASUMS256.txt.asc的签名,确认Good signature; - 用
sha256sum -c比对下载文件与校验和是否一致:
# 1) 校验 PGP 签名(需已导入官方发布密钥) gpg --verify SHASUMS256.txt.asc SHASUMS256.txt # 2) 校验下载文件的 SHA-256 是否匹配 sha256sum -c SHASUMS256.txt --ignore-missingWindows 用户可在 PowerShell 中使用Get-FileHash计算 SHA-256,并与公告中的哈希值逐字比对。在生产环境、CI/CD 流水线或任何自动化分发场景中,请务必执行上述校验后再安装或打包镜像。
六、发布公告是如何生成的:仓库内的自动化管线
v20.18.2.md这类发布公告在 nodejs.org 仓库中并非手写,而是由 apps/site/scripts/release-post/index.mjs 自动化生成的。理解这条管线有助于读者判断公告内容的可靠性,也方便后续自己核对任何版本:
- 获取 changelog:从上游
CHANGELOG_V20.md中按<a id="20.18.2"></a>锚点截取对应发布段落(fetchChangelog,使用正则rxSection匹配); - 提取作者:从发布段落的头部(如
## 2025-01-21, Version 20.18.2 'Iron' (LTS), @RafaelGSS)用rxReleaseAuthor正则解析出@RafaelGSS,再调用 GitHub API 拿到展示名; - 提取版本策略:用
rxPolicy正则从 changelog 标题中解析出LTS/Current/Stable等策略标签; - 拉取 SHASUMS:从官方发行目录获取
SHASUMS256.txt.asc(fetchShasums,失败时以[INSERT SHASUMS HERE]占位); - 探测下载文件:基于 downloadsTable.mjs 生成平台文件清单,并对每个 URL 发 HEAD 请求探测可用性,不可用的标记为
*Coming soon*; - 渲染与落盘:将以上数据填充进 template.hbs(Handlebars 模板),经 Prettier 格式化后写入
pages/en/blog/release/v${version}.md。
模板文件template.hbs的结构与最终公告一一对应:
--- date: '{{date}}' category: release title: Node.js {{version}} ({{versionPolicy}}) layout: blog-post author: {{author}} --- {{changelog}} {{#files}} {{.}} \ {{/files}} Other release files: https://nodejs.org/dist/v{{version}}/ \ Documentation: https://nodejs.org/docs/v{{version}}/api/ ### SHASUMS{{shasums}}
这也解释了公告的固定三段式结构:Notable Changes(changelog 精华)→ 下载文件清单 → SHASUMS。公告正文中的 CVE 描述、提交列表均直接继承自上游 changelog,保证了发布信息与代码仓库的一致性;下载清单与校验和则由脚本在发布时实时抓取,避免了人工抄录导致的错漏。
七、漏洞数据如何呈现在官网上
安全发布公告之外,nodejs.org 官网还通过 next-data/generators/vulnerabilities.mjs 将历史漏洞按主版本聚合,供各版本的下载页与 EOL 相关组件 展示。该生成器从 Node.js Security Working Group 的漏洞数据源抓取 JSON,再用正则解析vulnerable字段中的版本表达式:
const RANGE_REGEX = /([<>]=?)\s*(\d+)(?:\.(\d+))?/; const V0_REGEX = /^0\.\d+(\.x)?$/; const VER_REGEX = /^\d+\.x$/;12.x这类简单主版本模式 → 归入主版本 12;0.10.x这类旧格式 → 归入主版本 0;>=6.0.0 <6.2.0、< 5、<= 10等范围表达式 → 按操作符推断受影响的主版本集合(例如<表示低于该主版本的所有版本)。
对应的单元测试 vulnerabilities.test.mjs 覆盖了空数据、非法值忽略、单版本、多版本、>=/</<=范围等场景。这意味着:当你在官网某个版本页面看到 "Vulnerabilities" 列表时,其数据正是由这套解析逻辑按你所在的 Node.js 主版本聚合而来的——例如本次发布的 CVE-2025-23083 等条目,会在 Node.js 20 主版本的漏洞清单中直接可见。这与发布公告正文形成互补:公告给出"某版本修复了哪些 CVE",官网页面则回答"当前主版本受哪些 CVE 影响"。
八、升级建议与操作指引
综合以上分析,针对 v20.18.2 给出如下落地建议:
- 确认当前版本:在部署环境执行
node -v,若版本低于20.18.2且运行在 20 系列(或使用了全局fetch的任意 Node.js 版本),建议尽快升级; - 重点关注高危项:若你的服务启用了
--permission权限模型,请优先验证 CVE-2025-23083 的修复行为(权限模型下 InternalWorker 调用将抛错),并回归相关 worker 场景; - Windows 用户:CVE-2025-23084 与
path.normalize()相关,涉及用户输入路径的文件处理逻辑需回归测试; - HTTP/2 长驻服务:关注 CVE-2025-23085 修复后的内存表现,升级后可对比 RSS 增长曲线;
- 严格校验产物:按上文 5.2 节的流程验证 PGP 签名与 SHA-256,再接入生产;
- 善用官网数据:可在官网对应主版本的漏洞列表页核对所有已知 CVE 的状态,其数据生成逻辑见 vulnerabilities.mjs。
延伸阅读(仓库内)
- 发布公告原始文件:apps/site/pages/en/blog/release/v20.18.2.md
- 相邻版本对比:apps/site/pages/en/blog/release/v20.18.1.md
- 发布公告自动化脚本:apps/site/scripts/release-post/index.mjs、模板、下载表生成
- 版本状态(LTS/Current/EOL)判定:apps/site/next-data/generators/releaseData.mjs 及其测试
- 漏洞数据聚合逻辑:apps/site/next-data/generators/vulnerabilities.mjs 及其测试
- 下载按钮与下载表组件:DownloadButton、DownloadsTable
【免费下载链接】nodejs.orgThe Node.js® Website项目地址: https://gitcode.com/GitHub_Trending/no/nodejs.org
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考