Metrics, Reporting & Remediation
Risk Scoring & Prioritization
3 min read
Not all vulnerabilities require immediate attention. A systematic risk scoring approach helps organizations prioritize remediation efforts based on actual business impact.
Adapting CVSS for LLM Vulnerabilities
The Common Vulnerability Scoring System (CVSS) requires adaptation for AI-specific risks:
| CVSS Component | Traditional Web App | LLM Application |
|---|---|---|
| Attack Vector | Network/Local | Prompt interface |
| Attack Complexity | Technical skill | Prompt crafting |
| Privileges Required | Authentication | Session access |
| User Interaction | Click required | Conversation flow |
| Scope | System boundary | Model behavior |
| Confidentiality | Data access | Training data/prompts |
| Integrity | Data modification | Output manipulation |
| Availability | Service denial | Response degradation |
LLM-Specific Risk Framework
Create a scoring system tailored to AI vulnerabilities:
from dataclasses import dataclass
from enum import Enum
from typing import List
class ExploitabilityLevel(Enum):
"""How easy is it to exploit this vulnerability?"""
TRIVIAL = 4 # Single prompt, no skill required
EASY = 3 # Few attempts, basic prompt engineering
MODERATE = 2 # Multi-turn, requires understanding
DIFFICULT = 1 # Advanced techniques, tool-assisted
class ImpactLevel(Enum):
"""What is the potential business impact?"""
CRITICAL = 4 # Data breach, regulatory violation
HIGH = 3 # Reputation damage, significant cost
MODERATE = 2 # Limited data exposure, recoverable
LOW = 1 # Minor inconvenience, no data loss
class DetectionDifficulty(Enum):
"""How hard is it to detect exploitation?"""
UNDETECTABLE = 4 # No logs, appears normal
DIFFICULT = 3 # Requires advanced monitoring
MODERATE = 2 # Standard logging catches it
EASY = 1 # Obvious, immediate alerts
@dataclass
class LLMRiskScore:
"""
Calculate risk score for LLM vulnerabilities.
Score range: 1-100 (Critical: 80+, High: 60-79, Medium: 40-59, Low: <40)
"""
vulnerability_name: str
owasp_category: str
exploitability: ExploitabilityLevel
impact: ImpactLevel
detection_difficulty: DetectionDifficulty
affected_users_percentage: float # 0.0 to 1.0
data_sensitivity: str # PII, financial, health, general
def calculate_base_score(self) -> float:
"""Calculate base technical score."""
exp_weight = 0.3
imp_weight = 0.4
det_weight = 0.3
base = (
(self.exploitability.value * exp_weight) +
(self.impact.value * imp_weight) +
(self.detection_difficulty.value * det_weight)
)
# Normalize to 0-100
return (base / 4) * 100
def calculate_environmental_score(self) -> float:
"""Adjust for environmental factors."""
base = self.calculate_base_score()
# Adjust for user exposure
user_multiplier = 0.5 + (self.affected_users_percentage * 0.5)
# Adjust for data sensitivity
sensitivity_multipliers = {
"health": 1.3,
"financial": 1.25,
"PII": 1.2,
"general": 1.0
}
sens_mult = sensitivity_multipliers.get(self.data_sensitivity, 1.0)
return min(100, base * user_multiplier * sens_mult)
def get_severity(self) -> str:
"""Get severity rating from score."""
score = self.calculate_environmental_score()
if score >= 80:
return "Critical"
elif score >= 60:
return "High"
elif score >= 40:
return "Medium"
else:
return "Low"
def get_remediation_timeline(self) -> str:
"""Suggested remediation timeline based on severity."""
severity = self.get_severity()
timelines = {
"Critical": "Immediate (24-48 hours)",
"High": "Urgent (1-2 weeks)",
"Medium": "Planned (30-60 days)",
"Low": "Backlog (90+ days)"
}
return timelines[severity]
# Example: Score a multi-turn injection vulnerability
vuln = LLMRiskScore(
vulnerability_name="Multi-turn prompt injection",
owasp_category="LLM01",
exploitability=ExploitabilityLevel.EASY,
impact=ImpactLevel.HIGH,
detection_difficulty=DetectionDifficulty.DIFFICULT,
affected_users_percentage=1.0, # All users
data_sensitivity="PII"
)
print(f"Vulnerability: {vuln.vulnerability_name}")
print(f"Base Score: {vuln.calculate_base_score():.1f}")
print(f"Environmental Score: {vuln.calculate_environmental_score():.1f}")
print(f"Severity: {vuln.get_severity()}")
print(f"Remediation Timeline: {vuln.get_remediation_timeline()}")
Prioritization Matrix
Combine risk score with remediation effort:
from dataclasses import dataclass
from typing import List
import json
from pathlib import Path
@dataclass
class RemediationEffort:
"""Estimate effort required to fix vulnerability."""
development_hours: float
testing_hours: float
deployment_complexity: str # low, medium, high
requires_model_retrain: bool
def total_effort_score(self) -> float:
"""Calculate total effort score (lower = easier)."""
base = self.development_hours + self.testing_hours
complexity_mult = {
"low": 1.0,
"medium": 1.5,
"high": 2.0
}
base *= complexity_mult.get(self.deployment_complexity, 1.0)
if self.requires_model_retrain:
base *= 3.0 # Retraining is expensive
return base
@dataclass
class PrioritizedVulnerability:
"""Combine risk and effort for prioritization."""
risk_score: LLMRiskScore
effort: RemediationEffort
def priority_score(self) -> float:
"""
Higher score = higher priority.
Formula: Risk / Effort (maximize risk reduction per effort)
"""
risk = self.risk_score.calculate_environmental_score()
effort = self.effort.total_effort_score()
# Avoid division by zero
return risk / max(effort, 1)
def get_priority_tier(self) -> str:
"""Assign to priority tier."""
score = self.priority_score()
if score > 5:
return "Tier 1 - Immediate"
elif score > 2:
return "Tier 2 - Next Sprint"
elif score > 1:
return "Tier 3 - Backlog"
else:
return "Tier 4 - Accept Risk"
def prioritize_vulnerabilities(
vulns: List[PrioritizedVulnerability]
) -> List[PrioritizedVulnerability]:
"""Sort vulnerabilities by priority score."""
return sorted(vulns, key=lambda v: v.priority_score(), reverse=True)
# Example prioritization
vulnerabilities = [
PrioritizedVulnerability(
risk_score=LLMRiskScore(
vulnerability_name="System prompt extraction",
owasp_category="LLM01",
exploitability=ExploitabilityLevel.TRIVIAL,
impact=ImpactLevel.MODERATE,
detection_difficulty=DetectionDifficulty.MODERATE,
affected_users_percentage=1.0,
data_sensitivity="general"
),
effort=RemediationEffort(
development_hours=4,
testing_hours=2,
deployment_complexity="low",
requires_model_retrain=False
)
),
PrioritizedVulnerability(
risk_score=LLMRiskScore(
vulnerability_name="Training data extraction",
owasp_category="LLM06",
exploitability=ExploitabilityLevel.DIFFICULT,
impact=ImpactLevel.CRITICAL,
detection_difficulty=DetectionDifficulty.UNDETECTABLE,
affected_users_percentage=0.1,
data_sensitivity="PII"
),
effort=RemediationEffort(
development_hours=80,
testing_hours=40,
deployment_complexity="high",
requires_model_retrain=True
)
)
]
prioritized = prioritize_vulnerabilities(vulnerabilities)
for v in prioritized:
print(f"{v.risk_score.vulnerability_name}:")
print(f" Priority: {v.get_priority_tier()}")
print(f" Score: {v.priority_score():.2f}")
Communicating Priority Decisions
Present prioritization to stakeholders:
| Priority Tier | Action | Resource Allocation |
|---|---|---|
| Tier 1 - Immediate | Stop current work | Dedicated team |
| Tier 2 - Next Sprint | Plan in sprint | Normal allocation |
| Tier 3 - Backlog | Schedule when capacity | As available |
| Tier 4 - Accept Risk | Document and monitor | Minimal |
Key Insight: The highest-risk vulnerability isn't always the first to fix. Balance risk reduction against effort to maximize security ROI. :::