Appearance
Scoring Methodology
This page describes how NetVuln Tool classifies finding severity, computes the Bullium Risk Score, applies the dual (actual vs operational) scoring model, and determines risk trends.
The relevant scripts are scripts/classify_severity.sh (severity rules), scripts/cve_lookup.sh (CVSS lookup), and scripts/risk_score.sh (scoring, grading, operational model, and trend).
Severity Classification
Each finding is assigned a severity level using a three-tier approach, applied in order of priority.
1. CVE/CVSS Lookup (Primary)
When a CVE identifier is detected in scan output, NetVuln Tool queries external sources for the CVSS base score:
- Primary source: cvedetails.com (HTML scraping)
- Fallback source: NVD API v2 (services.nvd.nist.gov)
- CVSS versions: v3.1 preferred, then v3.0, then v2
| CVSS Score | Severity |
|---|---|
| 9.0 - 10.0 | Critical |
| 7.0 - 8.9 | High |
| 4.0 - 6.9 | Medium |
| 0.1 - 3.9 | Low |
| 0.0 / N/A | Info |
Results are cached per-session to avoid redundant lookups. Rate limiting (a 2-second minimum between requests) is applied to respect API limits.
2. Pattern-Based Classification (Fallback)
Findings without CVE identifiers are classified by matching title and description text against known vulnerability patterns.
Critical patterns: Remote Code Execution (RCE), command/shell injection, default or blank credentials, unrestricted admin interfaces, SQL injection, and known critical CVEs (MS17-010, EternalBlue, Heartbleed, ShellShock, Log4Shell, ProxyLogon).
High patterns: Weak SSL/TLS (SSLv2, SSLv3, RC4, POODLE, BEAST, DROWN), SMB null sessions, anonymous access, cleartext protocols on sensitive services (Telnet, FTP), exposed databases without authentication, privilege escalation, path traversal.
Medium patterns: Missing security headers (HSTS, CSP, X-Frame-Options), outdated or end-of-life software, weak SSH configuration, self-signed or expired certificates, SNMP default community strings, DNS zone transfers allowed.
Low patterns: Information disclosure (server version banners), minor configuration issues (cookie flags, directory listing, X-Powered-By header), ICMP responses and timestamps.
Info: Unmatched findings default to informational.
3. Port-Based Classification (Default)
For findings that do not match any pattern, severity is assigned based on the exposed service type:
| Service | Ports | Default Severity |
|---|---|---|
| Telnet, RSH, Rlogin, Rexec | 23, 514, 513, 512 | High |
| FTP, SNMP | 21, 161 | Medium |
| Database services | MySQL (3306), PostgreSQL (5432), MongoDB (27017), SQL Server (1433), Oracle (1521) | Medium |
| Remote Desktop, VNC | 3389, 5900 | Medium |
| Other services | any other port | Info |
Bullium Risk Score (0-100)
The risk score provides a single numeric indicator of overall exposure, computed from weighted finding counts plus bonuses for high-risk exposed services.
Formula
Score = (Critical × 25) + (High × 15) + (Medium × 5) + (Low × 1) + Port BonusesThe score is capped at 100 (minimum 0).
Severity Weights
| Severity | Points per Finding |
|---|---|
| Critical | 25 |
| High | 15 |
| Medium | 5 |
| Low | 1 |
| Info | 0 |
Port Bonuses
Additional points are added for open high-risk services detected on any host:
| Category | Points | Ports |
|---|---|---|
| Cleartext services | +10 each | Telnet (23), FTP (21) |
| Management ports | +8 each | RDP (3389), VNC (5900, 5901), MySQL (3306), PostgreSQL (5432), SQL Server (1433), MongoDB (27017), Redis (6379) |
Example Calculation
A scan with 1 critical, 2 high, and 3 medium findings, plus open Telnet and RDP:
Severity: (1 × 25) + (2 × 15) + (3 × 5) = 25 + 30 + 15 = 70
Bonuses: Telnet (+10) + RDP (+8) = 18
Total: 70 + 18 = 88Grade Scale
The risk score maps to a letter grade:
| Grade | Score Range | Rating |
|---|---|---|
| A | 0 - 20 | Excellent, minimal risk exposure |
| B | 21 - 40 | Good, low risk with minor issues |
| C | 41 - 60 | Fair, moderate risk, action recommended |
| D | 61 - 80 | Poor, significant risk, remediation needed |
| F | 81 - 100 | Critical, severe exposure, immediate action required |
Dual Scoring Model (Actual vs Operational)
Added in v3.1.0, the dual scoring model reports two scores side by side so that risk that has been formally accepted does not hide from the raw number.
- Actual score (
risk_score/risk_grade): the raw exposure computed above, counting every finding. - Operational score (
risk_score_operational/risk_grade_operational): the same calculation with the severity weight of accepted, non-expired exceptions subtracted. It answers "what is the residual risk after leadership has signed off on known items?"
calculate_operational_score() in risk_score.sh collects the finding_ids from every .remediation[] entry whose exception_status is accepted and whose exception_expired is false, sums the severity weights of those findings, subtracts that total from the actual score (floored at 0), and re-grades the result. Port bonuses are deliberately not discounted: an exposed management port exists regardless of any paperwork.
When a session has no active exceptions, the operational score equals the actual score and the exception impact is zero.
Exception Impact Fields
Written to .summary alongside the two scores:
| Field | Type | Description |
|---|---|---|
risk_score_operational | number | Post-exception score (0-100) |
risk_grade_operational | string | Post-exception grade (A-F) |
exception_impact.excepted_count | number | Count of active (accepted, non-expired) exceptions |
exception_impact.score_delta | number | Actual score minus operational score |
exception_impact.excepted_findings | object | By-severity breakdown of excepted findings |
Exceptions are created and managed with remediation_update.sh --accept / --revoke. See Session Data for the full remediation and exception field schema, and the API Contract for how the portal extracts the exception summary at upload time.
Risk Trend
When multiple scans of the same target scope exist in the session directory, the current score is compared to the most recent prior scan:
- Improving: the current score is lower than the previous score (risk decreased)
- Worsening: the current score is higher than the previous score (risk increased)
- Stable: no change since the last scan
Trend comparison uses target-scope matching so that only scans of the same IP range or domain are compared. Historical scores are stored chronologically for long-term tracking. When operational scores are present, a parallel operational trend (risk_trend.operational_scores, operational_direction, operational_change) is tracked as well.
Source Files
| File | Purpose |
|---|---|
scripts/risk_score.sh | Risk score calculation, grading, operational (dual) model, trend analysis |
scripts/classify_severity.sh | Pattern-based severity classification rules |
scripts/cve_lookup.sh | CVE/CVSS lookup from cvedetails.com and the NVD API |
scripts/remediation_update.sh | Manual remediation status and exception (accept/revoke) management |
scripts/report_template.sh | Report HTML, including the scoring reference section |
