SAST 扫描
依赖审计覆盖你导入的代码;SAST 覆盖你编写的代码。它通过模式匹配(以及污点模式下的数据流追踪)来发现经典漏洞:命令/SQL 注入、路径遍历、不安全反序列化、在不可信输入上执行 eval/动态执行、硬编码加密、缺少认证检查。误报率高是固有特点——规范是按可达性分类,而非完全忽略。
何时运行
- 发布之前,针对差异或整个代码树。
- 当你添加处理不可信输入的代码时(新工具、端点、解析器、shell 调用)。
- 在 CI 中对 PR 运行时(差异范围,速度快且仅标记新问题)。
运行它
# semgrep — 安全规则集。`auto` 会根据检测到的语言自动选择规则。
semgrep scan --config auto --error .
# 聚焦的、信号更高的规则集(比 auto 噪音更少):
semgrep scan --config p/security-audit --config p/secrets --config p/command-injection .
# 仅差异(CI 中针对 PR — 快速,仅 NEW 发现):
semgrep scan --config auto --baseline-commit origin/main .
对于更深层的数据流分析(不可信输入是否真正到达接收点?),CodeQL 更强大但更重:
codeql database create db --language=javascript # 或 rust, python, …
codeql database analyze db --format=sarif-latest --output=results.sarif \
codeql/javascript-queries:codeql-suites/javascript-security-extended.qls
分类 — 追踪,而非忽略
针对每个发现,追踪 源 → 接收点 路径:
- 输入是否受攻击者控制? 对硬编码常量执行
child_process.exec没问题;但对请求参数执行则属于命令注入漏洞。semgrep 标记接收点;你来确认源。 - 两者之间是否有消毒器? 如果值在到达接收点前被验证/转义(zod 模式、白名单、参数化查询),则是误报——将其标记为
# nosemgrep: <rule-id>并附上一行原因,而非空白忽略。 - 真实漏洞? 在源头(验证/转义输入)或接收点(参数化、使用安全 API)修复,而不是通过抑制警告来修复。
切勿为了清空列表而全面禁用某条规则——这样会压制噪音中唯一一个真正的命中。按行抑制,并附上原因。
实际要修复的内容(按价值从高到低)
- 注入(命令/SQL/模板)在任何用户可触及的路径上——最高严重性、最常被利用的类别。
- 路径遍历——未经验证的路径到达文件读/写(写入文件的代理正是此类风险;通过作用域检查进行门控)。
- 对动态字符串的不安全 exec/eval。
- 安全上下文中的硬编码加密/弱随机性。
边界
SAST 静态地检查一个仓库的源代码——它无法看到运行时配置、环境驱动的代码路径或仅在跨服务边界时出现的缺陷。它补充但从不取代真正的威胁模型和 [[dependency-audit]]。对于代理/工具运行时,最强大的控制往往是架构层面的(内核门控每个动作),而非逐行检查——SAST 验证了该边界周围的代码。将其纳入 [[security-preflight]]。