# 安全扫描器会在你的 JavaScript bundle 中发现什么

形似密钥的模式、指回你源码的 sourceMappingURL、库指纹，以及“明文或已压缩”的标签。自动化阅读者会检查什么，以及混淆后的构建会让报告发生哪些变化。

Source: https://www.afterpack.dev/zh/docs/use-cases/security-scanners

一个扫描器、一份渗透测试报告或一份客户的安全问卷问到你发布的 JavaScript 是否可读，而你需要给出答案。

## 自动化扫描器实际检查什么

扫描器不会像人那样阅读你的代码。它会对能从响应中提取出的任何文本运行一组固定的检查：用形似密钥的模式去匹配你的字符串字面量；如果存在 `sourceMappingURL` 注释，就顺着它找回你的原始源码；识别你打包进来的各个库的版本指纹；并把文件标记为明文或已压缩。

这些都不需要理解你的逻辑。模式匹配能找到密钥，无论周围的代码是否真的会运行。一份 source map 能让一次扫描只用一个请求就读到完整的源码。阅读报告的人看到的是标签，而“明文”或“已压缩”的标签告诉他们源码就摆在那里。

## 混淆后的构建会让报告发生哪些变化

字符串字面量默认会被编码，因此密钥模式检查要找的文本不在文件中。当有可读字面量残留时，[`strings.leaks.max`](https://www.afterpack.dev/zh/docs/config#strings-leaks-max) 会让构建失败，并用 [`DIAG_SURVIVING_READABLE_LITERAL`](https://www.afterpack.dev/zh/docs/diagnostics) 指出它。[生产构建](https://www.afterpack.dev/zh/docs/config#build-mode)不会写出 `.map` 文件，也不会写出 `sourceMappingURL` 注释，除非你用 [`sourceMap.enabled`](https://www.afterpack.dev/zh/docs/config#sourceMap-enabled) 和 [`sourceMap.emitUrl`](https://www.afterpack.dev/zh/docs/config#sourceMap-emitUrl) 明确要求，所以没有可以顺藤摸瓜找回源码的 map。

保护级别检查仍然会把文件报告为已混淆，这本来就是这项检查的用途。输出的形态对任何查看它的人都是可见的；不再可读的是你的名称和字符串，而在 `light` 下数字仍然可读。

## 一个能回答问卷的发布构建

一个会编码字符串并把 map 挡在输出之外的发布构建：

```json
{
  "preset": "hard",
  "strings": {
    "encode": true,
    "leaks": { "max": 0 }
  },
  "sourceMap": { "enabled": false }
}
```

[`sourceMap.enabled`](https://www.afterpack.dev/zh/docs/config#sourceMap-enabled) 在生产构建中本来就是关闭的。在这里显式设置它，能让每一台运行这次构建的机器都给出相同的答案。

## 先扫描你自己的部署

在客户动手之前，先对你自己的部署运行扫描器会运行的那些检查：

```bash
npx afterpack@latest audit https://your-site.example.com
```

[`afterpack audit`](https://www.afterpack.dev/zh/docs/audit) 首先查找暴露的密钥和 source map，然后是保护级别、危险模式、检测到的技术栈，以及它能识别出指纹的组件中已知的 CVE。在流水线中，加上 [`--diagnostics.format=json`](https://www.afterpack.dev/zh/docs/config#diagnostics-format)，让结果可以被解析而不必靠抓取文本，再用 [`--diagnostics.level`](https://www.afterpack.dev/zh/docs/config#diagnostics-level) 选择返回多少细节。对你部署的每一个环境都运行它，包括预发布环境。

在本地保持 [`protectionMap.enabled`](https://www.afterpack.dev/zh/docs/config#protectionMap-enabled) 开启。[Protection Map](https://www.afterpack.dev/zh/docs/protection-map) 能把审计发现的任何问题追溯到它所来自的源码区域。

## 干净的扫描结果不意味着什么

审计你自己的站点，能告诉你任何阅读者已经可以从中提取出什么，而一个编码了字面量、没有发布 map 的构建，其可读文本远少于构建它所用的源码。

混淆修复不了扫描发现的问题。有漏洞的依赖、注入 bug，或者一个已经泄露出去的凭据，在构建之后仍然存在于运行中的应用里，所以请在源头修复它们，并轮换凭据。

## 下一步

- [审计](https://www.afterpack.dev/zh/docs/audit)：命令参考，以及如何阅读结果。
- [威胁模型](https://www.afterpack.dev/zh/docs/threat-model#the-boundary)：静态阅读者与运行你代码的人之间的边界。
- [诊断](https://www.afterpack.dev/zh/docs/diagnostics)：构建或审计可能发出的每一个代码。
