vulnerability management

Performing Asset Criticality Scoring for Vulns

Develop and apply a multi-factor asset criticality scoring model to weight vulnerability prioritization based on business impact, data sensitivity, and operational importance.

asset-classificationasset-criticalitybusiness-impactcmdbcrown-jewelsrisk-managementvulnerability-prioritization
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Asset criticality scoring assigns a business impact rating to each IT asset so that vulnerability remediation efforts focus on systems with the greatest organizational risk. Without criticality context, a CVSS 9.0 vulnerability on a test server receives the same urgency as the same vulnerability on a payment processing database. This skill covers building a multi-factor scoring model incorporating data sensitivity, business function dependency, regulatory scope, network exposure, and recoverability to create a 1-5 criticality tier that directly modifies vulnerability remediation SLAs.

When to Use

  • When conducting security assessments that involve performing asset criticality scoring for vulns
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing

Prerequisites

  • Configuration Management Database (CMDB) or asset inventory
  • Business Impact Analysis (BIA) data
  • Data classification policy
  • Network architecture documentation
  • Stakeholder input from business unit owners

Core Concepts

Asset Criticality Scoring Model

Factor Weight Score Range Description
Business Function Impact 25% 1-5 How critical is the supported business process
Data Sensitivity 25% 1-5 Type and sensitivity of data processed/stored
Regulatory Scope 15% 1-5 Regulatory requirements (PCI, HIPAA, SOX)
Network Exposure 15% 1-5 Internet-facing vs internal-only
Recoverability 10% 1-5 RTO/RPO requirements, DR capability
User Population 10% 1-5 Number of users/customers affected

Criticality Tier Definitions

Tier Score Range Label SLA Modifier Examples
1 4.5-5.0 Crown Jewels -50% SLA Domain controllers, payment systems, ERP
2 3.5-4.4 High Value -25% SLA Email servers, HR systems, CI/CD
3 2.5-3.4 Standard Baseline SLA Internal apps, file servers
4 1.5-2.4 Low Impact +25% SLA Test environments, printers
5 1.0-1.4 Minimal +50% SLA Decommissioning, isolated labs

Data Sensitivity Scoring

Score Classification Examples
5 Restricted/Secret PII, PHI, payment card data, trade secrets
4 Confidential Financial reports, HR records, source code
3 Internal Internal documents, policies, project files
2 Semi-public Marketing materials, press releases (draft)
1 Public Published content, public APIs

Workflow

Step 1: Define Scoring Criteria

class AssetCriticalityScorer:
    """Multi-factor asset criticality scoring engine."""
 
    WEIGHTS = {
        "business_function": 0.25,
        "data_sensitivity": 0.25,
        "regulatory_scope": 0.15,
        "network_exposure": 0.15,
        "recoverability": 0.10,
        "user_population": 0.10,
    }
 
    TIER_THRESHOLDS = [
        (4.5, 1, "Crown Jewels", -0.50),
        (3.5, 2, "High Value", -0.25),
        (2.5, 3, "Standard", 0.00),
        (1.5, 4, "Low Impact", 0.25),
        (1.0, 5, "Minimal", 0.50),
    ]
 
    def score_asset(self, asset):
        """Calculate criticality score for an asset."""
        weighted_score = sum(
            asset.get(factor, 3) * weight
            for factor, weight in self.WEIGHTS.items()
        )
        score = round(weighted_score, 2)
 
        for threshold, tier, label, sla_mod in self.TIER_THRESHOLDS:
            if score >= threshold:
                return {
                    "score": score,
                    "tier": tier,
                    "label": label,
                    "sla_modifier": sla_mod,
                }
        return {"score": score, "tier": 5, "label": "Minimal", "sla_modifier": 0.50}
 
    def adjust_vuln_sla(self, base_sla_days, asset_tier_data):
        """Adjust vulnerability SLA based on asset criticality."""
        modifier = asset_tier_data["sla_modifier"]
        adjusted = int(base_sla_days * (1 + modifier))
        return max(1, adjusted)  # Minimum 1 day SLA

Step 2: Integrate with Vulnerability Prioritization

def apply_criticality_to_vulns(vulns_df, asset_scores):
    """Enrich vulnerability data with asset criticality context."""
    for idx, vuln in vulns_df.iterrows():
        asset_id = vuln.get("asset_id", "")
        asset_data = asset_scores.get(asset_id, {"tier": 3, "sla_modifier": 0})
 
        vulns_df.at[idx, "asset_tier"] = asset_data["tier"]
        vulns_df.at[idx, "asset_label"] = asset_data.get("label", "Standard")
 
        base_sla = get_base_sla(vuln["severity"])
        adjusted_sla = int(base_sla * (1 + asset_data["sla_modifier"]))
        vulns_df.at[idx, "adjusted_sla_days"] = max(1, adjusted_sla)
 
    return vulns_df

Best Practices

  1. Involve business stakeholders in criticality scoring; IT alone cannot assess business impact
  2. Review and update criticality scores at least quarterly or when systems change roles
  3. Automate scoring where possible using CMDB tags and data classification labels
  4. Apply criticality tiers to vulnerability SLAs for risk-proportional remediation
  5. Validate scoring against actual incident impact data to calibrate the model
  6. Start with a simple 3-tier model before expanding to 5 tiers

Common Pitfalls

  • Classifying all assets as "critical" which defeats the purpose of tiering
  • Not updating criticality scores when systems are repurposed or decommissioned
  • Using only technical factors without business context
  • Applying uniform SLAs regardless of asset importance
  • Not documenting the scoring methodology for audit and consistency
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md2.2 KB

Asset Criticality Scoring for Vulnerability Prioritization — API Reference

Criticality Scoring Factors

Factor Weight Description
Data Sensitivity 0.25 Classification of data stored/processed
Business Function 0.20 Revenue/operational importance
Regulatory Scope 0.15 Compliance frameworks in scope
Network Exposure 0.20 Internet-facing vs air-gapped
Recoverability 0.10 Recovery time and capability
User Count 0.10 Number of users impacted

Data Sensitivity Levels

Level Score Examples
Public 1 Marketing website, public docs
Internal 2 Internal wiki, employee tools
Confidential 3 Financial reports, source code
PII 4 Customer names, emails, addresses
PCI/PHI 5 Credit card data, health records

Criticality Tiers

Tier Score Range Name Remediation SLA (Critical)
1 >= 4.0 Crown Jewel 24 hours
2 3.0 - 3.9 Business Critical 48 hours
3 2.0 - 2.9 Important 7 days
4 1.5 - 1.9 Standard 14 days
5 < 1.5 Low Impact 30 days

Risk-Adjusted Priority Formula

adjusted_priority = min(CVSS_score * tier_multiplier, 10.0)
Tier multipliers: {1: 1.5, 2: 1.3, 3: 1.0, 4: 0.8, 5: 0.5}

CSV Inventory Format

hostname,data_classification,business_function,regulatory_scope,network_exposure,recoverability,user_count
db-prod-01,pci,revenue-generating,pci-dss,dmz,manual-recovery,50000
web-staging,internal,staging,none,vpn-accessible,auto-recovery,10

Integration Points

System Purpose
CMDB (ServiceNow, Qualys) Asset metadata source
Vulnerability Scanner CVSS scores for risk adjustment
Ticketing (Jira, ServiceNow) SLA-driven remediation tracking
SIEM Alert priority enrichment

External References

standards.md0.5 KB

Standards and References - Asset Criticality Scoring

Industry Standards

  • NIST SP 800-30 Rev 1: Guide for Conducting Risk Assessments
  • NIST CSF 2.0 ID.AM: Asset Management
  • CIS Controls v8.1 Control 1: Inventory and Control of Enterprise Assets
  • ISO 27001:2022 A.5.9: Inventory of information and other associated assets
  • FAIR Framework: Factor Analysis of Information Risk

Scoring References

  • NIST CMDB Best Practices
  • ITIL Asset Management Framework
  • CIS RAM (Risk Assessment Method)
workflows.md0.6 KB

Workflows - Asset Criticality Scoring

Workflow 1: Scoring Process

Identify Asset -> Gather Business Context -> Score Each Factor ->
Calculate Weighted Score -> Assign Tier -> Map to SLA Modifier ->
Store in CMDB -> Apply to Vulnerability Management

Workflow 2: Quarterly Review

Quarter Start:
    1. Export current asset criticality ratings
    2. Identify changes (new systems, decommissioned, role changes)
    3. Rescore changed assets with business owners
    4. Update CMDB with new scores
    5. Recalculate vulnerability SLAs for affected assets

Scripts 2

agent.py6.6 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Asset criticality scoring agent for vulnerability prioritization."""

import json
import argparse
import csv
from datetime import datetime


CRITICALITY_WEIGHTS = {
    "data_sensitivity": 0.25,
    "business_function": 0.20,
    "regulatory_scope": 0.15,
    "network_exposure": 0.20,
    "recoverability": 0.10,
    "user_count": 0.10,
}

DATA_SENSITIVITY_SCORES = {
    "public": 1, "internal": 2, "confidential": 3,
    "restricted": 4, "pci": 5, "phi": 5, "pii": 4,
}

BUSINESS_FUNCTION_SCORES = {
    "test": 1, "development": 2, "staging": 2,
    "internal-tool": 3, "customer-facing": 4,
    "revenue-generating": 5, "critical-infrastructure": 5,
}

REGULATORY_SCOPE_SCORES = {
    "none": 1, "internal-policy": 2, "soc2": 3,
    "gdpr": 4, "pci-dss": 5, "hipaa": 5, "fedramp": 5,
}

NETWORK_EXPOSURE_SCORES = {
    "air-gapped": 1, "internal-only": 2, "vpn-accessible": 3,
    "dmz": 4, "internet-facing": 5,
}

RECOVERABILITY_SCORES = {
    "auto-recovery": 1, "backup-available": 2,
    "manual-recovery": 3, "extended-downtime": 4,
    "no-recovery": 5,
}


def load_asset_inventory(csv_path):
    """Load asset inventory from CSV file."""
    assets = []
    with open(csv_path, "r") as f:
        reader = csv.DictReader(f)
        for row in reader:
            assets.append(row)
    return assets


def calculate_criticality_score(asset):
    """Calculate weighted criticality score for a single asset."""
    scores = {}
    scores["data_sensitivity"] = DATA_SENSITIVITY_SCORES.get(
        asset.get("data_classification", "internal").lower(), 2)
    scores["business_function"] = BUSINESS_FUNCTION_SCORES.get(
        asset.get("business_function", "internal-tool").lower(), 3)
    scores["regulatory_scope"] = REGULATORY_SCOPE_SCORES.get(
        asset.get("regulatory_scope", "none").lower(), 1)
    scores["network_exposure"] = NETWORK_EXPOSURE_SCORES.get(
        asset.get("network_exposure", "internal-only").lower(), 2)
    scores["recoverability"] = RECOVERABILITY_SCORES.get(
        asset.get("recoverability", "backup-available").lower(), 2)

    user_count = int(asset.get("user_count", 0))
    if user_count > 10000:
        scores["user_count"] = 5
    elif user_count > 1000:
        scores["user_count"] = 4
    elif user_count > 100:
        scores["user_count"] = 3
    elif user_count > 10:
        scores["user_count"] = 2
    else:
        scores["user_count"] = 1

    weighted_score = sum(
        scores[factor] * weight
        for factor, weight in CRITICALITY_WEIGHTS.items()
    )

    if weighted_score >= 4.0:
        tier = 1
        tier_name = "Crown Jewel"
    elif weighted_score >= 3.0:
        tier = 2
        tier_name = "Business Critical"
    elif weighted_score >= 2.0:
        tier = 3
        tier_name = "Important"
    elif weighted_score >= 1.5:
        tier = 4
        tier_name = "Standard"
    else:
        tier = 5
        tier_name = "Low Impact"

    return {
        "asset": asset.get("hostname", asset.get("name", "unknown")),
        "factor_scores": scores,
        "weighted_score": round(weighted_score, 2),
        "tier": tier,
        "tier_name": tier_name,
    }


def calculate_risk_adjusted_priority(criticality_tier, cvss_score):
    """Combine CVSS score with asset criticality for risk-adjusted priority."""
    tier_multipliers = {1: 1.5, 2: 1.3, 3: 1.0, 4: 0.8, 5: 0.5}
    multiplier = tier_multipliers.get(criticality_tier, 1.0)
    adjusted = min(cvss_score * multiplier, 10.0)
    return round(adjusted, 1)


def generate_sla_matrix(criticality_tier):
    """Generate remediation SLA based on asset criticality tier."""
    sla_matrix = {
        1: {"critical": "24h", "high": "72h", "medium": "7d", "low": "30d"},
        2: {"critical": "48h", "high": "7d", "medium": "14d", "low": "60d"},
        3: {"critical": "7d", "high": "14d", "medium": "30d", "low": "90d"},
        4: {"critical": "14d", "high": "30d", "medium": "60d", "low": "180d"},
        5: {"critical": "30d", "high": "60d", "medium": "90d", "low": "365d"},
    }
    return sla_matrix.get(criticality_tier, sla_matrix[3])


def run_audit(args):
    """Execute asset criticality scoring audit."""
    print(f"\n{'='*60}")
    print(f"  ASSET CRITICALITY SCORING FOR VULNERABILITY PRIORITIZATION")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    report = {}

    if args.inventory:
        assets = load_asset_inventory(args.inventory)
        scored = [calculate_criticality_score(a) for a in assets]
        scored.sort(key=lambda x: x["weighted_score"], reverse=True)

        report["scored_assets"] = scored
        tier_counts = {}
        for s in scored:
            tier_counts[s["tier_name"]] = tier_counts.get(s["tier_name"], 0) + 1
        report["tier_distribution"] = tier_counts

        print(f"--- ASSET CRITICALITY SCORES ({len(scored)} assets) ---")
        for s in scored[:20]:
            print(f"  Tier {s['tier']} ({s['tier_name']}): {s['asset']} "
                  f"— score {s['weighted_score']}")

        print(f"\n--- TIER DISTRIBUTION ---")
        for tier_name, count in sorted(tier_counts.items()):
            print(f"  {tier_name}: {count} assets")

        print(f"\n--- REMEDIATION SLA MATRIX ---")
        for tier in range(1, 6):
            sla = generate_sla_matrix(tier)
            print(f"  Tier {tier}: Critical={sla['critical']} High={sla['high']} "
                  f"Medium={sla['medium']} Low={sla['low']}")

    if args.cvss_score and args.asset_tier:
        adjusted = calculate_risk_adjusted_priority(args.asset_tier, args.cvss_score)
        sla = generate_sla_matrix(args.asset_tier)
        report["risk_adjustment"] = {
            "original_cvss": args.cvss_score,
            "asset_tier": args.asset_tier,
            "adjusted_priority": adjusted,
            "sla": sla,
        }
        print(f"\n--- RISK-ADJUSTED PRIORITY ---")
        print(f"  CVSS: {args.cvss_score} x Tier {args.asset_tier} = {adjusted}")
        print(f"  SLA: {sla}")

    return report


def main():
    parser = argparse.ArgumentParser(description="Asset Criticality Scoring Agent")
    parser.add_argument("--inventory", help="CSV file with asset inventory")
    parser.add_argument("--cvss-score", type=float, help="CVSS score to adjust")
    parser.add_argument("--asset-tier", type=int, choices=[1, 2, 3, 4, 5],
                        help="Asset criticality tier (1=highest)")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_audit(args)
    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2, default=str)
        print(f"\n[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
process.py3.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Asset Criticality Scoring Engine

Calculates multi-factor criticality scores for assets and
applies SLA modifiers to vulnerability remediation timelines.

Requirements:
    pip install pandas

Usage:
    python process.py score --csv assets.csv --output scored_assets.csv
    python process.py apply --assets scored_assets.csv --vulns vulns.csv --output adjusted.csv
"""

import argparse
import sys

import pandas as pd


WEIGHTS = {
    "business_function": 0.25,
    "data_sensitivity": 0.25,
    "regulatory_scope": 0.15,
    "network_exposure": 0.15,
    "recoverability": 0.10,
    "user_population": 0.10,
}

TIERS = [
    (4.5, 1, "Crown Jewels", -0.50),
    (3.5, 2, "High Value", -0.25),
    (2.5, 3, "Standard", 0.00),
    (1.5, 4, "Low Impact", 0.25),
    (1.0, 5, "Minimal", 0.50),
]

BASE_SLA = {"Critical": 14, "High": 30, "Medium": 60, "Low": 90}


def score_assets(df):
    """Calculate criticality scores for all assets."""
    scores = []
    for _, row in df.iterrows():
        weighted = sum(
            row.get(factor, 3) * weight
            for factor, weight in WEIGHTS.items()
        )
        score = round(weighted, 2)

        tier, label, sla_mod = 5, "Minimal", 0.50
        for threshold, t, l, s in TIERS:
            if score >= threshold:
                tier, label, sla_mod = t, l, s
                break

        scores.append({
            **row.to_dict(),
            "criticality_score": score,
            "tier": tier,
            "tier_label": label,
            "sla_modifier": sla_mod,
        })

    return pd.DataFrame(scores).sort_values("criticality_score", ascending=False)


def apply_to_vulns(assets_df, vulns_df):
    """Apply asset criticality to vulnerability SLAs."""
    asset_map = {}
    for _, row in assets_df.iterrows():
        asset_map[row.get("asset_id", "")] = {
            "tier": row["tier"],
            "label": row["tier_label"],
            "sla_modifier": row["sla_modifier"],
        }

    results = []
    for _, vuln in vulns_df.iterrows():
        asset_id = vuln.get("asset_id", "")
        asset = asset_map.get(asset_id, {"tier": 3, "label": "Standard", "sla_modifier": 0})
        severity = vuln.get("severity", "Medium")
        base_sla = BASE_SLA.get(severity, 60)
        adjusted_sla = max(1, int(base_sla * (1 + asset["sla_modifier"])))

        results.append({
            **vuln.to_dict(),
            "asset_tier": asset["tier"],
            "asset_label": asset["label"],
            "base_sla_days": base_sla,
            "adjusted_sla_days": adjusted_sla,
        })

    return pd.DataFrame(results)


def main():
    parser = argparse.ArgumentParser(description="Asset Criticality Scoring Engine")
    subparsers = parser.add_subparsers(dest="command")

    s_p = subparsers.add_parser("score", help="Score assets")
    s_p.add_argument("--csv", required=True)
    s_p.add_argument("--output", default="scored_assets.csv")

    a_p = subparsers.add_parser("apply", help="Apply to vulnerabilities")
    a_p.add_argument("--assets", required=True)
    a_p.add_argument("--vulns", required=True)
    a_p.add_argument("--output", default="adjusted_vulns.csv")

    args = parser.parse_args()

    if args.command == "score":
        df = pd.read_csv(args.csv)
        scored = score_assets(df)
        scored.to_csv(args.output, index=False)
        print(f"[+] Scored {len(scored)} assets to {args.output}")
        print(scored["tier_label"].value_counts().to_string())

    elif args.command == "apply":
        assets = pd.read_csv(args.assets)
        vulns = pd.read_csv(args.vulns)
        result = apply_to_vulns(assets, vulns)
        result.to_csv(args.output, index=False)
        print(f"[+] Applied criticality to {len(result)} vulnerabilities")

    else:
        parser.print_help()


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 0.5 KB
Keep exploring