bodadotsh/npm-security-best-practices

GitHub: bodadotsh/npm-security-best-practices

Stars: 762 | Forks: 19

![npm 梗图](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/30fa432001105811.png) # NPM 安全最佳实践 hn discussion lessnews.dev - webdev newsfeed for busy developers ## 目录 - [遭受攻击了?](#got-compromised) - [立即采取的行动](#immediate-actions-to-take) - [面向开发者](#for-developers) - [0. 了解你的包](#0-know-thy-package) - [1. 锁定依赖版本](#1-pin-dependency-versions) - [2. 包含 lockfiles](#2-include-lockfiles) - [3. 禁用生命周期脚本](#3-disable-lifecycle-scripts) - [4. 安装前预防措施](#4-preinstall-preventions) - [5. 运行时保护](#5-runtime-protections) - [6. 减少外部依赖](#6-reduce-external-dependencies) - [7. 隔离开发环境](#7-isolated-development) - [面向维护者](#for-maintainers) - [8. 启用 2FA](#8-enable-2fa) - [9. 创建受限访问的 Tokens](#9-create-tokens-with-limited-access) - [10. 生成来源声明](#10-generate-provenance-statements) - [11. 审查已发布文件](#11-review-published-files) - [其他事项](#miscellaneous) - [12. NPM 组织](#12-npm-organization) - [13. 替代 Registry](#13-alternative-registry) - [14. 审计、监控和安全工具](#14-audit-monitor-and-security-tools) - [15. 支持 OSS](#15-support-oss) ## 遭受攻击了? ### 立即采取的行动 根据你的需求选择以下最佳实践,以加强你的系统防御下一次攻击的能力。 ## 面向开发者 ### 0. 了解你的包 ### 1. 锁定依赖版本 以下是如何在各种包管理器中锁定确切版本: ``` npm install --save-exact react pnpm add --save-exact react yarn add --save-exact react bun add --exact react deno add npm:react@19.1.1 ``` 我们也可以在配置文件(例如 [`.npmrc`](https://docs.npmjs.com/cli/v11/configuring-npm/npmrc))中更新此设置,使用 [`save-exact`](https://docs.npmjs.com/cli/v11/using-npm/config#save-exact) 或 [`save-prefix`](https://docs.npmjs.com/cli/v11/using-npm/config#save-prefix) 键值对: ``` npm config set save-exact=true pnpm config set save-exact true yarn config set defaultSemverRangePrefix "" ``` 对于 `bun`,配置文件是 `bunfig.toml`,相应的配置是: ``` [install] exact = true ``` #### 覆盖传递依赖 在 `package.json` 中,如果我们有以下 `overrides` 字段: ``` { "dependencies": { "library-a": "^3.0.0" }, "overrides": { "lodash": "4.17.21" } } ``` - 让我们假设 `⁠library-a` 的 `⁠package.json` 有一个依赖项 `"lodash": "^4.17.0"` - 如果没有 `⁠overrides` 部分,`⁠npm` 可能会安装 `⁠lodash@4.17.22`(或任何最新的 `⁠4.x.x` 版本)作为 `⁠library-a` 的传递依赖 - 但是,通过添加 `"overrides": { "lodash": "4.17.21" }`,我们告诉 `⁠npm`,无论 `⁠lodash` 出现在依赖树的哪个位置,都必须精确解析为版本 `⁠4.17.21` 对于 `pnpm`,我们也可以在 `pnpm-workspace.yaml` 文件中定义 `overrides` 字段: 对于 `yarn`,`resolutions` 字段在 `overrides` 字段之前引入,它也提供了类似的功能: ``` { "resolutions": { "lodash": "4.17.21" } } ``` ``` # yarn 也提供了一个 CLI 来设置 resolution:https://yarnpkg.com/cli/set/resolution yarn set resolution ``` 对于 `bun`,它支持 `overrides` 字段或 `resolutions` 字段: 对于 `deno` 和 `deno.json`,请参阅 : ``` { "links": [ "../path/to/local_npm_package" ] } ``` ### 2. 包含 Lockfiles ``` npm ci bun install --frozen-lockfile yarn install --frozen-lockfile pnpm install --frozen-lockfile deno install --frozen ``` 对于 `deno`,我们也可以在 `deno.json` 文件中设置以下内容: ``` { "lock": { "frozen": true } } ``` ### 3. 禁用生命周期脚本 ``` npm config set ignore-scripts true --global yarn config set enableScripts false ``` 对于 `bun`、`deno` 和 `pnpm`,它们默认是禁用的。 ### 4. 安装前预防措施 #### 安装前扫描器 ``` npm i -g sfw # 适用于 `npm`、`yarn`、`pnpm` sfw npm install # 示例:在 zsh 中将 `npm` 别名为 `sfw npm` # echo "alias npm='sfw npm'" >> ~/.zshrc ``` Aikido Safe Chain 封装了 npm cli、`npx`、`yarn`、`pnpm`、`pnpx`、`bun`、`bunx` 和 `pip`,以便在安装新包之前提供额外的检查 ``` npm install -g @aikidosec/safe-chain ``` ``` npq install express NPQ_PKG_MGR=pnpm npx npq install fastify ``` 使用 Bun,我们可以使用其 [安全扫描器 API](https://bun.com/docs/pm/security-scanner-api) ``` bun add -d @socketsecurity/bun-security-scanner ``` 从 Bun v1.3+ 开始,你可以[将 Socket 与 Bun 集成](https://socket.dev/blog/socket-integrates-with-bun-1-3-security-scanner-api) ``` # 在 bunfig.toml 中 [install.security] scanner = "@socketsecurity/bun-security-scanner" ``` #### 设置最小发布龄期 ``` npm install --before=2025-10-22 # 仅安装至少发布 1 天的 package npm install --before="$(date -v -1d)" # for Mac or BSD users npm install --before="$(date -d '1 days ago' +%Y-%m-%dT%H:%M:%S%z)" # for Linux users # 其他相关 flags:minimumReleaseAgeExclude pnpm config set minimumReleaseAge # 其他相关 flags:npmPreapprovedPackages yarn config set npmMinimalAgeGate ``` 对于 `npm`,有一项[提案](https://github.com/npm/cli/issues/8570)要添加 `minimumReleaseAge` 选项和 `minimumReleaseAgeExclude` 选项。 对于 `bun`,自 [`v1.3`](https://bun.com/docs/cli/install#minimum-release-age) 起支持 `minimumReleaseAge` 和 `minimumReleaseAgeExcludes` 选项。 ``` [install] minimumReleaseAge = 604800 # 7 days in seconds ``` 对于 `deno`,他们很快也会推出类似的功能: 提供类似功能的其他工具示例: - `npm-check-updates` () 有 `--cooldown/-c` 标志,例如:`npx npm-check-updates -i --format group -c 7` - Renovate CLI () 有一个 [`minimumReleaseAge`](https://docs.renovatebot.com/configuration-options/#minimumreleaseage) 配置选项。 - Step Security () 有一个 [NPM Package Cooldown Check](https://www.stepsecurity.io/blog/introducing-the-npm-package-cooldown-check) 功能。 ### 5. 运行时保护 大多数技术都集中在 _安装_ 和 _构建_ 阶段,我们可以在 JavaScript 应用程序的 _运行时_ 阶段添加额外的安全层。 #### 权限模型 阅读关于 Node.js 权限模型的信息: ``` # 默认授予完全访问权限 node index.js # 限制对所有可用权限的访问 node --permission index.js # 启用特定权限 node --permission --allow-fs-read=* --allow-fs-write=* index.js # 使用 `npx` 的权限模型 npx --node-options="--permission" ``` Deno 默认禁用权限。请参阅 ``` # 默认情况下限制访问 deno run script.ts # 启用特定权限 deno run --allow-read script.ts ``` 对于 Bun,权限模型目前在[这里](https://github.com/oven-sh/bun/discussions/725)和[这里](https://github.com/oven-sh/bun/issues/6617)进行讨论。 #### 强化 JavaScript 像 MetaMask 和 Moddable 这样的公司使用 来启用运行时保护,例如防止修改 JavaScript 的原始对象(Object、String、Number、Array 等),并限制对平台 API(window、document、XHR 等)的每个包访问。这些机制也被提议为 TC39 提案,如 ### 6. 减少外部依赖 在 `nodejs`、`bun`、`deno` 和 Web API 之间,开发者可以使用它们的许多现代功能,而不是依赖第三方库。原生模块可能无法提供相同级别的功能,但应尽可能考虑使用它们。以下是几个例子: | NPM 库 | 内置模块 | | -------------------------------- | ------------------------------------------------------------------- | | `axios`, `node-fetch`, `got` 等 | 原生 `fetch` API | | `jest`, `mocha`, `ava` 等 | `node:test`, `node:assert`, `bun test` 和 `deno test` | | `nodemon`, `chokidar` 等 | `node --watch`, `bun --watch` 和 `deno --watch` | | `dotenv`, `dotenv-expand` 等 | `node --env-file`, `bun --env-file` 和 `deno --env-file` | | `typescript`, `ts-node` 等 | `node --experimental-strip-types`[^10], `deno` 和 `bun` 原生支持 | | `esbuild`, `rollup` 等 | `bun build` 和 `deno bundle` | | `prettier`, `eslint` 等 | `deno lint` 和 `deno fmt` | 以下是一些你可能会觉得有用的资源: - - - - - - 可视化库依赖关系: - 在线分析依赖元数据:,或本地:`pnpm dlx node-modules-inspector` - Knip(移除未使用的依赖项): - 使用 [`npkill`](https://github.com/voidcosmos/npkill) 清除不需要的 `node_modules`:`cd ~ && npx npkill` ### 7. 隔离开发环境 在隔离环境中开发代码是防止供应链攻击的一种流行且有效的方法。一些知名的本地虚拟机 (VM) 解决方案包括:[VirtualBox](https://www.virtualbox.org/)、[VMware Fusion](https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion)、[Parallels Desktop](https://www.parallels.com/) 和 [OrbStack](https://orbstack.dev/)。 云沙盒也提供了更简单的设置路径,并且可以直接在浏览器中使用,流行的产品包括:[CodeSandbox](https://codesandbox.io)、[Ona (前身为 Gitpod)](https://ona.com/)、[GitHub Codespaces](https://github.com/features/codespaces) 等等。 基于容器的开发也越来越受欢迎,特别是随着专注于丰富容器中开发特定内容和设置的 [Development Containers](https://containers.dev/) 规范的推出。 如果你有任何好的技巧或反馈,[请在此处加入讨论](https://github.com/bodadotsh/npm-security-best-practices/issues/3)! ## 面向维护者 ### 8. 启用 2FA ``` # 确保 auth 和 writes 启用了 2FA(这是默认设置) npm profile enable-2fa auth-and-writes ``` | 自动化级别 | 包发布访问权限 | | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | | 手动 | 将每个包的访问权限设置为 `Require 2FA` 和 `Disable Tokens` | | 自动 | 将每个包的访问权限设置为 `Require two-factor authentication` 或 `Single factor automation tokens` 或 `Single factor granular access tokens` | ### 9. 创建受限访问的 Tokens 通过网站创建细粒度访问令牌: 或 `npm` cli: `npm login` cli 命令启用两小时的会话令牌,而不是长期有效的令牌。在这些会话期间,发布操作会强制执行 2FA,从而增加了一层额外的安全性。 以下是创建令牌时的一些最佳实践: - 描述性的令牌名称 - 将令牌限制为特定的包、范围和组织 - 设置令牌过期日期(例如,每年) - 根据 IP 地址范围(CIDR 表示法)限制令牌访问 - 在只读或读写访问之间进行选择 - 不要将同一个令牌用于多种目的 ### 10. 生成来源声明 要建立来源,请使用支持的 CI/CD 提供商(例如 GitHub Actions)并使用正确的标志进行发布: ``` npm publish --provenance ``` 要在不调用 `npm publish` 命令的情况下进行发布,我们可以执行以下操作之一: - 在 CI/CD 环境中将 `NPM_CONFIG_PROVENANCE` 设置为 `true` - 将 `provenance=true` 添加到 `.npmrc` 文件 - 将 `publishConfig` 块添加到 `package.json` ``` "publishConfig": { "provenance": true } ``` #### 可信发布 当使用 OpenID Connect (OIDC) 身份验证时,可以在 _不需要_ npm 令牌的情况下发布包,并获得 _自动_ 来源证明。这被称为 **可信发布**,请在此处阅读 GitHub 公告: 有关如何配置可信发布的说明,请参阅 。 相关工具: - (用于为 monorepo 包设置可信发布者的 CLI) - (用于在 npmjs.com 上填写可信发布者表单的用户脚本) ### 11. 审查已发布文件 `package.json` 中的 `files` 字段用于指定应包含在已发布包中的文件。某些文件总是包含在内,有关更多详细信息,请参阅: ``` { "name": "my-package", "version": "1.0.0", "main": "dist/index.js", "files": ["dist", "LICENSE", "README.md"] } ``` 运行 `npm pack --dry-run` `npm publish --dry-run` 来查看当我们运行 pack 或 publish 命令时会发生什么。 ``` > npm pack --dry-run npm notice Tarball Contents npm notice 1.1kB LICENSE npm notice 1.9kB README.md npm notice 108B index.js npm notice 700B package.json npm notice Tarball Details ``` 在 `deno.json` 中,使用 `publish.include` 和 `publish.exclude` 字段指定应包含或排除的文件: ``` { "publish": { "include": ["dist/", "README.md", "deno.json"], "exclude": ["**/*.test.*"] } } ``` ## 其他事项 ### 12. NPM 组织 在组织层面,最佳实践是: - 在组织级别启用 `Require 2FA` - 最小化 `npm` 组织成员的数量 - 如果同一组织中有多个包团队,请将所有包的 `developers` 团队权限设置为 `READ` - 创建单独的团队来管理每个包的权限 ### 13. 替代 Registry JSR 是一个现代的 JavaScript/TypeScript 包注册中心,与 npm 向后兼容。 ``` deno add jsr: pnpm add jsr: # pnpm 10.9+ yarn add jsr: # yarn 4.9+ # npm、bun 以及旧版本的 yarn 或 pnpm npx jsr add # replace npx with yarn dlx, pnpm dlx, or bunx ``` #### 私有 Registry 以下是一些你可能会觉得有用的私有注册中心: - GitHub Packages - Verdaccio - 查看 Verdaccio 最佳实践: - Vlt - [vlt 的无服务器 Registry](https://docs.vlt.sh/registry) (VSR) 可以在几分钟内部署到 Cloudflare Workers。 - JFrog Artifactory - Sonatype: ### 14. 审计、监控和安全工具 #### 审计 ``` npm audit # audit dependencies npm audit fix # automatically install any compatible updates npm audit signatures # verify the signatures of the dependencies pnpm audit pnpm audit --fix bun audit deno audit deno audit --socket yarn npm audit yarn npm audit --recursive # audit transitive dependencies ``` #### GitHub GitHub 提供了几种服务,可以帮助防御 `npm` 恶意软件,包括: - [Dependabot](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide):此工具会自动扫描你项目的依赖项,包括 `npm` 包,以查找已知的漏洞。 - [软件物料清单](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/exporting-a-software-bill-of-materials-for-your-repository):GitHub 允许你直接从其依赖图中导出存储库的 SBOM。SBOM 提供了项目所有依赖项的综合列表,包括传递依赖项(你依赖项的依赖项)。 - [代码扫描](https://docs.github.com/en/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning):代码扫描还可以帮助识别潜在的漏洞或可疑模式,这些漏洞或模式可能是由于集成受损的 `npm` 包而引起的。 #### OpenSSF Scorecard 免费且开源的自动化工具,用于评估与软件安全相关的许多重要启发式方法(“检查”),并为每项检查分配 0-10 的分数。本存储库中提到的几个风险作为检查的一部分包括:锁定依赖项、令牌权限、打包、签名发布等。 运行检查: 1. 使用 [GitHub Action](https://github.com/marketplace/actions/ossf-scorecard-action) 自动对你拥有的代码运行 2. 通过 [命令行](https://github.com/ossf/scorecard#scorecard-command-line-interface) 手动对你的(或其他人的)项目运行 #### Socket.dev Socket.dev 是一个安全平台,保护代码免受易受攻击和恶意的依赖项的侵害。它提供了各种工具,例如用于扫描拉取请求的 [GitHub App](https://socket.dev/features/github)、[CLI 工具](https://socket.dev/features/cli)、[Web 扩展](https://socket.dev/features/web-extension)、[VSCode 扩展](https://docs.socket.dev/docs/socket-for-vs-code) 等。这是他们关于 [AI 驱动的大规模恶意软件搜寻,2025 年 1 月](https://youtu.be/cxJPiMwoIyY) 的演讲。还有 [安装前扫描器部分](https://github.com/bodadotsh/npm-security-best-practices/tree/main?tab=readme-ov-file#preinstall-scanners) 中的 Socket Firewall `sfw` 工具。 #### Snyk Snyk 提供了一套工具来修复开源依赖项中的漏洞,包括用于在本地机器上运行漏洞扫描的 CLI、用于嵌入开发环境的 IDE 集成,以及用于以编程方式与 Snyk 集成的 API。例如,你可以[在使用前测试公共 npm 包](https://docs.snyk.io/developer-tools/snyk-cli/scan-and-maintain-projects-using-the-cli/test-public-npm-packages-before-use)或[为已知漏洞创建自动 PR](https://docs.snyk.io/scan-with-snyk/pull-requests/snyk-pull-or-merge-requests/create-automatic-prs-for-backlog-issues-and-known-vulnerabilities-backlog-prs)。 #### FOSSA FOSSA 是一个合规性和安全平台,可帮助组织管理其软件供应链的复杂性。它通过提供对所有软件组件(从[包和容器到二进制文件](https://fossa.com/products/scan/))的可见性来实现这一点。通过生成全面的 SBOM(软件物料清单),公司降低了法律和 IP 风险,整合了其代码库中的漏洞管理,并[遵守监管报告要求](https://fossa.com/solutions/due-diligence/)。 ### 15. 支持 OSS 在 JavaScript 生态系统中,OpenJS Foundation () 于 2019 年由 JS Foundation 和 Node.js Foundation 合并成立,旨在支持一些最重要的 JS 项目。下面列出了其他几个平台,你可以在这些平台上捐赠和支持你每天使用的 OSS: - GitHub Sponsors - Open Collective - Thanks.dev - Open Source Pledge - 生态系统基金: ## Star History [![Star History 图表](https://api.star-history.com/svg?repos=bodadotsh/npm-security-best-practices&type=date&legend=top-left)](https://www.star-history.com/#bodadotsh/npm-security-best-practices&type=date&legend=top-left)
标签:2FA, Cilium, CMS安全, DevSecOps, GNU通用公共许可证, JavaScript, MITM代理, Node.js, NPM, Syscall 审计, 上游代理, 依赖管理, 包管理器, 双因素认证, 开发者安全, 恶意软件防护, 数据可视化, 文档安全, 暗色界面, 最佳实践, 漏洞缓解, 生态安全, 统一API, 网络安全, 软件供应链, 软件开发工具包, 锁定文件, 防御指南, 隐私保护