漏洞没修也能关闭?Mitigated该怎么管
安全告警里最容易被滥用的按钮,往往不是“忽略”。
而是:
这个漏洞还在,
但我们有其他控制措施,
所以先关掉。
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
至少:
public record MitigationRecord(
String alertId,
String controlType,
String evidenceRef,
String owner,
Instant effectiveAt,
Instant expiresAt) {
}
再加:
review_frequency
更完整一点:
public record MitigationRecord(
String mitigationId,
String alertId,
String repository,
String controlType,
String controlId,
String evidenceRef,
String owner,
String approver,
Instant effectiveAt,
Instant expiresAt,
Duration reviewInterval,
MitigationStatus status) {
}
没有 expiresAt 的补偿控制,我会默认认为风险很高。
为什么一定要Expiry Date
WAF Rule 今天存在。
三个月后可能:
- 规则被合并;
- 迁了网关;
- 服务改了域名;
- Network Policy 改了 Namespace;
- 新路径绕开控制;
- 业务接口重构。
如果安全告警已经关掉,代码扫描也不会每天提醒你:
“你那个补偿措施还在吗?”
所以必须自己建立到期机制。
例如:
mitigation:
max_validity:
WAF_RULE: 90d
NETWORK_POLICY: 90d
FEATURE_FLAG: 30d
RATE_LIMIT: 60d
到期前:
14天提醒
7天提醒
当天自动进入REVIEW_REQUIRED
Owner不能写“安全团队”
必须是具体责任主体。
差:
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=
WAF 声称会拦。
那就应该有一个安全测试:
请求恶意Payload
↓
确认返回403
↓
确认后端没有收到请求
每次 WAF Policy 更新后自动再跑。
补偿控制不是配置存在就算有效。
必须验证:
它真的拦住了对应攻击路径
Mitigation状态机
我会定义:
public enum MitigationStatus {
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
补偿控制失效,风险状态立即恢复。
一个简单的数据模型
create table vulnerability_mitigation (
mitigation_id varchar(128) primary key,
alert_id varchar(128) not null,
control_type varchar(64) not null,
control_id varchar(256) not null,
owner varchar(128) not null,
evidence_ref varchar(512) not null,
status varchar(32) not null,
effective_at timestamptz not null,
expires_at timestamptz not null,
last_verified_at timestamptz,
next_review_at timestamptz not null
);
索引:
create index idx_mitigation_review
on vulnerability_mitigation(
status,
next_review_at
);
每天扫:
next_review_at 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 endpoint
Network Policy 阻断某些 Egress,可能有效。
但如果:
新Pod没套Policy
Namespace Label变了
Sidecar绕过
补偿就失效。
所以 Evidence 应该包含:
Policy Selector
Namespace
Pod Label
Egress Test
Mitigated不应该绕过修复SLA
我更建议:
漏洞SLA继续存在
但可以暂停升级
例如 Critical:
正常修复:
7天
Mitigated后:
30天内完成永久修复计划
而不是:
Mitigated = 永久关闭
具体期限按企业风险制度定。
一个审批策略
mitigation-policy:
critical:
security-approval: required
business-owner: required
max-validity: 30d
high:
security-approval: required
max-validity: 60d
medium:
team-lead-approval: required
max-validity: 90d
越高风险,补偿控制有效期越短。
哪些漏洞我不会接受Mitigated
明确涉及:
认证绕过
跨租户读取
密钥泄漏
远程代码执行
支付篡改
即使有外部控制,我也会要求非常高的批准级别,并优先永久修复。
因为这些漏洞一旦补偿层失效,损失上限太高。
GitHub新增这个reason真正解决了一个治理问题
过去安全团队经常被迫二选一:
Fixed
Won't Fix
现实里却存在第三种情况:
代码还没修
但风险已经被外层控制有效降低
把它单独建模是好事。
问题在于:
Mitigated不是漏洞生命周期的终点,而是另一个需要持续维护的安全对象。
如果系统只记录一个 dismissal reason,却不记录证据、Owner、Expiry 和复审,Mitigated 很容易从“补偿控制”退化成一个更好听的“以后再修”。
我会把它理解成:
风险暂时转移到了另一层控制
既然风险转移了,责任、证据和有效期也必须一起转移。
更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界:
https://www.zyentor.com/