Introduction

Security Metrics and Reporting

Security metrics translate technical security operations into business-relevant information that drives decision-making. Without metrics, security programs cannot demonstrate value, identify weaknesses, or justify resource allocation. Effective security reporting addresses multiple audiences — from technical teams to the board of directors — each with different information needs.

KPIs vs KRIs

Key Performance Indicators (KPIs)

KPIs measure the efficiency and effectiveness of security operations.

class SecurityKPI:

def init(self):

self.metrics = {}

def calculate_mttd(self, detection_times):

"""Mean Time to Detect — average time from compromise to detection."""

if not detection_times:

return None

return sum(detection_times) / len(detection_times)

def calculate_mttr(self, response_times):

"""Mean Time to Respond — average time from detection to containment."""

if not response_times:

return None

return sum(response_times) / len(response_times)

def calculate_coverage_rate(self, monitored_assets, total_assets):

"""Percentage of assets under monitoring."""

if total_assets == 0:

return 0

return (monitored_assets / total_assets) * 100

def calculate_patch_compliance(self, patched_systems, vulnerable_systems):

"""Percentage of systems patched within SLA."""

total = patched_systems + vulnerable_systems

if total == 0:

return 100

return (patched_systems / total) * 100

Key Risk Indicators (KRIs)

KRIs measure the level of security risk exposure.

class SecurityKRI:

def calculate_vulnerability_risk_score(self, vulnerabilities):

"""Weighted risk score based on CVSS and asset criticality."""

total_risk = 0

for vuln in vulnerabilities:

CVSS score * asset criticality multiplier

risk = vuln['cvss'] * (vuln['asset_criticality'] / 5)

Exploit availability multiplier

if vuln.get('exploit_available'):

risk *= 1.5

if vuln.get('in_wild'):

risk *= 2.0

total_risk += risk

return total_risk

def calculate_mean_time_to_patch(self, patch_times):

"""Average time to apply security patches by severity."""

categories = {'critical': [], 'high': [], 'medium': [], 'low': []}

for patch in patch_times:

categories[patch['severity']].append(patch['hours_to_patch'])

return {

severity: sum(times) / len(times) if times else 0

for severity, times in categories.items()

}

Dashboard Design

Effective dashboards present the right information at the right level of detail for the audience.

Executive Dashboard

def generate_executive_dashboard(metrics):

"""Board-level dashboard — strategic, summary, trend-focused."""

return {

'security_posture_score': metrics['posture_score'], # 0-100

'risk_trend': metrics['risk_trend'], # improving/stable/declining

'incidents_this_quarter': {

'total': metrics['incident_count'],

'critical': metrics['critical_incidents'],

'trend': metrics['incident_trend']

},

'top_risks': [

{'risk': 'Unpatched critical vulnerabilities',

'status': 'on_track', 'due_date': '2026-06-01'},

{'risk': 'Cloud misconfigurations',

'status': 'at_risk', 'due_date': '2026-05-15'},

],

'compliance_status': {

'soc2': 'compliant',

'pci_dss': 'compliant',

'hipaa': 'in_progress'

},

'budget_utilization': {

'allocated': 2500000,

'spent': 1850000,

'remaining': 650000

}

}

Operational Dashboard

def generate_operational_dashboard(soc_metrics):

"""SOC-level dashboard — tactical, detailed, real-time."""

return {

'alert_volume': {

'today': 847,

'change': '+12%',

'by_severity': {

'critical': 3,

'high': 27,

'medium': 145,

'low': 672

}

},

'mean_times': {

'mttd': '45 minutes',

'mttr': '3.2 hours',

'triage_time': '8 minutes'

},

'queue_status': {

'unassigned': 23,

'in_progress': 45,

'escalated': 12

},

'false_positive_rate': '28%',

'coverage': {

'endpoints': '98.5%',

'servers': '100%',

'cloud_accounts': '95%'

}

}

Board Reporting Framework

quarterly_board_report:

sections:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- title: "Executive Summary"

content:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- "Security posture improved from 72 to 78 (target: 80)"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- "Zero critical incidents this quarter"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- "Three compliance audits passed"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- title: "Incident Summary"

metrics:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "Total Incidents"

value: 12

trend: "decreasing"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "Mean Time to Detect"

value: "45 min"

target: "< 60 min"

status: "on_track"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "Mean Time to Respond"

value: "3.2 hrs"

target: "< 4 hrs"

status: "on_track"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "Phishing Click Rate"

value: "4.2%"

target: "< 5%"

status: "on_track"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- title: "Risk Profile"

risks:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- id: "R-001"

description: "Third-party vendor access to production"

likelihood: "medium"

impact: "high"

mitigation: "Vendor access review in progress"

target_date: "2026-07-01"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- title: "Compliance Status"

frameworks:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "SOC 2 Type II"

status: "compliant"

last_audit: "2026-03-15"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "PCI DSS 4.0"

status: "compliant"

last_audit: "2026-02-28"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- name: "ISO 27001"

status: "in_progress"

target: "2026-09-01"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- title: "Resource Allocation"

budget:

allocated: "$2.5M"

spent: "$1.85M (74%)"

key_investments:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- "EDR platform upgrade: $450K"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- "Security awareness training: $85K"

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- "Penetration testing: $120K"

Security Scorecards

def generate_team_scorecard(metrics):

"""Department-level scorecard for security team performance."""

thresholds = {

'patch_compliance': {'good': 95, 'acceptable': 85},

'coverage': {'good': 98, 'acceptable': 90},

'false_positive_rate': {'good': 20, 'acceptable': 35},

'mttd_minutes': {'good': 30, 'acceptable': 60},

'mttr_hours': {'good': 2, 'acceptable': 4},

}

scorecard = {}

for metric, value in metrics.items():

if metric not in thresholds:

continue

threshold = thresholds[metric]

if value >= threshold['good']:

scorecard[metric] = 'GREEN'

elif value >= threshold['acceptable']:

scorecard[metric] = 'YELLOW'

else:

scorecard[metric] = 'RED'

return scorecard

Industry Benchmarks

industry_benchmarks:

mttd:

top_performer: "< 1 hour"

average: "24-48 hours"

below_average: "> 1 week"

mttr:

top_performer: "< 2 hours"

average: "4-8 hours"

below_average: "> 24 hours"

vulnerability_remediation:

critical: "15 days (top), 30 days (average)"

high: "30 days (top), 60 days (average)"

security_spend:

as_percentage_of_it: "5-10% (recommended)"

per_employee: "$1,500-2,500 (enterprise)"

Conclusion

Security metrics must be meaningful, measurable, and actionable. Distinguish between KPIs that measure operational effectiveness and KRIs that measure risk exposure. Tailor dashboards for each audience — executives need strategic trends and risk summaries, while SOC teams need real-time operational data. Benchmark against industry peers, track trends over time (not just snapshots), and always tie metrics back to business impact and risk reduction.