ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Anthropic工程师忘了加一行.npmignore,整个Claude Code的心脏被人扒光了:从 source map 到 TypeScript 源码的完整还原与防护配置

Anthropic工程师忘了加一行.npmignore,整个Claude Code的心脏被人扒光了:从 source map 到 TypeScript 源码的完整还原与防护配置 1. 一次 npm 发布事故为什么值得每个库作者复盘你可能已经在各种技术群里刷到过那条消息某个 AI 编程工具的 npm 包里混进了 source map 文件几十万行 TypeScript 原始源码被完整还原出来。很多人当八卦看但如果你自己维护过 npm 包这件事其实是一面镜子——它照出的不是某个大厂工程师的疏忽而是绝大多数 Node.js 库作者都踩过或即将踩的坑。先把概念说清楚。source map 是构建工具生成的一种映射文件后缀是.map作用是让压缩后的 JavaScript 能对应回原始源码。它本身是好东西浏览器 DevTools 靠它调试Sentry 靠它还原堆栈。问题在于很多打包器默认会把sourcesContent字段塞进 map 文件这个字段里存的是每个源文件的完整原始代码字符串。也就是说一个.map文件几乎等于一份可读的源码副本。npm 发布时默认行为是把包目录下几乎所有文件都推上公共注册表除非你用.npmignore或package.json的files字段做排除。很多人以为.gitignore会顺带管住 npm其实两者互不相干。于是.map、测试用例、.env.example、甚至本地调试脚本都可能被一起发出去。这篇就围绕这条链路给你一套可以直接抄走的防护配置以及发布前能自动拦截的检查命令。适合所有维护 Node.js 库、CLI 工具、AI SDK 的开发者。2. 发布前先想清楚npm 到底会打包哪些文件2.1 默认打包规则和两个例外npm 打包时遵循一套固定的优先级。理解它你才知道该在哪里下手。机制作用范围优先级典型用途files字段白名单只打包列出的路径最高精确控制发布内容.npmignore黑名单排除指定路径次之排除构建产物、测试.gitignore仅当没有.npmignore时被借用最低兜底不推荐依赖强制包含package.json、README、LICENSE等不可排除元信息关键点在于files白名单的优先级高于.npmignore。如果你在package.json里写了files那么.npmignore里再写排除规则对白名单之外的路径基本没意义——因为那些路径压根不会进包。反过来如果你只写.npmignore就得自己保证排除规则足够全漏一条就出事。2.2 为什么.map最容易漏因为它在构建产物目录里和真正要发布的.js文件挨着。你写.npmignore时脑子里想的是排除 src、排除 test很容易忘了dist里还躺着.map。而且很多脚手架生成的.npmignore模板压根不含*.map这一行。注意如果你的包需要给下游用户提供调试能力可以保留 map但要确认sourcesContent已被剥离或者 map 里不包含敏感逻辑。对闭源商业库最稳妥的做法是直接不发 map。3. 可复制的防护配置.npmignore骨架 files白名单3.1 一份能直接用的.npmignore# 源码与构建输入 src/ test/ tests/ __tests__/ coverage/ *.ts !*.d.ts # source map重点 *.map *.js.map *.css.map # 配置与密钥 .env .env.* *.pem *.key secrets/ # 开发工具 .eslintrc* .prettierrc* tsconfig*.json jest.config* .vscode/ .idea/ .github/ # 杂项 *.log .DS_Store *.tgz这里*.ts配合!*.d.ts是个常用组合排除 TypeScript 源文件但保留类型声明这样下游用户仍有类型提示。如果你的包是纯 JS 发布直接删掉这两行即可。3.2 更推荐的做法files白名单黑名单永远在补漏白名单才是根治。在package.json里这样写{ name: your-lib, version: 1.0.0, main: dist/index.js, types: dist/index.d.ts, files: [ dist/**/*.js, dist/**/*.d.ts, !dist/**/*.map, README.md, LICENSE ] }files里支持!取反所以你可以先包含整个dist再单独把 map 踢掉。这种写法比.npmignore更不容易漏因为默认就是不发布只有你明确列出的才进包。提示files和.npmignore同时存在时files说了算。团队协作里建议统一用files把.npmignore删掉避免两套规则打架。4. 发布前本地验证用npm pack把包拆开看配置写完不代表生效必须实际打一次包检查。npm pack会在当前目录生成一个.tgz这就是将要上传到注册表的内容。# 生成 tarball--dry-run 只列出文件不真正打包 npm pack --dry-run # 真正打包然后解压检查 npm pack tar -tzf your-lib-1.0.0.tgztar -tzf会列出包内所有文件路径。你要重点确认三件事有没有.map、有没有src/、有没有.env之类的东西。更进一步直接检查 map 文件是否被打进去# 列出 tarball 里所有 .map 文件有输出就说明漏了 tar -tzf your-lib-1.0.0.tgz | grep \.map$ # 解压后检查 map 里是否含 sourcesContent mkdir -p /tmp/pkgcheck tar -xzf your-lib-1.0.0.tgz -C /tmp/pkgcheck grep -rl sourcesContent /tmp/pkgcheck/package/ 2/dev/null第二条命令如果打印出文件路径说明你的 map 里带着完整源码风险等级最高。把这段检查写进 CI 的prepublishOnly脚本就能在发布前自动拦截{ scripts: { prepublishOnly: npm run build node scripts/check-pack.js } }// scripts/check-pack.js const { execSync } require(child_process); const out execSync(npm pack --dry-run --json, { encoding: utf8 }); const files JSON.parse(out)[0].files.map(f f.path); const bad files.filter(f f.endsWith(.map) || f.startsWith(src/)); if (bad.length) { console.error(发布内容包含敏感文件, bad); process.exit(1); } console.log(打包检查通过共, files.length, 个文件);这段脚本在npm publish前自动跑一旦发现 map 或源码目录就直接失败从流程上堵死事故。5. 常见报错与排查清单5.1npm pack后仍然看到.map先确认files字段有没有写错路径。files里的路径是相对于package.json所在目录的dist/**/*.map和./dist/**/*.map在某些 npm 版本下行为不一致建议统一不带./。另外检查构建脚本是不是在prepublishOnly之后才生成 map导致检查时文件还不存在。5.2.npmignore写了但没生效八成是因为同时存在files字段。前面说过files优先级更高此时.npmignore对白名单外路径无效。解决办法是二选一别混用。如果确实想用.npmignore就把files从package.json里删掉。5.3 类型声明被误删下游报Could not find a declaration file这是*.ts排除规则误伤了.d.ts。确认.npmignore里有!*.d.ts这行或者改用files白名单显式包含dist/**/*.d.ts。5.4 发布后才发现问题怎么补救npm 允许在 72 小时内npm unpublish指定版本但已经下载的人无法追回。更现实的做法是立刻发一个修复版本并在 README 里说明。如果泄露的是密钥类内容第一时间轮换密钥别指望删包能解决问题。注意npm unpublish有严格限制超过时间窗口或已被大量依赖的包基本无法撤销。所以防护必须做在发布前而不是事后。6. 把检查固化进流程比记住规则更可靠回到开头那件事一行.npmignore的缺失代价是几十万行源码的公开。对个人开发者来说你未必有那么多心脏可被扒但 API Key、内部接口地址、未公开的业务逻辑泄露任何一样都够头疼。我自己的习惯是所有要发布的包package.json里只写files白名单.npmignore直接不建prepublishOnly里挂一个打包检查脚本CI 上再跑一遍npm pack --dry-run做二次确认。这套组合下来基本不会再出现发完才发现多带了文件的情况。如果你在接入模型能力做 AI 工具开发需要管理 API Key 和调用额度可以到 TaoToken API Keys 创建和管理密钥接入方式参考 TaoToken 接入文档想先验证模型效果可以直接用 模型对话。长期做编码和 Agent 类项目的话Coding Plan 会更合适。官网入口在 taotoken.net。最后留一个可以立刻执行的动作打开你最近发布过的那个包跑一遍npm pack --dry-run看看输出里有没有你不认识的文件。如果有今天就把它修掉。
返回列表