漏洞管理Skill vulnerability-management

本技能用于漏洞生命周期的全面管理,从发现到验证,包括 CVE 跟踪、CVSS 评分、风险优先级排序、修复工作流程、漏洞披露和 Bug Bounty 程序。关键词:漏洞管理,CVE,CVSS,风险优先级,修复,SLA,EPSS,KEV,漏洞披露,Bug Bounty,扫描,资产清单。

安全运维 0 次安装 0 次浏览 更新于 3/11/2026

name: 漏洞管理 description: 漏洞生命周期管理,包括 CVE 跟踪、CVSS 评分、风险优先级排序、修复工作流程和协调披露实践 allowed-tools: Read, Grep, Glob, Write, Edit, Task, mcp__perplexity__, mcp__context7__

漏洞管理

从发现到修复和验证的端到端漏洞生命周期。

何时使用此技能

关键词: 漏洞管理,CVE,CVSS,修复,打补丁,风险优先级排序,EPSS,KEV,漏洞披露,Bug Bounty,补丁管理,漏洞扫描,资产清单

在以下情况下使用此技能:

  • 设置漏洞管理程序
  • 解释 CVSS 分数和指标
  • 优先排序漏洞修复
  • 设计补丁管理流程
  • 实施漏洞披露程序
  • 管理 Bug Bounty 程序
  • 跟踪 CVE/CWE/NVD 数据
  • 创建修复的 SLA 策略

快速决策树

  1. 理解漏洞分数? → 参见 CVSS 评分概述
  2. 优先修复什么? → 参见 基于风险优先级排序
  3. 设计修复工作流程? → 参见 references/remediation-workflow.md
  4. 设置披露程序? → 参见 漏洞披露
  5. CVSS 计算细节? → 参见 references/cvss-scoring.md

漏洞生命周期

┌─────────────────────────────────────────────────────────────────┐
│               漏洞管理生命周期                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  发现 ──▶ 评估 ──▶ 优先级排序 ──▶ 修复 ──▶ 验证                │
│      │          │           │              │            │        │
│      ▼          ▼           ▼              ▼            ▼        │
│  ┌───────┐  ┌───────┐  ┌────────┐    ┌────────┐   ┌────────┐   │
│  │扫描器│  │CVSS   │  │风险    │    │补丁/   │   │重新扫描/│   │
│  │渗透测试│  │上下文│  │矩阵    │    │配置    │   │验证    │   │
│  │Bug    │  │资产  │  │EPSS+KEV│    │缓解    │   │关闭    │   │
│  │Bounty │  │影响  │  │SLA     │    │接受    │   │        │   │
│  └───────┘  └───────┘  └────────┘    └────────┘   └────────┘   │
│                                                                  │
│  持续监控 ◀────────────────────────────────────────────────────┤
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

CVSS 评分概述

通用漏洞评分系统提供标准化的严重性评级。

CVSS v3.1 分数范围

分数 严重性 典型 SLA
9.0-10.0 严重 24-72 小时
7.0-8.9 7-14 天
4.0-6.9 30-60 天
0.1-3.9 90-180 天
0.0 风险接受

CVSS v3.1 指标组

public enum AttackVector { Network, Adjacent, Local, Physical }
public enum AttackComplexity { Low, High }
public enum PrivilegesRequired { None, Low, High }
public enum UserInteraction { None, Required }
public enum Scope { Unchanged, Changed }
public enum ImpactLevel { None, Low, High }

/// <summary>
/// CVSS v3.1 基础分数向量
/// </summary>
public sealed record CvssV31Vector(
    AttackVector AttackVector,
    AttackComplexity AttackComplexity,
    PrivilegesRequired PrivilegesRequired,
    UserInteraction UserInteraction,
    Scope Scope,
    ImpactLevel Confidentiality,
    ImpactLevel Integrity,
    ImpactLevel Availability)
{
    private static readonly FrozenDictionary<AttackVector, (string Code, double Value)> AvMetrics =
        new Dictionary<AttackVector, (string, double)>
        {
            [AttackVector.Network] = ("N", 0.85),
            [AttackVector.Adjacent] = ("A", 0.62),
            [AttackVector.Local] = ("L", 0.55),
            [AttackVector.Physical] = ("P", 0.20)
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<AttackComplexity, (string Code, double Value)> AcMetrics =
        new Dictionary<AttackComplexity, (string, double)>
        {
            [AttackComplexity.Low] = ("L", 0.77),
            [AttackComplexity.High] = ("H", 0.44)
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<ImpactLevel, (string Code, double Value)> ImpactMetrics =
        new Dictionary<ImpactLevel, (string, double)>
        {
            [ImpactLevel.None] = ("N", 0.00),
            [ImpactLevel.Low] = ("L", 0.22),
            [ImpactLevel.High] = ("H", 0.56)
        }.ToFrozenDictionary();

    public string ToVectorString() =>
        $"CVSS:3.1/AV:{AvMetrics[AttackVector].Code}/" +
        $"AC:{AcMetrics[AttackComplexity].Code}/" +
        $"PR:{GetPrCode()}/" +
        $"UI:{(UserInteraction == UserInteraction.None ? "N" : "R")}/" +
        $"S:{(Scope == Scope.Unchanged ? "U" : "C")}/" +
        $"C:{ImpactMetrics[Confidentiality].Code}/" +
        $"I:{ImpactMetrics[Integrity].Code}/" +
        $"A:{ImpactMetrics[Availability].Code}";

    public double CalculateBaseScore()
    {
        // 影响子分数
        var iscBase = 1 - (
            (1 - ImpactMetrics[Confidentiality].Value) *
            (1 - ImpactMetrics[Integrity].Value) *
            (1 - ImpactMetrics[Availability].Value));

        var impact = Scope == Scope.Unchanged
            ? 6.42 * iscBase
            : 7.52 * (iscBase - 0.029) - 3.25 * Math.Pow(iscBase - 0.02, 15);

        // 可利用性子分数
        var exploitability = 8.22 *
            AvMetrics[AttackVector].Value *
            AcMetrics[AttackComplexity].Value *
            GetPrValue() *
            (UserInteraction == UserInteraction.None ? 0.85 : 0.62);

        if (impact <= 0) return 0.0;

        var score = Scope == Scope.Unchanged
            ? Math.Min(impact + exploitability, 10)
            : Math.Min(1.08 * (impact + exploitability), 10);

        return Math.Round(score * 10) / 10; // 四舍五入到 1 位小数
    }

    private string GetPrCode() => PrivilegesRequired switch
    {
        PrivilegesRequired.None => "N",
        PrivilegesRequired.Low => "L",
        PrivilegesRequired.High => "H",
        _ => "N"
    };

    private double GetPrValue() => (PrivilegesRequired, Scope) switch
    {
        (PrivilegesRequired.None, _) => 0.85,
        (PrivilegesRequired.Low, Scope.Unchanged) => 0.62,
        (PrivilegesRequired.Low, Scope.Changed) => 0.68,
        (PrivilegesRequired.High, Scope.Unchanged) => 0.27,
        (PrivilegesRequired.High, Scope.Changed) => 0.50,
        _ => 0.85
    };
}

// 示例:Log4Shell (CVE-2021-44228)
var log4shell = new CvssV31Vector(
    AttackVector: AttackVector.Network,
    AttackComplexity: AttackComplexity.Low,
    PrivilegesRequired: PrivilegesRequired.None,
    UserInteraction: UserInteraction.None,
    Scope: Scope.Changed,
    Confidentiality: ImpactLevel.High,
    Integrity: ImpactLevel.High,
    Availability: ImpactLevel.High);

Console.WriteLine($"向量: {log4shell.ToVectorString()}");
Console.WriteLine($"分数: {log4shell.CalculateBaseScore()}"); // 10.0

有关详细 CVSS 评分包括时间和环境指标,参见 references/cvss-scoring.md

基于风险优先级排序

CVSS 单独不足以进行优先级排序。使用多种信号:

优先级排序框架

using System.Collections.Frozen;

public enum AssetCriticality { Low, Medium, High, Critical }
public enum AssetExposure { Internal, Dmz, External }
public enum DataSensitivity { Public, Internal, Confidential, Restricted }
public enum ExploitMaturity { Unproven, Poc, Functional, High }

/// <summary>漏洞优先级排序的完整上下文</summary>
public sealed record VulnerabilityContext(
    string CveId,
    double CvssBase,
    double? CvssEnvironmental = null,
    double? CvssTemporal = null,
    double EpssProbability = 0.0,      // 0-1 的利用概率
    double EpssPercentile = 0.0,       // 相对排名
    bool InKev = false,
    DateTimeOffset? KevDueDate = null,
    AssetCriticality AssetCriticality = AssetCriticality.Medium,
    AssetExposure AssetExposure = AssetExposure.Internal,
    DataSensitivity DataSensitivity = DataSensitivity.Internal,
    bool PublicExploit = false,
    ExploitMaturity ExploitMaturity = ExploitMaturity.Unproven);

public sealed record PriorityResult(double Score, string Category, int SlaHours);

/// <summary>多因素漏洞优先级排序</summary>
public sealed class RiskPrioritizer
{
    // 不同因素的权重(根据组织优先级调整)
    private static readonly FrozenDictionary<string, double> Weights =
        new Dictionary<string, double>
        {
            ["cvss"] = 0.25,
            ["epss"] = 0.20,
            ["kev"] = 0.20,
            ["asset"] = 0.20,
            ["exploit"] = 0.15
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<AssetCriticality, double> AssetScores =
        new Dictionary<AssetCriticality, double>
        {
            [AssetCriticality.Low] = 25,
            [AssetCriticality.Medium] = 50,
            [AssetCriticality.High] = 75,
            [AssetCriticality.Critical] = 100
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<AssetExposure, double> ExposureMultipliers =
        new Dictionary<AssetExposure, double>
        {
            [AssetExposure.Internal] = 0.7,
            [AssetExposure.Dmz] = 0.85,
            [AssetExposure.External] = 1.0
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<DataSensitivity, double> DataMultipliers =
        new Dictionary<DataSensitivity, double>
        {
            [DataSensitivity.Public] = 0.5,
            [DataSensitivity.Internal] = 0.7,
            [DataSensitivity.Confidential] = 0.9,
            [DataSensitivity.Restricted] = 1.0
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<ExploitMaturity, double> ExploitScores =
        new Dictionary<ExploitMaturity, double>
        {
            [ExploitMaturity.Unproven] = 20,
            [ExploitMaturity.Poc] = 50,
            [ExploitMaturity.Functional] = 80,
            [ExploitMaturity.High] = 100
        }.ToFrozenDictionary();

    /// <summary>计算综合优先级分数(0-100)</summary>
    public double CalculatePriorityScore(VulnerabilityContext vuln)
    {
        // CVSS 组件(0-10 归一化到 0-100)
        var cvssScore = (vuln.CvssEnvironmental ?? vuln.CvssTemporal ?? vuln.CvssBase) * 10;

        // EPSS 组件(概率 * 100)
        var epssScore = vuln.EpssProbability * 100;

        // KEV 组件(二元提升)
        var kevScore = vuln.InKev ? 100.0 : 0.0;

        // 资产关键性组件
        var assetScore = AssetScores[vuln.AssetCriticality]
            * ExposureMultipliers[vuln.AssetExposure]
            * DataMultipliers[vuln.DataSensitivity];

        // 利用成熟度组件
        var exploitScore = ExploitScores[vuln.ExploitMaturity];
        if (vuln.PublicExploit)
            exploitScore = Math.Max(exploitScore, 60);

        // 加权综合
        var priority =
            Weights["cvss"] * cvssScore +
            Weights["epss"] * epssScore +
            Weights["kev"] * kevScore +
            Weights["asset"] * assetScore +
            Weights["exploit"] * exploitScore;

        return Math.Round(priority, 1);
    }

    /// <summary>分类优先级分数</summary>
    public static string GetPriorityCategory(double score) => score switch
    {
        >= 80 => "P1 - 严重",
        >= 60 => "P2 - 高",
        >= 40 => "P3 - 中",
        _ => "P4 - 低"
    };

    /// <summary>获取修复 SLA 小时数</summary>
    public static int GetSlaHours(double score) => score switch
    {
        >= 80 => 24,
        >= 60 => 168,   // 7 天
        >= 40 => 720,   // 30 天
        _ => 2160       // 90 天
    };

    /// <summary>计算完整的优先级结果</summary>
    public PriorityResult Evaluate(VulnerabilityContext vuln)
    {
        var score = CalculatePriorityScore(vuln);
        return new PriorityResult(score, GetPriorityCategory(score), GetSlaHours(score));
    }
}

// 示例用法
var vuln = new VulnerabilityContext(
    CveId: "CVE-2021-44228",
    CvssBase: 10.0,
    EpssProbability: 0.975,
    EpssPercentile: 0.999,
    InKev: true,
    AssetCriticality: AssetCriticality.Critical,
    AssetExposure: AssetExposure.External,
    DataSensitivity: DataSensitivity.Confidential,
    PublicExploit: true,
    ExploitMaturity: ExploitMaturity.High);

var prioritizer = new RiskPrioritizer();
var result = prioritizer.Evaluate(vuln);

Console.WriteLine($"优先级分数: {result.Score}");  // ~95
Console.WriteLine($"类别: {result.Category}");     // P1 - 严重
Console.WriteLine($"SLA: {result.SlaHours} 小时");    // 24

EPSS 集成

using System.Net.Http.Json;
using System.Text.Json.Serialization;

public sealed record EpssScore(
    string Cve,
    double Epss,
    double Percentile,
    string Date);

/// <summary>EPSS(利用预测评分系统)API 客户端</summary>
public sealed class EpssClient(HttpClient httpClient)
{
    private const string BaseUrl = "https://api.first.org/data/v1/epss";

    /// <summary>获取 CVE 的 EPSS 分数</summary>
    public async Task<EpssScore?> GetScoreAsync(string cveId, CancellationToken ct = default)
    {
        var response = await httpClient.GetFromJsonAsync<EpssResponse>(
            $"{BaseUrl}?cve={Uri.EscapeDataString(cveId)}", ct);

        if (response?.Data is not { Count: > 0 })
            return null;

        var data = response.Data[0];
        return new EpssScore(data.Cve, data.Epss, data.Percentile, data.Date);
    }

    /// <summary>获取多个 CVE 的 EPSS 分数</summary>
    public async Task<IReadOnlyList<EpssScore>> GetBulkScoresAsync(
        IEnumerable<string> cveIds,
        CancellationToken ct = default)
    {
        var cveParam = string.Join(",", cveIds.Select(Uri.EscapeDataString));
        var response = await httpClient.GetFromJsonAsync<EpssResponse>(
            $"{BaseUrl}?cve={cveParam}", ct);

        return response?.Data?
            .Select(d => new EpssScore(d.Cve, d.Epss, d.Percentile, d.Date))
            .ToArray() ?? [];
    }

    private sealed record EpssResponse(
        [property: JsonPropertyName("data")] List<EpssData>? Data);

    private sealed record EpssData(
        [property: JsonPropertyName("cve")] string Cve,
        [property: JsonPropertyName("epss")] double Epss,
        [property: JsonPropertyName("percentile")] double Percentile,
        [property: JsonPropertyName("date")] string Date);
}

// 注册到 IHttpClientFactory
// services.AddHttpClient<EpssClient>();

KEV(已知被利用漏洞)集成

using System.Collections.Concurrent;
using System.Net.Http.Json;
using System.Text.Json.Serialization;

/// <summary>CISA 已知被利用漏洞条目</summary>
public sealed record KevEntry(
    string CveId,
    string VendorProject,
    string Product,
    string VulnerabilityName,
    DateOnly DateAdded,
    DateOnly DueDate,
    string ShortDescription,
    string RequiredAction,
    string Notes);

/// <summary>CISA KEV 目录客户端</summary>
public sealed class KevClient(HttpClient httpClient)
{
    private const string CatalogUrl =
        "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json";

    private readonly ConcurrentDictionary<string, KevEntry> _cache = new();
    private DateTimeOffset _lastRefresh = DateTimeOffset.MinValue;

    public DateTimeOffset LastRefresh => _lastRefresh;

    /// <summary>从 CISA 刷新 KEV 目录</summary>
    public async Task RefreshCatalogAsync(CancellationToken ct = default)
    {
        var catalog = await httpClient.GetFromJsonAsync<KevCatalog>(CatalogUrl, ct)
            ?? throw new InvalidOperationException("获取 KEV 目录失败");

        _cache.Clear();
        foreach (var vuln in catalog.Vulnerabilities ?? [])
        {
            var entry = new KevEntry(
                CveId: vuln.CveId,
                VendorProject: vuln.VendorProject,
                Product: vuln.Product,
                VulnerabilityName: vuln.VulnerabilityName,
                DateAdded: DateOnly.Parse(vuln.DateAdded),
                DueDate: DateOnly.Parse(vuln.DueDate),
                ShortDescription: vuln.ShortDescription,
                RequiredAction: vuln.RequiredAction,
                Notes: vuln.Notes ?? string.Empty);

            _cache[entry.CveId] = entry;
        }

        _lastRefresh = DateTimeOffset.UtcNow;
    }

    /// <summary>检查 CVE 是否在 KEV 目录中</summary>
    public bool IsInKev(string cveId) => _cache.ContainsKey(cveId);

    /// <summary>获取 CVE 的 KEV 条目</summary>
    public KevEntry? GetEntry(string cveId) =>
        _cache.TryGetValue(cveId, out var entry) ? entry : null;

    /// <summary>获取所有过期的 KEV 条目</summary>
    public IReadOnlyList<KevEntry> GetOverdue()
    {
        var today = DateOnly.FromDateTime(DateTime.UtcNow);
        return _cache.Values.Where(e => e.DueDate < today).ToArray();
    }

    private sealed record KevCatalog(
        [property: JsonPropertyName("vulnerabilities")] List<KevVuln>? Vulnerabilities);

    private sealed record KevVuln(
        [property: JsonPropertyName("cveID")] string CveId,
        [property: JsonPropertyName("vendorProject")] string VendorProject,
        [property: JsonPropertyName("product")] string Product,
        [property: JsonPropertyName("vulnerabilityName")] string VulnerabilityName,
        [property: JsonPropertyName("dateAdded")] string DateAdded,
        [property: JsonPropertyName("dueDate")] string DueDate,
        [property: JsonPropertyName("shortDescription")] string ShortDescription,
        [property: JsonPropertyName("requiredAction")] string RequiredAction,
        [property: JsonPropertyName("notes")] string? Notes);
}

// 注册到 IHttpClientFactory
// services.AddHttpClient<KevClient>();

漏洞披露

Security.txt

# security.txt - RFC 9116 兼容
# 放置在 /.well-known/security.txt

Contact: mailto:security@example.com
Contact: https://example.com/security/report
Expires: 2025-12-31T23:59:59.000Z
Encryption: https://example.com/.well-known/pgp-key.txt
Acknowledgments: https://example.com/security/hall-of-fame
Preferred-Languages: en
Canonical: https://example.com/.well-known/security.txt
Policy: https://example.com/security/policy
Hiring: https://example.com/careers/security

披露策略

# 漏洞披露策略

## 范围
以下资产在范围内:
- *.example.com
- Example 移动应用(iOS, Android)
- Example API (api.example.com)

范围外:
- 第三方服务
- 社会工程攻击
- 物理安全测试
- 拒绝服务攻击

## 参与规则
- 不要访问或修改他人的数据
- 如果访问用户数据,立即停止测试并报告
- 在我们解决问题之前,不要公开披露
- 提供足够的细节以重现问题

## 安全港
对于以下研究人员,我们不会采取法律行动:
- 善意行事
- 避免隐私侵犯
- 不造成服务中断
- 遵循负责任的披露时间表

## 时间表
- 确认:3 个工作日
- 初步评估:7 个工作日
- 状态更新:每 14 天
- 解决目标:90 天(根据严重性变化)

## 奖励
| 严重性 | 奖金范围 |
|----------|--------------|
| 严重 | $5,000 - $25,000 |
| 高 | $2,000 - $5,000 |
| 中 | $500 - $2,000 |
| 低 | $100 - $500 |

Bug Bounty 集成

using System.Collections.Frozen;

public enum ReportStatus
{
    New,
    Triaged,
    Duplicate,
    Informative,
    NotApplicable,
    Resolved,
    BountyAwarded
}

public enum BountySeverity { Critical, High, Medium, Low }

/// <summary>Bug Bounty 报告跟踪</summary>
public sealed record BountyReport(
    string Id,
    string Title,
    string Reporter,
    BountySeverity Severity,
    ReportStatus Status,
    DateTimeOffset SubmittedAt,
    string Asset,
    string Description,
    string ReproductionSteps,
    string Impact,
    string? CveId = null,
    decimal? BountyAmount = null,
    DateTimeOffset? ResolvedAt = null);

public sealed record SlaComplianceResult(
    int SlaHours,
    double ElapsedHours,
    bool IsCompliant,
    double RemainingHours);

public sealed record DisclosureTimeline(
    DateTimeOffset Submitted,
    DateTimeOffset TriageDeadline,
    DateTimeOffset InitialResponse,
    DateTimeOffset ResolutionTarget,
    DateTimeOffset PublicDisclosure);

/// <summary>管理 Bug Bounty 程序操作</summary>
public sealed class BugBountyManager
{
    private static readonly FrozenDictionary<BountySeverity, (decimal Min, decimal Max)> SeverityBountyRange =
        new Dictionary<BountySeverity, (decimal, decimal)>
        {
            [BountySeverity.Critical] = (5000, 25000),
            [BountySeverity.High] = (2000, 5000),
            [BountySeverity.Medium] = (500, 2000),
            [BountySeverity.Low] = (100, 500)
        }.ToFrozenDictionary();

    private static readonly FrozenDictionary<BountySeverity, int> SlaHours =
        new Dictionary<BountySeverity, int>
        {
            [BountySeverity.Critical] = 24,
            [BountySeverity.High] = 72,
            [BountySeverity.Medium] = 168,
            [BountySeverity.Low] = 336
        }.ToFrozenDictionary();

    /// <summary>基于严重性和因素计算奖金金额</summary>
    public decimal CalculateBounty(
        BountySeverity severity,
        double impactFactor = 1.0,
        double qualityFactor = 1.0)
    {
        var (minBounty, maxBounty) = SeverityBountyRange.GetValueOrDefault(severity);

        // 基础奖金为中间值
        var baseBounty = (minBounty + maxBounty) / 2;

        // 应用因素
        var adjusted = baseBounty * (decimal)impactFactor * (decimal)qualityFactor;

        // 钳制到范围
        return Math.Clamp(adjusted, minBounty, maxBounty);
    }

    /// <summary>检查报告是否在 SLA 内</summary>
    public SlaComplianceResult CheckSlaCompliance(BountyReport report)
    {
        var slaHours = SlaHours.GetValueOrDefault(report.Severity, 168);
        var elapsed = (DateTimeOffset.UtcNow - report.SubmittedAt).TotalHours;

        return new SlaComplianceResult(
            SlaHours: slaHours,
            ElapsedHours: elapsed,
            IsCompliant: elapsed <= slaHours,
            RemainingHours: Math.Max(0, slaHours - elapsed));
    }

    /// <summary>生成协调披露时间表</summary>
    public static DisclosureTimeline GenerateDisclosureTimeline(DateTimeOffset submitted) =>
        new(
            Submitted: submitted,
            TriageDeadline: submitted.AddDays(3),
            InitialResponse: submitted.AddDays(7),
            ResolutionTarget: submitted.AddDays(90),
            PublicDisclosure: submitted.AddDays(104)); // 90 + 14 天
}

SLA 配置

# vulnerability-sla.yaml
sla_policy:
  name: "生产漏洞 SLA"
  version: "2.0"
  effective_date: "2024-01-01"

  # 按 CVSS 分数默认 SLA
  severity_slas:
    critical:  # CVSS 9.0-10.0
      detection_to_triage: 4h
      triage_to_remediation_start: 24h
      remediation_sla: 72h
      total_sla: 96h
      escalation_path:
        - level: 1
          after: 24h
          notify: [security-team, engineering-lead]
        - level: 2
          after: 48h
          notify: [ciso, vp-engineering]
        - level: 3
          after: 72h
          notify: [ceo, board]

    high:  # CVSS 7.0-8.9
      detection_to_triage: 8h
      triage_to_remediation_start: 48h
      remediation_sla: 168h  # 7 天
      total_sla: 216h
      escalation_path:
        - level: 1
          after: 72h
          notify: [security-team]
        - level: 2
          after: 120h
          notify: [ciso]

    medium:  # CVSS 4.0-6.9
      detection_to_triage: 24h
      triage_to_remediation_start: 168h
      remediation_sla: 720h  # 30 天
      total_sla: 888h
      escalation_path:
        - level: 1
          after: 336h
          notify: [security-team]

    low:  # CVSS 0.1-3.9
      detection_to_triage: 72h
      triage_to_remediation_start: 336h
      remediation_sla: 2160h  # 90 天
      total_sla: 2496h
      escalation_path: []

  # 特定条件覆盖
  overrides:
    - condition: "in_kev == true"
      override_sla: "critical"
      reason: "CISA KEV 要求加速修复"

    - condition: "epss_percentile >= 0.95"
      decrease_sla_percent: 50
      reason: "高利用概率"

    - condition: "asset_exposure == 'external' and asset_criticality == 'critical'"
      override_sla: "critical"
      reason: "面向互联网的关键资产"

  # 风险接受策略
  risk_acceptance:
    allowed_severities: [low, medium]
    max_acceptance_period: 180d
    required_approvers:
      low: [security-team-lead]
      medium: [ciso]
    documentation_required: true
    review_frequency: 30d

安全检查清单

在最终确定漏洞管理设置之前:

  • [ ] 资产清单完整且最新
  • [ ] 对所有资产的扫描覆盖
  • [ ] CVSS + EPSS + KEV 优先级排序配置
  • [ ] SLA 定义并沟通
  • [ ] 升级路径建立
  • [ ] 修复工作流程文档化
  • [ ] 披露策略发布(security.txt)
  • [ ] Bug Bounty 程序考虑
  • [ ] 指标和报告建立
  • [ ] 异常/风险接受流程定义

参考文献

版本历史

  • v1.0.0 (2025-12-26): 初始发布,包括 CVSS、优先级排序、披露

最后更新: 2025-12-26