漏洞没修也能关闭?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/