| name | vulnerability-management |
| description | Vulnerability lifecycle management including CVE tracking, CVSS scoring, risk prioritization, remediation workflows, and coordinated disclosure practices |
| allowed-tools | Read, Grep, Glob, Write, Edit, Task, mcp__perplexity__*, mcp__context7__* |
Vulnerability Management
End-to-end vulnerability lifecycle from discovery through remediation and verification.
When to Use This Skill
Keywords: vulnerability management, CVE, CVSS, remediation, patching, risk prioritization, EPSS, KEV, vulnerability disclosure, bug bounty, patch management, vulnerability scanning, asset inventory
Use this skill when:
- Setting up vulnerability management programs
- Interpreting CVSS scores and metrics
- Prioritizing vulnerability remediation
- Designing patch management processes
- Implementing vulnerability disclosure programs
- Managing bug bounty programs
- Tracking CVE/CWE/NVD data
- Creating SLA policies for remediation
Quick Decision Tree
- Understanding vulnerability scores? → See CVSS Scoring
- Prioritizing what to fix first? → See Risk-Based Prioritization
- Designing remediation workflow? → See references/remediation-workflow.md
- Setting up disclosure program? → See Vulnerability Disclosure
- CVSS calculation details? → See references/cvss-scoring.md
Vulnerability Lifecycle
┌─────────────────────────────────────────────────────────────────┐
│ VULNERABILITY MANAGEMENT LIFECYCLE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ DISCOVER ──▶ ASSESS ──▶ PRIORITIZE ──▶ REMEDIATE ──▶ VERIFY │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌───────┐ ┌───────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │Scanner│ │CVSS │ │Risk │ │Patch/ │ │Rescan/ │ │
│ │Pentest│ │Context│ │Matrix │ │Config │ │Validate│ │
│ │Bug │ │Assets │ │EPSS+KEV│ │Mitigate│ │Close │ │
│ │Bounty │ │Impact │ │SLA │ │Accept │ │ │ │
│ └───────┘ └───────┘ └────────┘ └────────┘ └────────┘ │
│ │
│ CONTINUOUS: Monitor ◀──────────────────────────────────────────┤
│ │
└─────────────────────────────────────────────────────────────────┘
CVSS Scoring Overview
Common Vulnerability Scoring System provides standardized severity ratings.
CVSS v3.1 Score Ranges
| Score | Severity | Typical SLA |
|---|---|---|
| 9.0-10.0 | Critical | 24-72 hours |
| 7.0-8.9 | High | 7-14 days |
| 4.0-6.9 | Medium | 30-60 days |
| 0.1-3.9 | Low | 90-180 days |
| 0.0 | None | Risk acceptance |
CVSS v3.1 Metric Groups
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 Base Score vector
/// </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()
{
// Impact sub-score
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);
// Exploitability sub-score
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; // Round to 1 decimal
}
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
};
}
// Example: 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($"Vector: {log4shell.ToVectorString()}");
Console.WriteLine($"Score: {log4shell.CalculateBaseScore()}"); // 10.0
For detailed CVSS scoring including Temporal and Environmental metrics, see references/cvss-scoring.md.
Risk-Based Prioritization
CVSS alone is insufficient for prioritization. Use multiple signals:
Prioritization Framework
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>Complete context for vulnerability prioritization</summary>
public sealed record VulnerabilityContext(
string CveId,
double CvssBase,
double? CvssEnvironmental = null,
double? CvssTemporal = null,
double EpssProbability = 0.0, // 0-1 probability of exploitation
double EpssPercentile = 0.0, // Relative ranking
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>Multi-factor vulnerability prioritization</summary>
public sealed class RiskPrioritizer
{
// Weights for different factors (tune based on org priorities)
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>Calculate composite priority score (0-100)</summary>
public double CalculatePriorityScore(VulnerabilityContext vuln)
{
// CVSS component (0-10 normalized to 0-100)
var cvssScore = (vuln.CvssEnvironmental ?? vuln.CvssTemporal ?? vuln.CvssBase) * 10;
// EPSS component (probability * 100)
var epssScore = vuln.EpssProbability * 100;
// KEV component (binary with boost)
var kevScore = vuln.InKev ? 100.0 : 0.0;
// Asset criticality component
var assetScore = AssetScores[vuln.AssetCriticality]
* ExposureMultipliers[vuln.AssetExposure]
* DataMultipliers[vuln.DataSensitivity];
// Exploit maturity component
var exploitScore = ExploitScores[vuln.ExploitMaturity];
if (vuln.PublicExploit)
exploitScore = Math.Max(exploitScore, 60);
// Weighted composite
var priority =
Weights["cvss"] * cvssScore +
Weights["epss"] * epssScore +
Weights["kev"] * kevScore +
Weights["asset"] * assetScore +
Weights["exploit"] * exploitScore;
return Math.Round(priority, 1);
}
/// <summary>Categorize priority score</summary>
public static string GetPriorityCategory(double score) => score switch
{
>= 80 => "P1 - Critical",
>= 60 => "P2 - High",
>= 40 => "P3 - Medium",
_ => "P4 - Low"
};
/// <summary>Get remediation SLA in hours</summary>
public static int GetSlaHours(double score) => score switch
{
>= 80 => 24,
>= 60 => 168, // 7 days
>= 40 => 720, // 30 days
_ => 2160 // 90 days
};
/// <summary>Calculate complete priority result</summary>
public PriorityResult Evaluate(VulnerabilityContext vuln)
{
var score = CalculatePriorityScore(vuln);
return new PriorityResult(score, GetPriorityCategory(score), GetSlaHours(score));
}
}
// Example usage
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($"Priority Score: {result.Score}"); // ~95
Console.WriteLine($"Category: {result.Category}"); // P1 - Critical
Console.WriteLine($"SLA: {result.SlaHours} hours"); // 24
EPSS Integration
using System.Net.Http.Json;
using System.Text.Json.Serialization;
public sealed record EpssScore(
string Cve,
double Epss,
double Percentile,
string Date);
/// <summary>Client for EPSS (Exploit Prediction Scoring System) API</summary>
public sealed class EpssClient(HttpClient httpClient)
{
private const string BaseUrl = "https://api.first.org/data/v1/epss";
/// <summary>Get EPSS score for a CVE</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>Get EPSS scores for multiple CVEs</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);
}
// Registration with IHttpClientFactory
// services.AddHttpClient<EpssClient>();
KEV (Known Exploited Vulnerabilities) Integration
using System.Collections.Concurrent;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
/// <summary>CISA Known Exploited Vulnerability entry</summary>
public sealed record KevEntry(
string CveId,
string VendorProject,
string Product,
string VulnerabilityName,
DateOnly DateAdded,
DateOnly DueDate,
string ShortDescription,
string RequiredAction,
string Notes);
/// <summary>Client for CISA KEV catalog</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>Refresh KEV catalog from CISA</summary>
public async Task RefreshCatalogAsync(CancellationToken ct = default)
{
var catalog = await httpClient.GetFromJsonAsync<KevCatalog>(CatalogUrl, ct)
?? throw new InvalidOperationException("Failed to fetch KEV catalog");
_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>Check if CVE is in KEV catalog</summary>
public bool IsInKev(string cveId) => _cache.ContainsKey(cveId);
/// <summary>Get KEV entry for CVE</summary>
public KevEntry? GetEntry(string cveId) =>
_cache.TryGetValue(cveId, out var entry) ? entry : null;
/// <summary>Get all overdue KEV entries</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);
}
// Registration with IHttpClientFactory
// services.AddHttpClient<KevClient>();
Vulnerability Disclosure
Security.txt
# security.txt - RFC 9116 compliant
# Place at /.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
Disclosure Policy
# Vulnerability Disclosure Policy
## Scope
The following assets are in scope:
- *.example.com
- Example Mobile Apps (iOS, Android)
- Example API (api.example.com)
Out of scope:
- Third-party services
- Social engineering attacks
- Physical security testing
- Denial of service attacks
## Rules of Engagement
- Do not access or modify data belonging to others
- Stop testing and report immediately if you access user data
- Do not publicly disclose before we've addressed the issue
- Provide sufficient detail to reproduce the issue
## Safe Harbor
We will not pursue legal action against researchers who:
- Act in good faith
- Avoid privacy violations
- Do not cause service disruption
- Follow responsible disclosure timeline
## Timeline
- Acknowledgment: 3 business days
- Initial assessment: 7 business days
- Status updates: Every 14 days
- Resolution target: 90 days (varies by severity)
## Rewards
| Severity | Bounty Range |
|----------|--------------|
| Critical | $5,000 - $25,000 |
| High | $2,000 - $5,000 |
| Medium | $500 - $2,000 |
| Low | $100 - $500 |
Bug Bounty Integration
using System.Collections.Frozen;
public enum ReportStatus
{
New,
Triaged,
Duplicate,
Informative,
NotApplicable,
Resolved,
BountyAwarded
}
public enum BountySeverity { Critical, High, Medium, Low }
/// <summary>Bug bounty report tracking</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>Manage bug bounty program operations</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>Calculate bounty amount based on severity and factors</summary>
public decimal CalculateBounty(
BountySeverity severity,
double impactFactor = 1.0,
double qualityFactor = 1.0)
{
var (minBounty, maxBounty) = SeverityBountyRange.GetValueOrDefault(severity);
// Base bounty is midpoint
var baseBounty = (minBounty + maxBounty) / 2;
// Apply factors
var adjusted = baseBounty * (decimal)impactFactor * (decimal)qualityFactor;
// Clamp to range
return Math.Clamp(adjusted, minBounty, maxBounty);
}
/// <summary>Check if report is within 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>Generate coordinated disclosure timeline</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 days
}
SLA Configuration
# vulnerability-sla.yaml
sla_policy:
name: "Production Vulnerability SLA"
version: "2.0"
effective_date: "2024-01-01"
# Default SLAs by CVSS score
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 days
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 days
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 days
total_sla: 2496h
escalation_path: []
# Overrides for specific conditions
overrides:
- condition: "in_kev == true"
override_sla: "critical"
reason: "CISA KEV mandates accelerated remediation"
- condition: "epss_percentile >= 0.95"
decrease_sla_percent: 50
reason: "High exploitation probability"
- condition: "asset_exposure == 'external' and asset_criticality == 'critical'"
override_sla: "critical"
reason: "Internet-facing critical assets"
# Risk acceptance policy
risk_acceptance:
allowed_severities: [low, medium]
max_acceptance_period: 180d
required_approvers:
low: [security-team-lead]
medium: [ciso]
documentation_required: true
review_frequency: 30d
Security Checklist
Before finalizing vulnerability management setup:
- Asset inventory complete and current
- Scanning coverage for all assets
- CVSS + EPSS + KEV prioritization configured
- SLAs defined and communicated
- Escalation paths established
- Remediation workflow documented
- Disclosure policy published (security.txt)
- Bug bounty program considered
- Metrics and reporting established
- Exception/risk acceptance process defined
References
- CVSS Scoring Deep Dive - v3.1 and v4.0 detailed calculation
- Remediation Workflow - End-to-end remediation processes
Version History
- v1.0.0 (2025-12-26): Initial release with CVSS, prioritization, disclosure
Last Updated: 2025-12-26