Vulnerability Management

Detect CVEs in dependencies, prioritize by real risk, and auto-generate fix PRs.


Architecture

%%{init: {'theme': 'base', 'themeVariables': { 
  'primaryColor': '#6366f1',
  'lineColor': '#94a3b8',
  'fontFamily': 'system-ui, sans-serif'
}}}%%
flowchart TB
    subgraph Detect["🔍 Detection"]
        Parse["Parse Manifests"]
        SBOM["Generate SBOM"]
        Parse --> SBOM
    end
    
    subgraph Lookup["📚 CVE Lookup"]
        direction LR
        OSV["OSV"]
        NVD["NVD"]
        GHSA["GitHub"]
    end
    
    subgraph AI["🤖 AI Analysis"]
        Reach["Reachability"]
        Risk["Risk Score"]
        Reach --> Risk
    end
    
    subgraph Actions["📤 Actions"]
        direction LR
        Fix["Auto-Fix PR"]
        Block["Block Merge"]
        Alert["Alert"]
    end
    
    Detect --> Lookup --> AI --> Actions
    
    style Detect fill:#dbeafe,stroke:#3b82f6
    style Lookup fill:#f3e8ff,stroke:#9333ea
    style AI fill:#fef3c7,stroke:#f59e0b
    style Actions fill:#dcfce7,stroke:#22c55e

Step 1: Dependency Discovery

Supported Ecosystems

Ecosystem Manifest Lock
npm package.json package-lock.json, yarn.lock
Python requirements.txt Pipfile.lock, poetry.lock
Java pom.xml -
Go go.mod go.sum
Ruby Gemfile Gemfile.lock
Rust Cargo.toml Cargo.lock

Find Manifests

{
  "schemaVersion": "1.0",
  "stepId": "find-manifests",
  "type": "FUNCTION",
  "next": "fetch-loop",
  "def": {
    "language": "PYTHON",
    "content": "def execute(ctx):\n    tree = ctx.steps['fetch-tree']['response']['tree']\n    names = ['package.json','requirements.txt','pom.xml','go.mod','Gemfile','Cargo.toml']\n    return {'manifests': [f for f in tree if any(f['path'].endswith(n) for n in names)]}"
  }
}

Step 2: SBOM Generation

Generate Software Bill of Materials in CycloneDX format.

{
  "schemaVersion": "1.0",
  "stepId": "generate-sbom",
  "type": "AIAGENT",
  "next": "query-cves",
  "def": {
    "agentId": "security-analyst",
    "input": "Parse manifests and generate CycloneDX SBOM:\n\n{{step.fetch-loop.iterations | tojson}}\n\nExtract ALL dependencies with:\n- name, version (exact)\n- ecosystem (npm, pypi, maven, go)\n- purl (pkg:ecosystem/name@version)\n- scope (runtime, dev)"
  }
}

SBOM Schema

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "components": [
    {
      "type": "library",
      "name": "lodash",
      "version": "4.17.21",
      "purl": "pkg:npm/lodash@4.17.21",
      "scope": "required"
    }
  ]
}

Step 3: CVE Database Queries

Query OSV (Primary)

{
  "schemaVersion": "1.0",
  "stepId": "query-osv",
  "type": "CONNECTOR",
  "parent": "cve-loop",
  "def": {
    "connectorName": "HTTP",
    "operation": {
      "operationType": "HTTP",
      "operationInput": {
        "type": "HTTP",
        "baseUrl": "https://api.osv.dev",
        "method": "POST",
        "body": {
          "package": {
            "name": "{{loop.current.item.name}}",
            "ecosystem": "{{loop.current.item.ecosystem}}"
          },
          "version": "{{loop.current.item.version}}"
        }
      }
    }
  }
}

Cache Results

{
  "stepId": "cache-cve",
  "type": "DATABASE",
  "def": {
    "connectionId": "{{connections.security-db}}",
    "operation": "EXECUTE",
    "query": "INSERT INTO cve_cache (cve_id, package, severity, cvss, cached_at, expires_at) VALUES (:cve, :pkg, :sev, :cvss, NOW(), NOW() + INTERVAL '24 hours') ON CONFLICT (cve_id) DO UPDATE SET severity = :sev",
    "parameters": {
      "cve": "{{loop.current.item.id}}",
      "pkg": "{{loop.current.item.package}}",
      "sev": "{{loop.current.item.severity}}",
      "cvss": "{{loop.current.item.cvss_score}}"
    }
  }
}

Step 4: AI Risk Prioritization

Not all CVEs are equal. Assess real-world exploitability.

Priority Matrix

CVSS Reachable Exposed Priority
9-10 Critical
9-10 High
7-9 High
7-9 Medium
4-7 - Medium
<4 - - Low

Reachability Analysis

{
  "schemaVersion": "1.0",
  "stepId": "assess-risk",
  "type": "AIAGENT",
  "parent": "vuln-loop",
  "def": {
    "agentId": "security-analyst",
    "input": "Assess this vulnerability:\n\nCVE: {{loop.current.item.id}}\nPackage: {{loop.current.item.package}}@{{loop.current.item.version}}\nCVSS: {{loop.current.item.cvss}}\n\nAssess:\n1. **Reachability** - Is vulnerable code reachable?\n2. **Exploitability** - How easy to exploit?\n3. **Impact** - Blast radius if exploited?\n\nOutput:\n- Risk Score: 0-100\n- Priority: CRITICAL|HIGH|MEDIUM|LOW\n- Recommendation: URGENT_FIX|SCHEDULE_FIX|MONITOR\n- Has Fix: true/false"
  }
}

Step 5: Auto-Fix PRs

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#22c55e'}}}%%
flowchart LR
    V["CVE Found"] --> G["Generate Fix"]
    G --> B["Branch"]
    B --> C["Commit"]
    C --> PR["Create PR"]
    
    style V fill:#fee2e2,stroke:#ef4444
    style PR fill:#dcfce7,stroke:#22c55e

Create Fix Branch

{
  "schemaVersion": "1.0",
  "stepId": "create-branch",
  "type": "CONNECTOR",
  "parent": "fix-loop",
  "def": {
    "connectorName": "GitHub",
    "operation": {
      "operationType": "HTTP",
      "connection": {"type": "BINDING", "bindingName": "github-integration"},
      "operationInput": {
        "type": "HTTP",
        "method": "POST",
        "baseUrl": "https://api.github.com",
        "body": {
          "ref": "refs/heads/security/fix-{{loop.current.item.id | lower}}",
          "sha": "{{variables.ref}}"
        }
      }
    }
  }
}

Create Pull Request

{
  "stepId": "create-pr",
  "type": "CONNECTOR",
  "def": {
    "connectorName": "GitHub",
    "operation": {
      "operationType": "HTTP",
      "operationInput": {
        "body": {
          "title": "🔒 Fix {{loop.current.item.id}} in {{loop.current.item.package}}",
          "body": "## Vulnerability Fix\n\n| Field | Value |\n|-------|-------|\n| **CVE** | {{loop.current.item.id}} |\n| **Package** | {{loop.current.item.package}} |\n| **Fixed Version** | {{loop.current.item.fixed_version}} |\n| **Severity** | {{loop.current.item.severity}} |\n\n---\n*Auto-generated by work.studio*",
          "head": "security/fix-{{loop.current.item.id | lower}}",
          "base": "main"
        }
      }
    }
  }
}

Step 6: License Detection

Identify problematic open-source licenses.

Risk Categories

Category Examples Risk
Permissive MIT, Apache 2.0, BSD 🟢 Low
Weak Copyleft LGPL, MPL 🟡 Medium
Strong Copyleft GPL, AGPL 🔴 High
Unknown No license 🔴 High

License Detection

{
  "stepId": "detect-license",
  "type": "AIAGENT",
  "def": {
    "agentId": "security-analyst",
    "input": "Analyze license for:\n\nPackage: {{loop.current.item.name}}\nLicense: {{loop.current.item.license}}\n\nAssess:\n1. License obligations\n2. Compatibility with {{input.product_license}}\n3. Disclosure requirements\n\nOutput:\n- Risk: LOW|MEDIUM|HIGH\n- Recommendation: APPROVE|REVIEW|REPLACE"
  }
}

Step 7: Alerting

Slack Notification

{
  "stepId": "notify",
  "type": "CONNECTOR",
  "def": {
    "connectorName": "Slack",
    "operation": {
      "operationType": "HTTP",
      "connection": {"type": "BINDING", "bindingName": "slack-security"},
      "operationInput": {
        "body": {
          "channel": "#security-alerts",
          "blocks": [
            {"type": "header", "text": {"type": "plain_text", "text": "🚨 Vulnerabilities Detected"}},
            {"type": "section", "text": {"type": "mrkdwn", "text": "*Repo:* {{variables.repo}}\n*Total:* {{step.aggregate.total}}\n*Critical:* {{step.aggregate.critical}}"}}
          ]
        }
      }
    }
  }
}

Step 8: Reporting

Dashboard Queries

-- By Severity
SELECT severity, COUNT(*) 
FROM vulnerability_findings 
WHERE status = 'OPEN' 
GROUP BY severity;

-- MTTR
SELECT severity, AVG(EXTRACT(EPOCH FROM (resolved_at - detected_at))/3600) as hours
FROM vulnerability_findings 
WHERE status = 'RESOLVED' 
GROUP BY severity;

-- Top Vulnerable Packages
SELECT package_name, COUNT(DISTINCT cve_id) as cves
FROM vulnerability_findings WHERE status = 'OPEN'
GROUP BY package_name ORDER BY cves DESC LIMIT 10;

Weekly Report

{
  "schemaVersion": "1.0",
  "stepId": "weekly-report",
  "type": "AIAGENT",
  "def": {
    "agentId": "security-analyst",
    "input": "Generate weekly vulnerability summary:\n\n{{step.query-stats.results | tojson}}\n\nInclude:\n1. Executive Summary\n2. New This Week\n3. Resolved\n4. Top Priorities\n5. Recommendations"
  }
}

Quick Reference

Remediation SLAs

Severity SLA
Critical 24 hours
High 7 days
Medium 30 days
Low 90 days

Suppression Format

{
  "cve_id": "CVE-2024-1234",
  "package": "example@1.0.0",
  "reason": "DEV_DEPENDENCY",
  "justification": "Only in test suite",
  "approved_by": "security-team",
  "expires_at": "2026-07-21"
}

Filters

Filter Usage
tojson {{data \| tojson}}
b64decode {{content \| b64decode}}
lower {{id \| lower}}
length {{items \| length}}

Next Steps