Vulnerability lifecycle management including CVE tracking, CVSS scoring, risk prioritization, remediation workflows, and coordinated disclosure practices
Manages vulnerability lifecycle from discovery through remediation, including CVE tracking, CVSS scoring, and risk-based prioritization using EPSS/KEV data. Use when interpreting CVSS scores, prioritizing remediation, designing patch management workflows, or setting up vulnerability disclosure programs.
/plugin marketplace add melodic-software/claude-code-plugins/plugin install security@melodic-softwareThis skill is limited to using the following tools:
references/cvss-scoring.mdreferences/remediation-workflow.mdEnd-to-end vulnerability lifecycle from discovery through remediation and verification.
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:
┌─────────────────────────────────────────────────────────────────┐
│ 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 ◀──────────────────────────────────────────┤
│ │
└─────────────────────────────────────────────────────────────────┘
Common Vulnerability Scoring System provides standardized severity ratings.
| 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 |
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.
CVSS alone is insufficient for prioritization. Use multiple signals:
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
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>();
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>();
# 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
# 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 |
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
}
# 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
Before finalizing vulnerability management setup:
Last Updated: 2025-12-26
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.