安全告警里最容易被滥用的按钮,往往不是“忽略”。
而是:
这个漏洞还在, 但我们有其他控制措施, 所以先关掉。GitHub 8 月 20 日给 Code Scanning 新增了一个专门的 dismissal reason:
Mitigated适用场景是:
漏洞仍然存在于代码中 但外部补偿控制已经降低了风险官方给出的例子包括:
Web Application Firewall Network Policy这个能力本身很合理。
真正危险的是,如果企业把Mitigated当成一个新的“关闭按钮”,很快就会形成另一种安全债:
漏洞没修 告警关了 补偿控制后来失效 没人知道所以Mitigated不能只是一列状态。
它应该是一份有证据、有Owner、有期限、可复审的风险接受记录。
Mitigated和Won’t Fix不是一回事
这两个状态经常被混。
Won't Fix的意思更接近:
我们决定不修原因可能是:
- 风险很低;
- 代码即将下线;
- 修复成本不合理;
- 误报边缘场景;
- 接受业务风险。
Mitigated则不同:
风险原本存在 但另一个控制把它压下去了例如:
代码里仍有 SQL Injection 路径 ↓ 外层 API Gateway 强制参数白名单 ↓ 攻击路径被阻断如果白名单策略被删掉:
风险重新暴露这就是补偿控制。
Mitigated至少要保存6个字段
我不会只保存:
reason = MITIGATED至少:
publicrecordMitigationRecord(StringalertId,StringcontrolType,StringevidenceRef,Stringowner,InstanteffectiveAt,InstantexpiresAt){}再加:
review_frequency更完整一点:
publicrecordMitigationRecord(StringmitigationId,StringalertId,Stringrepository,StringcontrolType,StringcontrolId,StringevidenceRef,Stringowner,Stringapprover,InstanteffectiveAt,InstantexpiresAt,DurationreviewInterval,MitigationStatusstatus){}没有expiresAt的补偿控制,我会默认认为风险很高。
为什么一定要Expiry Date
WAF Rule 今天存在。
三个月后可能:
- 规则被合并;
- 迁了网关;
- 服务改了域名;
- Network Policy 改了 Namespace;
- 新路径绕开控制;
- 业务接口重构。
如果安全告警已经关掉,代码扫描也不会每天提醒你:
“你那个补偿措施还在吗?”所以必须自己建立到期机制。
例如:
mitigation:max_validity:WAF_RULE:90dNETWORK_POLICY:90dFEATURE_FLAG:30dRATE_LIMIT:60d到期前:
14天提醒 7天提醒 当天自动进入REVIEW_REQUIREDOwner不能写“安全团队”
必须是具体责任主体。
差:
owner = Security好:
owner = platform-security-oncall或者:
owner = team-payment-api更关键的是:
谁负责保证补偿控制持续有效不一定就是发现漏洞的人。
例如 WAF 由平台团队管理,应用团队负责代码,两个Owner可能不同。
Evidence不能是一句备注
差:
“有WAF挡着”这不叫证据。
至少要能定位到:
WAF Rule ID Policy Version Namespace Rule Hash Dashboard Test Result例如:
{"control_type":"WAF","control_id":"rule-8821","policy_version":"v17","evidence":"security-test/run-1842"}这样复审时不是靠回忆。
最好做一次“补偿控制验证测试”
例如漏洞是:
/path?q=<payload>WAF 声称会拦。
那就应该有一个安全测试:
请求恶意Payload ↓ 确认返回403 ↓ 确认后端没有收到请求每次 WAF Policy 更新后自动再跑。
补偿控制不是配置存在就算有效。
必须验证:
它真的拦住了对应攻击路径Mitigation状态机
我会定义:
publicenumMitigationStatus{PROPOSED,APPROVED,ACTIVE,REVIEW_REQUIRED,EXPIRED,INVALID,SUPERSEDED}流程:
Alert Open ↓ Propose Mitigation ↓ Security Review ↓ ACTIVE ↓ Periodic Verification ↓ 继续 ACTIVE 或 INVALID / EXPIRED如果:
INVALID原漏洞自动重新进入:
OPEN“外部控制失效”必须能反向打开漏洞
这是最关键的一步。
否则系统只有:
Alert → Mitigated没有:
Mitigation Failed → Alert Reopened真正的闭环应该是:
Vulnerability ↔ Mitigation补偿控制失效,风险状态立即恢复。
一个简单的数据模型
createtablevulnerability_mitigation(mitigation_idvarchar(128)primarykey,alert_idvarchar(128)notnull,control_typevarchar(64)notnull,control_idvarchar(256)notnull,ownervarchar(128)notnull,evidence_refvarchar(512)notnull,statusvarchar(32)notnull,effective_at timestamptznotnull,expires_at timestamptznotnull,last_verified_at timestamptz,next_review_at timestamptznotnull);索引:
createindexidx_mitigation_reviewonvulnerability_mitigation(status,next_review_at);每天扫:
next_review_at <= now()生成 Review Task。
Mitigated告警仍然要算Security Debt
很多 Dashboard 一旦告警被关闭:
Open Findings ↓看起来质量变好了。
但实际上只是:
Code Fix Debt 转成了 Control Maintenance Debt所以我建议单独统计:
Open Vulnerability Mitigated Vulnerability Fixed Vulnerability不要把 Mitigated 从风险面板彻底消失。
一个很实用的指标:Mitigation Age
今天 - effective_at例如:
< 30d 30—90d 90—180d > 180d如果大量漏洞长期处于:
Mitigated > 180d说明补偿控制正在变成永久替代修复。
这通常不是好信号。
另一个指标:Mitigation Dependency Concentration
假设:
83 个漏洞 都依赖同一套WAF Policy这个 Policy 就成为:
高价值单点控制一旦配置失效,83 个风险一起恢复。
可以计算:
control_id → linked_alert_count超过阈值:
进入关键控制清单WAF不是万能Mitigation
WAF 适合:
HTTP入口 已知Payload模式 可观察请求不适合:
- 内部服务调用;
- 非HTTP路径;
- 业务逻辑漏洞;
- 权限绕过;
- 后台任务;
- 消息队列;
- 本地文件处理。
所以安全 Review 必须检查:
攻击路径是否真的经过这层控制不能只因为“我们有WAF”就判 Mitigated。
Network Policy也有边界
例如漏洞需要:
应用访问 metadata endpointNetwork Policy 阻断某些 Egress,可能有效。
但如果:
新Pod没套Policy Namespace Label变了 Sidecar绕过补偿就失效。
所以 Evidence 应该包含:
Policy Selector Namespace Pod Label Egress TestMitigated不应该绕过修复SLA
我更建议:
漏洞SLA继续存在 但可以暂停升级例如 Critical:
正常修复: 7天 Mitigated后: 30天内完成永久修复计划而不是:
Mitigated = 永久关闭具体期限按企业风险制度定。
一个审批策略
mitigation-policy:critical:security-approval:requiredbusiness-owner:requiredmax-validity:30dhigh:security-approval:requiredmax-validity:60dmedium:team-lead-approval:requiredmax-validity:90d越高风险,补偿控制有效期越短。
哪些漏洞我不会接受Mitigated
明确涉及:
认证绕过 跨租户读取 密钥泄漏 远程代码执行 支付篡改即使有外部控制,我也会要求非常高的批准级别,并优先永久修复。
因为这些漏洞一旦补偿层失效,损失上限太高。
GitHub新增这个reason真正解决了一个治理问题
过去安全团队经常被迫二选一:
Fixed Won't Fix现实里却存在第三种情况:
代码还没修 但风险已经被外层控制有效降低把它单独建模是好事。
问题在于:
Mitigated不是漏洞生命周期的终点,而是另一个需要持续维护的安全对象。
如果系统只记录一个 dismissal reason,却不记录证据、Owner、Expiry 和复审,Mitigated 很容易从“补偿控制”退化成一个更好听的“以后再修”。
我会把它理解成:
风险暂时转移到了另一层控制既然风险转移了,责任、证据和有效期也必须一起转移。