DAST不能在代码提交阶段拦截SQL注入,因其需应用运行后才能发送请求验证漏洞;真正能快速拦截的是SAST工具如Semgrep或SonarQube,它们基于源码分析,可在PR触发时秒级检测拼接SQL等缺陷。

DAST 不能在代码提交阶段拦截 SQL 注入
直接把 DAST 放进 PR 构建流程里,指望它“快速拦截”SQL注入,是方向性错误。DAST 是动态测试工具,必须等应用真正跑起来、监听端口、能接收 HTTP 请求后才能工作。它不看源码,只发请求、看响应——所以它根本不知道哪行代码有 cursor.execute("SELECT * FROM " + table) 这种拼接,只能事后验证“这个 URL 是否被成功注入”。CI 流水线里若在服务未启动时就运行 DAST,Connection refused 或 timeout 是必然结果。
为什么 DAST 在 CI 中必须放在部署之后
DAST 的生效前提是:一个可访问的、带漏洞逻辑的运行实例。常见误操作包括:
- 在
build阶段就调用zaproxy或nikto扫描本地http://localhost:8080——此时服务大概率没启动,或只暴露了健康检查端点 - 扫描镜像但不启动容器,等于对着 Dockerfile 开枪
- 用 DAST 扫测试环境(如 staging),却把结果当“代码级阻断依据”,导致修复反馈延迟数小时甚至数天
正确顺序只能是:build → deploy-to-temp-env → wait-for-ready → run-dast → report-vulns → tear-down。极狐 GitLab 官方文档也明确要求 DAST job 必须依赖 review 或 deploy stage 的成功输出。
想“快速拦截”,该用 SAST 而不是 DAST
真正能在代码提交瞬间卡住 SQL 注入的,是 SAST 工具链。比如:
-
semgrep配合规则p/python.lang.security.insecure-sql-string-concatenation,1 秒内就能报出query = "SELECT * FROM " + user_table -
SonarQube启用java:S2077(SQL query string concatenation)或python:S5131,对参数绑定缺失的语句打标 - 关键配置必须加
--error,否则 CI 不会失败;必须--exclude=tests/,否则测试用例里的"SELECT * FROM user_test"会误报
这些工具跑的是 AST 或字节码,不依赖运行环境,平均耗时 2–8 秒,完全适配 PR 触发场景。
如果非要用 DAST 做“准实时反馈”,得绕过它的天然延迟
DAST 本身无法提速,但可以靠流程设计压缩感知周期:
- 只对
main分支合并前的临时环境做 DAST,跳过 feature branch —— 减少 80% 无效扫描 - 限制扫描范围:用
--url http://temp-env/api/login替代全站爬取,聚焦高危接口 - 预置已知 payload 列表(如
' OR '1'='1、admin' --),禁用模糊探测(--spider关闭),把耗时从 15 分钟压到 90 秒内 - 把 DAST 报告解析成 SARIF 格式,接入 GitHub Code Scanning,让漏洞直接显示在 PR 的 Files Changed 里——虽然仍是“部署后发现”,但开发者能立刻看到影响位置
记住:DAST 的价值不在“快”,而在“真实上下文验证”。它能确认 PreparedStatement 写对了但前端没过滤、或 WAF 规则漏掉了某个编码变体。指望它替代 SAST 去拦代码,就像让消防车去管电路布线——职责错位,越用力越偏。

















