Skip to main content

Vulnerability Management

Vulnerability management identifies security weaknesses in systems and applications, prioritises them by exploitability and impact, and drives remediation within defined timeframes. This task covers the complete cycle from asset discovery through scanning, prioritisation, remediation tracking, and exception handling. Execute these procedures on a continuous basis: authenticated scans weekly, unauthenticated scans daily, and prioritisation review within 24 hours of new findings.

Prerequisites

RequirementDetail
Scanner accessAdministrative credentials for vulnerability scanner (OpenVAS, Nessus, or Qualys)
Scan credentialsService accounts with read access to target systems for authenticated scanning
Asset inventoryCurrent list of IP ranges, hostnames, and system owners from CMDB or asset register
Network accessScanner host must reach all target networks; firewall rules permitting scanner source IPs
PermissionsVulnerability analyst role with write access to ticketing system for remediation tracking
Time allocation4 hours weekly for scan review and prioritisation; additional time for remediation coordination

Verify scanner connectivity before beginning. For OpenVAS, confirm the Greenbone Vulnerability Manager service is running:

Terminal window
sudo systemctl status gvmd
# Expected: active (running)
sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
--xml "<get_version/>"
# Expected: <get_version_response status="200">

For Nessus, verify the service and API availability:

Terminal window
sudo systemctl status nessusd
# Expected: active (running)
curl -sk https://localhost:8834/server/status
# Expected: {"status":"ready"}

Ensure scan credentials have been tested against representative targets. Authentication failures during scans produce incomplete results that miss critical vulnerabilities requiring local access to detect.

Procedure

Asset discovery and scope definition

  1. Export the current asset inventory from your configuration management database or asset register. The scope must include all systems the organisation operates, including cloud instances, containers, and field office infrastructure.

    For organisations using a spreadsheet-based inventory, structure the export with these columns:

    IP/Hostname,Environment,Owner,OS,Criticality,Last Scan Date
    10.0.1.50,Production,j.smith@example.org,Ubuntu 22.04,High,2024-11-01
    192.168.5.20,Development,k.jones@example.org,Windows Server 2022,Medium,2024-11-08
  2. Identify assets not present in the inventory through network discovery. Run an Nmap sweep against all known network ranges:

    Terminal window
    nmap -sn -PE -PP -PM -PS21,22,23,25,80,443,3389 \
    10.0.0.0/16 192.168.0.0/16 172.16.0.0/12 \
    -oX discovery_results.xml

    Compare discovered hosts against the asset inventory. Any discrepancy indicates either an inventory gap or an unauthorised device requiring investigation.

  3. Categorise assets into scan groups based on network location, criticality, and scan window constraints. Critical production systems require authenticated scans during maintenance windows. Development and test systems tolerate more aggressive scanning during business hours.

    Create scan groups in your scanner. For OpenVAS:

    Terminal window
    sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
    --xml '<create_target>
    <name>Production Servers</name>
    <hosts>10.0.1.0/24,10.0.2.0/24</hosts>
    <port_list id="33d0cd82-57c6-11e1-8ed1-406186ea4fc5"/>
    <ssh_credential id="[credential-uuid]"/>
    </create_target>'
  4. Define scan schedules that balance detection coverage against operational impact. Configure authenticated scans for weekly execution during low-usage periods. Unauthenticated external scans run daily without operational restrictions.

    +------------------------------------------------------------------+
    | SCAN SCHEDULE MATRIX |
    +------------------------------------------------------------------+
    | |
    | DAILY (02:00-04:00 UTC) |
    | +---------------------------+ |
    | | External unauthenticated | |
    | | - Perimeter hosts | |
    | | - Web applications | |
    | | - API endpoints | |
    | +---------------------------+ |
    | |
    | WEEKLY (Saturday 22:00-06:00 UTC) |
    | +---------------------------+ |
    | | Internal authenticated | |
    | | - Production servers | |
    | | - Database servers | |
    | | - Domain controllers | |
    | +---------------------------+ |
    | |
    | WEEKLY (Wednesday 12:00-18:00 UTC) |
    | +---------------------------+ |
    | | Development/Test | |
    | | - Dev environments | |
    | | - Staging systems | |
    | | - CI/CD infrastructure | |
    | +---------------------------+ |
    | |
    | MONTHLY (First Sunday 22:00-06:00 UTC) |
    | +---------------------------+ |
    | | Full credential scan | |
    | | - All assets | |
    | | - Deep plugin set | |
    | +---------------------------+ |
    | |
    +------------------------------------------------------------------+

    Figure 1: Scan schedule distribution across asset categories

Vulnerability scanning execution

  1. Initiate the scheduled scan or trigger an ad-hoc scan for newly deployed systems. For OpenVAS, create and start a task:

    Terminal window
    # Create scan task
    TASK_UUID=$(sudo -u gvm gvm-cli socket --gmp-username admin \
    --gmp-password $GVM_PASS \
    --xml '<create_task>
    <name>Weekly Production Scan</name>
    <config id="daba56c8-73ec-11df-a475-002264764cea"/>
    <target id="[target-uuid]"/>
    <scanner id="08b69003-5fc2-4037-a479-93b440211c73"/>
    </create_task>' | grep -oP 'id="\K[^"]+')
    # Start the task
    sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
    --xml "<start_task task_id=\"$TASK_UUID\"/>"
  2. Monitor scan progress to detect stalled or failed scans early. Check task status every 30 minutes during execution:

    Terminal window
    sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
    --xml "<get_tasks task_id=\"$TASK_UUID\"/>" | \
    grep -oP 'progress="\K[^"]+'
    # Expected: value between 0 and 100, increasing over time

    A scan showing 0% progress after 30 minutes indicates a connectivity or credential problem. A scan showing the same percentage for over 60 minutes suggests a hung scanner process.

  3. Export scan results upon completion. Generate reports in both machine-readable and human-readable formats:

    Terminal window
    # Get the report ID from the completed task
    REPORT_UUID=$(sudo -u gvm gvm-cli socket --gmp-username admin \
    --gmp-password $GVM_PASS \
    --xml "<get_tasks task_id=\"$TASK_UUID\"/>" | \
    grep -oP 'report id="\K[^"]+' | head -1)
    # Export as CSV for processing
    sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
    --xml "<get_reports report_id=\"$REPORT_UUID\" format_id=\"c1645568-627a-11e3-a660-406186ea4fc5\"/>" \
    > scan_results.csv
    # Export as PDF for stakeholder reporting
    sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
    --xml "<get_reports report_id=\"$REPORT_UUID\" format_id=\"c402cc3e-b531-11e1-9163-406186ea4fc5\"/>" \
    | base64 -d > scan_report.pdf

Vulnerability prioritisation

  1. Import scan results into your vulnerability tracking system or spreadsheet. Each vulnerability requires assessment against multiple factors before assigning remediation priority.

    The CVSS base score provides a standardised severity rating from 0.0 to 10.0, but this score alone produces poor prioritisation. A CVSS 9.8 vulnerability in an isolated development server presents less organisational risk than a CVSS 7.5 vulnerability in an internet-facing payment system.

  2. Apply contextual factors to each vulnerability. Calculate an adjusted priority score using this formula:

    Priority Score = CVSS Base Score × Asset Criticality × Exposure Factor × Exploit Availability
    Where:
    - Asset Criticality: 1.5 (Critical), 1.2 (High), 1.0 (Medium), 0.7 (Low)
    - Exposure Factor: 1.5 (Internet-facing), 1.2 (Partner-accessible), 1.0 (Internal only)
    - Exploit Availability: 1.5 (Active exploitation), 1.3 (Public exploit), 1.0 (No known exploit)

    Worked example for a SQL injection vulnerability:

    CVE-2024-1234: SQL Injection in web application
    CVSS Base Score: 8.6
    Asset: Donor management portal (Critical, Internet-facing)
    Exploit: Public Metasploit module available
    Priority Score = 8.6 × 1.5 × 1.5 × 1.3 = 25.1
    Compare to:
    CVE-2024-5678: Local privilege escalation
    CVSS Base Score: 7.8
    Asset: Development workstation (Low, Internal only)
    Exploit: No known public exploit
    Priority Score = 7.8 × 0.7 × 1.0 × 1.0 = 5.5

    The SQL injection receives priority despite comparable CVSS scores because contextual factors multiply the base risk.

  3. Consult the CISA Known Exploited Vulnerabilities (KEV) catalogue for any vulnerabilities under active exploitation. KEV-listed vulnerabilities receive automatic Critical priority regardless of calculated score:

    Terminal window
    # Download current KEV catalogue
    curl -s https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json \
    -o kev.json
    # Check if a specific CVE is listed
    jq -r '.vulnerabilities[] | select(.cveID=="CVE-2024-1234")' kev.json

    Any match indicates the vulnerability is under active exploitation and requires remediation within the KEV-specified timeframe, which is 14 days for most entries.

  4. Check the Exploit Prediction Scoring System (EPSS) for vulnerabilities not yet in KEV. EPSS provides a probability score (0.0 to 1.0) indicating likelihood of exploitation within 30 days:

    Terminal window
    # Query FIRST EPSS API
    curl -s "https://api.first.org/data/v1/epss?cve=CVE-2024-1234" | \
    jq '.data[0].epss'
    # Returns: 0.89 (89% probability of exploitation)

    Vulnerabilities with EPSS scores above 0.7 warrant treatment equivalent to known-exploited vulnerabilities. Scores between 0.4 and 0.7 justify accelerated remediation timelines.

  5. Assign remediation SLAs based on final priority classification:

    PriorityCriteriaRemediation SLAVerification deadline
    CriticalPriority score > 20, or KEV-listed, or EPSS > 0.772 hours96 hours
    HighPriority score 12-20, or CVSS ≥ 9.07 days10 days
    MediumPriority score 6-12, or CVSS 7.0-8.930 days45 days
    LowPriority score < 6, or CVSS < 7.090 days120 days

Remediation workflow

  1. Create remediation tickets for each vulnerability requiring action. Group vulnerabilities affecting the same system or requiring the same fix into a single ticket to reduce operational overhead.

    Ticket content must include:

    Title: [Priority] CVE-2024-1234 - SQL Injection in donor-portal
    Affected Asset: donor-portal.example.org (10.0.5.20)
    CVE: CVE-2024-1234
    CVSS: 8.6
    Priority: Critical
    Description: SQL injection vulnerability in login form allows
    unauthenticated attackers to extract database contents.
    Remediation: Upgrade donor-portal application to version 3.2.1
    Vendor Advisory: https://vendor.example/security/2024-001
    SLA: 72 hours (due: 2024-11-18 14:00 UTC)
    Owner: j.smith@example.org
    Verification: Re-scan after patching confirms vulnerability absent
  2. Assign tickets to system owners identified in the asset inventory. For organisations without clear ownership, escalate to IT management for assignment within 24 hours of vulnerability discovery.

    +------------------------------------------------------------------+
    | REMEDIATION WORKFLOW |
    +------------------------------------------------------------------+
    | |
    | +-------------------+ |
    | | Vulnerability | |
    | | Identified | |
    | +---------+---------+ |
    | | |
    | v |
    | +---------+---------+ +-----------------------+ |
    | | Owner | | No owner identified | |
    | | Assigned? +---->| Escalate to IT Mgmt | |
    | +---------+---------+ | (24hr assignment SLA) | |
    | | +-----------+-----------+ |
    | | Yes | |
    | v | |
    | +---------+---------+<----------------+ |
    | | Ticket Created | |
    | | SLA Clock Starts | |
    | +---------+---------+ |
    | | |
    | v |
    | +---------+---------+ |
    | | Owner Implements | |
    | | Fix | |
    | +---------+---------+ |
    | | |
    | v |
    | +---------+---------+ |
    | | Owner Requests | |
    | | Verification | |
    | +---------+---------+ |
    | | |
    | v |
    | +---------+---------+ +-----------------------+ |
    | | Verification | No | Return to Owner | |
    | | Scan Confirms +------->| Reset SLA Clock | |
    | | Fix? | +-----------------------+ |
    | +---------+---------+ |
    | | |
    | | Yes |
    | v |
    | +---------+---------+ |
    | | Ticket Closed | |
    | | Metrics Captured | |
    | +-------------------+ |
    | |
    +------------------------------------------------------------------+

    Figure 2: Remediation workflow from identification through closure

  3. Monitor remediation progress against SLA. Run daily reports showing tickets approaching or exceeding their deadlines:

    Terminal window
    # Example query for Jira-based tracking
    curl -s -u "$JIRA_USER:$JIRA_TOKEN" \
    "https://jira.example.org/rest/api/2/search?jql=project=VULN+AND+status!=Closed+AND+duedate<=1d" | \
    jq '.issues[] | {key: .key, summary: .fields.summary, due: .fields.duedate}'

    Tickets within 24 hours of SLA breach require escalation to the owner’s manager. Tickets exceeding SLA require documentation and escalation to IT leadership.

  4. Execute verification scans within the verification deadline to confirm remediation success. Target only the specific hosts remediated rather than running a full infrastructure scan:

    Terminal window
    # Targeted verification scan with OpenVAS
    sudo -u gvm gvm-cli socket --gmp-username admin --gmp-password $GVM_PASS \
    --xml '<create_target>
    <name>Verification - CVE-2024-1234</name>
    <hosts>10.0.5.20</hosts>
    <port_list id="33d0cd82-57c6-11e1-8ed1-406186ea4fc5"/>
    <ssh_credential id="[credential-uuid]"/>
    </create_target>'

    The vulnerability must be absent from verification scan results to close the ticket. Partial remediation or compensating controls require exception handling rather than closure.

Exception handling

  1. Initiate an exception request when remediation is impossible within the SLA. Valid exception reasons include vendor patch unavailability, business-critical system constraints, and third-party managed systems outside organisational control. Convenience, resource constraints, and competing priorities do not justify exceptions for Critical or High vulnerabilities.

  2. Document the exception request with required fields:

    VULNERABILITY EXCEPTION REQUEST
    Vulnerability: CVE-2024-1234
    Affected Asset: legacy-finance.example.org
    Original SLA: 72 hours (Critical)
    Reason for Exception:
    Application vendor discontinued support in 2023. No patch available.
    Replacement project scheduled for Q2 2025.
    Compensating Controls:
    1. Network segmentation - system isolated to finance VLAN (10.0.8.0/24)
    2. WAF rule deployed blocking SQL injection patterns
    3. Enhanced monitoring - all database queries logged to SIEM
    4. Reduced attack surface - removed public-facing components
    Residual Risk Assessment:
    Attack requires authenticated access from finance VLAN.
    WAF blocks 94% of SQL injection attempts in testing.
    Estimated residual risk: Medium (reduced from Critical)
    Requested Exception Period: 180 days (until replacement deployment)
    Review Date: 2025-02-15
    Requestor: j.smith@example.org
    Date: 2024-11-15
  3. Route exception requests through the approval chain based on original vulnerability priority:

    Original PriorityApproverMaximum Exception Period
    CriticalCISO or IT Director30 days, renewable
    HighSecurity Manager90 days, renewable
    MediumSecurity Analyst Lead180 days
    LowSystem Owner365 days
  4. Implement compensating controls before exception approval. The approver must verify compensating controls are operational, not merely planned. Document control effectiveness with evidence:

    Terminal window
    # Verify network segmentation
    nmap -Pn -p 443 10.0.5.20 -S 10.0.1.100
    # Expected: filtered (not reachable from general network)
    nmap -Pn -p 443 10.0.5.20 -S 10.0.8.50
    # Expected: open (reachable from finance VLAN)
    # Verify WAF rule deployment
    curl -s "https://legacy-finance.example.org/login" \
    -d "user=admin' OR '1'='1" | grep -i blocked
    # Expected: WAF block page returned
  5. Track exceptions in a register separate from the main vulnerability tracking. Review all active exceptions at the cadence appropriate to their priority: Critical exceptions weekly, High exceptions fortnightly, Medium and Low monthly.

    +------------------------------------------------------------------+
    | EXCEPTION APPROVAL FLOW |
    +------------------------------------------------------------------+
    | |
    | +-------------------+ |
    | | Exception | |
    | | Requested | |
    | +---------+---------+ |
    | | |
    | v |
    | +---------+---------+ +-----------------------+ |
    | | Compensating | No | Request Returned | |
    | | Controls +------->| Implement controls | |
    | | Implemented? | | before resubmitting | |
    | +---------+---------+ +-----------------------+ |
    | | |
    | | Yes |
    | v |
    | +---------+---------+ |
    | | Security Review | |
    | | Control Efficacy | |
    | +---------+---------+ |
    | | |
    | v |
    | +---------+---------+ +-----------------------+ |
    | | Controls | No | Additional controls | |
    | | Adequate? +------->| required | |
    | +---------+---------+ +-----------------------+ |
    | | |
    | | Yes |
    | v |
    | +---------+---------+ |
    | | Approver Review | |
    | | (per priority) | |
    | +---------+---------+ |
    | | |
    | +----+----+ |
    | | | |
    | v v |
    | +----+----+ +--+-------------+ |
    | |Approved | | Denied | |
    | |Exception| | Remediation | |
    | |Registered| Required | |
    | +---------+ +----------------+ |
    | |
    +------------------------------------------------------------------+

    Figure 3: Exception approval flow with control verification

Reporting and metrics

  1. Generate weekly vulnerability status reports summarising the current state and remediation progress. Include these metrics:

    WEEKLY VULNERABILITY REPORT - Week ending 2024-11-15
    CURRENT STATE
    +-----------+-------+--------+---------+
    | Priority | Open | In SLA | Overdue |
    +-----------+-------+--------+---------+
    | Critical | 3 | 2 | 1 |
    | High | 12 | 10 | 2 |
    | Medium | 47 | 45 | 2 |
    | Low | 134 | 132 | 2 |
    +-----------+-------+--------+---------+
    | Total | 196 | 189 | 7 |
    +-----------+-------+--------+---------+
    ACTIVITY THIS WEEK
    - New vulnerabilities identified: 23
    - Vulnerabilities remediated: 31
    - Exceptions approved: 2
    - Exceptions expired: 1
    MEAN TIME TO REMEDIATE (last 30 days)
    - Critical: 2.3 days (SLA: 3 days)
    - High: 5.8 days (SLA: 7 days)
    - Medium: 22.4 days (SLA: 30 days)
    - Low: 67.2 days (SLA: 90 days)
    OVERDUE ITEMS REQUIRING ESCALATION
    1. CVE-2024-1234 on legacy-finance (Critical, 5 days overdue)
    2. CVE-2024-2345 on dev-server-03 (High, 3 days overdue)
  2. Calculate trend metrics monthly to identify systemic issues:

    Vulnerability Density = Total Open Vulnerabilities / Total Assets
    Example: 196 vulnerabilities / 450 assets = 0.44 vulnerabilities per asset
    Target: < 0.5 for mature programmes, < 1.0 for developing programmes
    SLA Compliance Rate = (Tickets Closed in SLA / Total Tickets Closed) × 100
    Example: 31 in SLA / 35 total = 88.6%
    Target: > 95% for Critical/High, > 90% for Medium/Low
    Recurrence Rate = (Vulnerabilities Reopened / Vulnerabilities Closed) × 100
    Example: 4 reopened / 35 closed = 11.4%
    Target: < 5% indicates effective remediation
  3. Present quarterly executive summaries showing risk reduction over time. Express findings in business terms rather than technical metrics:

    QUARTERLY EXECUTIVE SUMMARY - Q3 2024
    Risk Posture: IMPROVING
    Key Achievements:
    - Reduced critical vulnerabilities from 12 to 3 (75% reduction)
    - Achieved 94% SLA compliance for critical issues
    - Eliminated all internet-facing critical vulnerabilities
    Areas Requiring Attention:
    - Legacy finance system carries accepted risk (exception in place)
    - Remediation capacity constrained - 2 weeks backlog on Medium items
    Resource Request:
    - Additional 0.5 FTE for remediation would reduce backlog by 60%

Verification

Confirm the vulnerability management process is functioning correctly through these checks:

Scan coverage verification:

Terminal window
# Compare scanned assets against inventory
INVENTORY_COUNT=$(wc -l < asset_inventory.csv)
SCANNED_COUNT=$(sudo -u gvm gvm-cli socket --gmp-username admin \
--gmp-password $GVM_PASS \
--xml "<get_hosts/>" | grep -c '<host')
echo "Inventory: $INVENTORY_COUNT, Scanned: $SCANNED_COUNT"
# Coverage should exceed 95%
COVERAGE=$(echo "scale=2; $SCANNED_COUNT / $INVENTORY_COUNT * 100" | bc)
echo "Coverage: $COVERAGE%"

Prioritisation consistency:

Review 10 randomly selected vulnerabilities and recalculate their priority scores manually. All scores should match the assigned priority within one category.

Remediation SLA adherence:

Terminal window
# Calculate SLA compliance from ticketing system
CLOSED_IN_SLA=$(curl -s -u "$JIRA_USER:$JIRA_TOKEN" \
"https://jira.example.org/rest/api/2/search?jql=project=VULN+AND+status=Closed+AND+resolved>=startOfMonth()" | \
jq '[.issues[] | select(.fields.resolutiondate <= .fields.duedate)] | length')
TOTAL_CLOSED=$(curl -s -u "$JIRA_USER:$JIRA_TOKEN" \
"https://jira.example.org/rest/api/2/search?jql=project=VULN+AND+status=Closed+AND+resolved>=startOfMonth()" | \
jq '.total')
echo "SLA Compliance: $(echo "scale=1; $CLOSED_IN_SLA / $TOTAL_CLOSED * 100" | bc)%"

Exception register accuracy:

Cross-reference active exceptions against current scan results. Every excepted vulnerability must still appear in scans; if absent, the exception should be closed.

Troubleshooting

SymptomCauseResolution
Scan shows 0 hosts discoveredFirewall blocking scanner, incorrect IP ranges, network routing issueVerify scanner can ping targets; check firewall rules allow scanner source IP; confirm IP ranges match current network architecture
Authenticated scan shows far fewer vulnerabilities than expectedCredential failure, insufficient permissions, credential lockoutCheck scanner logs for authentication errors; verify service account has local admin or root equivalent; confirm account not locked
Scan never completesTarget host unresponsive, scan hanging on specific check, scanner resource exhaustionReduce concurrent scan threads; exclude problematic hosts and scan separately; increase scanner memory allocation
Same vulnerability reappears after remediationIncomplete patching, configuration management overwriting fix, different instance of same vulnerabilityVerify patch applied to correct host; check for configuration automation reverting changes; confirm vulnerability is identical CVE and host
CVSS scores not matching vendor advisoriesScanner using outdated NVD data, vendor-modified score, scanner interpolation errorUpdate scanner vulnerability feeds; compare scanner CVE data against NVD directly; use vendor CVSS where available
Scans impacting production performanceScan timing during peak hours, aggressive scan settings, network saturationReschedule to maintenance windows; reduce scan intensity settings; implement rate limiting on scanner
False positives overwhelming real findingsBanner-based detection without verification, outdated scanner signatures, misidentified softwareEnable active verification where available; update scanner feeds; tune scanner to reduce banner-only detections
Unable to scan cloud instancesSecurity groups blocking scanner, ephemeral instances changing IPs, container environmentsDeploy cloud-native scanner or agent; use API-based scanning for cloud providers; implement container scanning in CI/CD
Verification scan still shows vulnerability presentPatch requires reboot not yet performed, cached scan data, vulnerability in different componentConfirm service restart after patching; wait for cache expiry or force rescan; verify exact file versions match patched state
Exception request rejected despite compensating controlsControls insufficiently documented, control effectiveness not demonstrated, residual risk still too highProvide evidence of control testing; demonstrate detection capability; propose additional controls to further reduce risk
Metrics show declining performance despite remediation effortScan scope expansion, new systems added faster than remediation, detection capability improvementSegment metrics by asset age; track new vs legacy vulnerability rates separately; normalise metrics by asset count
Scanner credential warning after password rotationScan credentials updated in source system but not scanner, credential synchronisation delayUpdate credentials in scanner configuration immediately after rotation; implement credential management integration

Automation

Automate routine elements of vulnerability management to reduce manual effort and improve consistency.

Scheduled scan execution:

/etc/cron.d/vulnerability-scans
# Daily external scan at 02:00
0 2 * * * gvm /usr/local/bin/run-external-scan.sh
# Weekly internal scan Saturday 22:00
0 22 * * 6 gvm /usr/local/bin/run-internal-scan.sh

Automatic ticket creation from scan results:

create-vuln-tickets.py
#!/usr/bin/env python3
import json
import requests
from datetime import datetime, timedelta
def calculate_sla(priority):
sla_days = {'Critical': 3, 'High': 7, 'Medium': 30, 'Low': 90}
return datetime.now() + timedelta(days=sla_days.get(priority, 90))
def create_ticket(vuln):
priority = classify_priority(vuln)
due_date = calculate_sla(priority)
ticket = {
'fields': {
'project': {'key': 'VULN'},
'issuetype': {'name': 'Vulnerability'},
'summary': f"[{priority}] {vuln['cve']} - {vuln['name'][:50]}",
'description': format_description(vuln),
'duedate': due_date.strftime('%Y-%m-%d'),
'assignee': {'name': get_asset_owner(vuln['host'])}
}
}
response = requests.post(
'https://jira.example.org/rest/api/2/issue',
json=ticket,
auth=(JIRA_USER, JIRA_TOKEN)
)
return response.json()

KEV and EPSS enrichment:

enrich-vulnerabilities.sh
#!/bin/bash
# Download current KEV catalogue
curl -s https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json \
-o /var/lib/vulnmgmt/kev.json
# Enrich each vulnerability with KEV and EPSS data
while read -r cve; do
# Check KEV
kev_match=$(jq -r ".vulnerabilities[] | select(.cveID==\"$cve\")" /var/lib/vulnmgmt/kev.json)
# Get EPSS
epss_score=$(curl -s "https://api.first.org/data/v1/epss?cve=$cve" | jq -r '.data[0].epss // 0')
# Update vulnerability record
echo "$cve,$kev_match,$epss_score" >> /var/lib/vulnmgmt/enriched.csv
done < /var/lib/vulnmgmt/pending_cves.txt

Resource-constrained implementation

Organisations with limited IT capacity can implement vulnerability management using free tools. Deploy OpenVAS on a dedicated virtual machine with 4 CPU cores and 8GB RAM. Start with monthly authenticated scans of critical systems only, expanding scope as capacity allows. Use spreadsheet-based tracking initially, migrating to ticketing systems as volume increases. Prioritise ruthlessly: focus exclusively on Critical and High vulnerabilities until those are under control before addressing Medium and Low findings.

See also