---
name: rt-cvss-calculator
description: "Calculate CVSS 4.0 score with full metric justification. Covers Base metrics (AV/AC/AT/PR/UI/VC/VI/VA/SC/SI/SA), Threat metric (E), and Environmental metrics. Produces complete CVSS:4.0/AV:N/... vector string. Explains each metric selection with real examples. References FIRST.org CVSS 4.0 specification."
---

# rt-cvss-calculator — CVSS 4.0 Scoring Skill

## Overview

This skill guides a red team operator through a complete CVSS 4.0 scoring session for a confirmed finding. It produces a fully justified vector string, a numeric score, a qualitative severity rating, and a prose justification block ready to paste into a finding document.

CVSS 4.0 is the current standard (published June 2023, replacing CVSS 3.1). It introduces sub-scores (Base, Threat, Environmental, Supplemental), removes the Scope metric, and adds Attacked Technology (AT) and new impact granularity. All scores in RTExit use CVSS 4.0.

**Reference**: https://www.first.org/cvss/v4.0/specification-document

### Role in Engagement Lifecycle

```
Exploit confirmed → Evidence collected → CVSS scored → Finding documented → Report generated
                                              ↑
                                   rt-cvss-calculator
```

Invoke this skill after a vulnerability is confirmed and before calling `rt-agent-scribe` to write the full finding. The output of this skill feeds directly into `finding_tracker.py add` and the finding document template.

---

## Pre-Flight Checks

Before scoring, confirm all of the following:

- [ ] Vulnerability is confirmed (not theoretical) — you have reproduction steps and evidence
- [ ] Target asset is in scope (SEAD exists)
- [ ] You know the attack vector (network, adjacent, local, physical)
- [ ] You know what data or system component is directly affected
- [ ] You can distinguish "Vulnerable System" impact from "Subsequent System" impact

If any item is unconfirmed, note it explicitly and score conservatively (lower severity) until evidence supports higher scoring.

---

## CVSS 4.0 Metric Reference

### Group 1 — Exploitability Metrics (Base)

| Metric | Code | Values | Default |
|--------|------|--------|---------|
| Attack Vector | AV | N (Network), A (Adjacent), L (Local), P (Physical) | N |
| Attack Complexity | AC | L (Low), H (High) | L |
| Attack Requirements | AT | N (None), P (Present) | N |
| Privileges Required | PR | N (None), L (Low), H (High) | N |
| User Interaction | UI | N (None), P (Passive), A (Active) | N |

### Group 2 — Vulnerable System Impact (Base)

| Metric | Code | Values |
|--------|------|--------|
| Confidentiality | VC | H (High), L (Low), N (None) |
| Integrity | VI | H (High), L (Low), N (None) |
| Availability | VA | H (High), L (Low), N (None) |

### Group 3 — Subsequent System Impact (Base)

| Metric | Code | Values |
|--------|------|--------|
| Confidentiality | SC | H (High), L (Low), N (None) |
| Integrity | SI | H (High), L (Low), N (None) |
| Availability | SA | H (High), L (Low), N (None) |

### Group 4 — Threat Metric (replaces Temporal)

| Metric | Code | Values |
|--------|------|--------|
| Exploit Maturity | E | A (Attacked), P (PoC), U (Unreported), X (Not Defined) |

### Group 5 — Environmental Metrics (optional, client-specific)

Override Base metrics based on the specific deployment context.

| Metric | Code | Notes |
|--------|------|-------|
| Modified Attack Vector | MAV | Override AV |
| Modified Attack Complexity | MAC | Override AC |
| Modified Attack Requirements | MAT | Override AT |
| Modified Privileges Required | MPR | Override PR |
| Modified User Interaction | MUI | Override UI |
| Modified VC/VI/VA | MVC/MVI/MVA | Override vulnerable system impact |
| Modified SC/SI/SA | MSC/MSI/MSA | Override subsequent system impact |
| Confidentiality Requirement | CR | H/M/L — asset sensitivity |
| Integrity Requirement | IR | H/M/L |
| Availability Requirement | AR | H/M/L |

### Severity Thresholds (CVSS 4.0)

| Score Range | Rating |
|-------------|--------|
| 9.0 – 10.0 | CRITICAL |
| 7.0 – 8.9 | HIGH |
| 4.0 – 6.9 | MEDIUM |
| 0.1 – 3.9 | LOW |
| 0.0 | NONE / INFORMATIONAL |

---

## Step-by-Step Workflow

### Step 1 — Name the Finding

State the finding clearly before scoring. Use a concrete, action-oriented title.

Good: `Unauthenticated SQL Injection in /api/v2/users/search endpoint`
Bad: `SQL Injection`

### Step 2 — Walk Through Each Metric

Answer each question in order. For each metric, state:
1. Which value you selected
2. One sentence of justification tied to the specific finding

**Work through the metrics in this order:**

#### AV — Attack Vector

> Can an attacker exploit this vulnerability remotely over a network, or do they need proximity or physical access?

- **N (Network)** — Exploitable from the internet or any routed network without physical or adjacent-network presence
- **A (Adjacent)** — Requires attacker to be on the same local network (same VLAN, Wi-Fi segment, Bluetooth range)
- **L (Local)** — Requires attacker to have a local OS session (interactive login or scripted execution)
- **P (Physical)** — Requires attacker to physically touch the device

Example: An unauthenticated API endpoint reachable from the internet → `AV:N`

#### AC — Attack Complexity

> Are there conditions outside the attacker's control that must align for exploitation to succeed?

- **L (Low)** — Exploitation is reliable; no special conditions required
- **H (High)** — Success depends on race conditions, specific software versions, timing, or other factors not fully in the attacker's control

Example: SQL injection that fires on every request → `AC:L`. Race condition that requires two requests to land within 50ms → `AC:H`

#### AT — Attack Requirements

> Does the attack require specific pre-existing target configuration that is not the default?

- **N (None)** — Works against a default or standard deployment; no special configuration needed
- **P (Present)** — Only works because of a non-default config, shared resource, or specific environmental prerequisite already present

Example: RCE only works when a non-default debug mode is enabled in the app config → `AT:P`

#### PR — Privileges Required

> What level of authorization must the attacker already have before launching the attack?

- **N (None)** — No authentication required (unauthenticated, pre-auth)
- **L (Low)** — Requires basic authenticated access (standard user account, guest, read-only role)
- **H (High)** — Requires elevated privileges (admin, manager role, API key with write access)

Example: Endpoint is behind login but any registered user can trigger it → `PR:L`

#### UI — User Interaction

> Does exploitation require a human to take an action (beyond the attacker themselves)?

- **N (None)** — Attacker can exploit without any victim interaction
- **P (Passive)** — Victim must passively trigger the vulnerability (visit a page, receive an email, open a file)
- **A (Active)** — Victim must take a deliberate action (approve a request, click a link and enter credentials)

Example: Stored XSS fires when any admin loads the dashboard → `UI:P`

#### VC / VI / VA — Vulnerable System Impact

Assess the direct impact on the component containing the vulnerability.

- **VC** — Does the attacker gain unauthorized read access to data within this system?
- **VI** — Can the attacker modify data or behavior within this system without authorization?
- **VA** — Can the attacker deny service to legitimate users of this system?

Rate each: H (complete loss), L (partial loss), N (no loss).

Example: SQL injection that dumps the full users table → `VC:H`. It cannot insert or delete data → `VI:N`. The DB remains available → `VA:N`.

#### SC / SI / SA — Subsequent System Impact

Does exploiting this vulnerability enable impact beyond the directly vulnerable component? Consider: connected databases, internal APIs, downstream services, other tenants, identity providers.

- **SC** — Can the attacker read data from systems beyond the vulnerable component?
- **SI** — Can the attacker write or corrupt data in downstream systems?
- **SA** — Can the attacker deny service to downstream systems?

Example: SSRF that reaches an internal metadata service exposing AWS credentials → `SC:H` (attacker can read cloud secrets), `SI:H` (attacker can provision/destroy cloud resources), `SA:L` (partial availability risk to cloud services).

#### E — Exploit Maturity (Threat)

> Is there evidence this vulnerability class is being actively exploited in the wild, or is a working PoC publicly available?

- **A (Attacked)** — Evidence of active exploitation in the wild (known threat groups, CISA KEV list, observed in honeypots)
- **P (PoC)** — Working public proof-of-concept exists (GitHub, Exploit-DB, security blog with code)
- **U (Unreported)** — No public PoC, no known exploitation; vulnerability discovered internally
- **X (Not Defined)** — Do not adjust; use the Base score as-is

Example: CVE-2021-44228 (Log4Shell) → `E:A`. A novel logic flaw found during this engagement with no prior disclosure → `E:U`

### Step 3 — Compute the Vector String

Assemble metrics in canonical order:

```
CVSS:4.0/AV:[value]/AC:[value]/AT:[value]/PR:[value]/UI:[value]/VC:[value]/VI:[value]/VA:[value]/SC:[value]/SI:[value]/SA:[value]
```

Append Threat metric if not X:
```
/E:[value]
```

Append Environmental metrics only if they differ from the Base values.

### Step 4 — Calculate the Score

Use the FIRST.org calculator: https://www.first.org/cvss/calculator/4.0

Alternatively, use the cvss-bt Python library:
```bash
pip install cvss
python3 -c "from cvss import CVSS4; c = CVSS4('CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:L'); print(c.scores())"
```

Note: CVSS 4.0 scoring uses a lookup table (not the linear formula from CVSS 3.x). Manual calculation is error-prone — always verify with the official calculator.

### Step 5 — Write the Justification Block

Produce a structured prose block for the finding document. See the template below.

### Step 6 — Register the Finding

```bash
python3 {project-root}/_rtexit/scripts/finding_tracker.py add \
  "Unauthenticated SQL Injection in /api/v2/users/search" \
  CRITICAL \
  9.3 \
  "api.acmecorp.com/api/v2/users/search" \
  --cwe CWE-89 \
  --mitre "T1190" \
  --phase "Exploitation" \
  --notes "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:L/E:P"
```

### Step 7 — Log to Timeline

```bash
python3 {project-root}/_rtexit/scripts/autodoc_engine.py log \
  --skill rt-cvss-calculator \
  --phase Exploitation \
  --finding F-003 \
  --note "CVSS 4.0 scored: 9.3 CRITICAL. Vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:L/E:P"
```

---

## Templates

### CVSS Justification Block (paste into finding document)

```markdown
### CVSS 4.0 Score

**Score**: 9.3 CRITICAL
**Vector**: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:L/E:P

| Metric | Value | Justification |
|--------|-------|---------------|
| Attack Vector (AV) | Network (N) | The vulnerable endpoint `/api/v2/users/search` is publicly reachable from the internet without VPN or network-layer restriction. Exploitation was confirmed from an external Kali machine with no special routing. |
| Attack Complexity (AC) | Low (L) | The injection payload fires on every request. No timing dependencies, race conditions, or environmental factors need to align. Exploitation is fully deterministic and reproducible across test runs. |
| Attack Requirements (AT) | None (N) | The endpoint is enabled by default in all deployment configurations. No non-default setting or pre-existing condition is required. |
| Privileges Required (PR) | None (N) | The endpoint accepts unauthenticated requests. No login, API key, or session token is required to reach the vulnerable parameter. |
| User Interaction (UI) | None (N) | Exploitation is fully server-side. No victim user action is needed; the attacker sends the payload directly to the server. |
| Vuln. System Confidentiality (VC) | High (H) | A UNION-based payload dumped the full `users` table (47,000 records) including bcrypt password hashes, email addresses, phone numbers, and account creation dates. Complete confidentiality loss of the vulnerable database component. |
| Vuln. System Integrity (VI) | None (N) | Testing confirmed the injected session does not have INSERT/UPDATE/DELETE privileges. No data modification was possible within the directly vulnerable component. |
| Vuln. System Availability (VA) | None (N) | The database remained responsive throughout testing. No denial-of-service condition was triggered. |
| Subsequent Confidentiality (SC) | High (H) | The database user account (`app_user`) has SELECT privileges across all schemas. A second payload enumerated the `payments` schema and retrieved 12,000 partial card numbers and billing addresses from a separate table not accessible via the application UI. |
| Subsequent Integrity (SI) | High (H) | The `app_user` account holds WRITE access to the `audit_logs` table. An attacker can inject false audit entries or erase existing ones, undermining forensic integrity across all subsequent systems relying on the audit trail. |
| Subsequent Availability (SA) | Low (L) | No cross-system denial-of-service was achievable, but large UNION queries caused transient slowdowns (2–4 seconds response degradation) on the reporting dashboard that shares the same DB instance. |
| Exploit Maturity (E) | PoC (P) | SQLMap with a standard tamper script (`--tamper=between`) produced a working PoC within 8 minutes. The technique (error-based UNION injection via URL parameter) is extensively documented and requires no novel research. |

**Rationale Summary**: The combination of unauthenticated network access, trivially exploitable injection, and cross-schema data access produces a near-maximum score. The only factors preventing a 10.0 are the absence of direct data modification capability and the partial (rather than complete) subsequent availability impact.
```

### Scoring Worksheet (use while interviewing the finding)

```
Finding Title: _____________________________________________
Asset / URL:   _____________________________________________
Confirmed by:  _____________________________________________  Date: ______

EXPLOITABILITY
  AV (N/A/L/P):  ___   Reason: __________________________________
  AC (L/H):      ___   Reason: __________________________________
  AT (N/P):      ___   Reason: __________________________________
  PR (N/L/H):    ___   Reason: __________________________________
  UI (N/P/A):    ___   Reason: __________________________________

VULNERABLE SYSTEM IMPACT
  VC (H/L/N):    ___   Reason: __________________________________
  VI (H/L/N):    ___   Reason: __________________________________
  VA (H/L/N):    ___   Reason: __________________________________

SUBSEQUENT SYSTEM IMPACT
  SC (H/L/N):    ___   Reason: __________________________________
  SI (H/L/N):    ___   Reason: __________________________________
  SA (H/L/N):    ___   Reason: __________________________________

THREAT
  E (A/P/U/X):   ___   Reason: __________________________________

VECTOR STRING: CVSS:4.0/AV:_/AC:_/AT:_/PR:_/UI:_/VC:_/VI:_/VA:_/SC:_/SI:_/SA:_/E:_
SCORE (from calculator): ___._
SEVERITY: __________
```

---

## Integration with RTExit Scripts

### finding_tracker.py

The tracker stores the CVSS score as a numeric value and the full vector string in the `notes` field.

**Add a finding after scoring:**
```bash
python3 _rtexit/scripts/finding_tracker.py add \
  "Stored XSS in Admin User Bio Field" \
  HIGH \
  8.2 \
  "portal.acmecorp.com/admin/users/edit" \
  --cwe CWE-79 \
  --mitre "T1185" \
  --phase "Exploitation" \
  --operator "m.hegazy" \
  --notes "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:L/VI:H/VA:N/SC:H/SI:H/SA:N/E:P"
```

**View finding after creation:**
```bash
python3 _rtexit/scripts/finding_tracker.py show F-005
```

**List all CRITICAL and HIGH findings:**
```bash
python3 _rtexit/scripts/finding_tracker.py list --severity CRITICAL
python3 _rtexit/scripts/finding_tracker.py list --severity HIGH
```

**Export findings with scores to Markdown:**
```bash
python3 _rtexit/scripts/finding_tracker.py export --format md
```

The exported Markdown includes the CVSS vector from the `notes` field. The report template in `rt-agent-scribe` renders this into the CVSS table automatically.

### autodoc_engine.py

Log the scoring session to the engagement timeline so the audit trail shows when and why a score was assigned.

**Log the scoring activity:**
```bash
python3 _rtexit/scripts/autodoc_engine.py log \
  --skill rt-cvss-calculator \
  --phase "Exploitation" \
  --finding "F-005" \
  --note "CVSS 4.0 scored 8.2 HIGH. Vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:L/VI:H/VA:N/SC:H/SI:H/SA:N/E:P. Score justified by admin-context stored XSS with cross-tenant session hijack potential."
```

**Log evidence collection for chain of custody:**
```bash
python3 _rtexit/scripts/autodoc_engine.py custody \
  --finding F-005 \
  --evidence "_rtexit-output/docs/evidence/screenshots/F-005-xss-payload-firing.png"
```

---

## Full Example Output

### Scenario

During a red team engagement against AcmeCorp, the operator discovers a server-side request forgery (SSRF) vulnerability in the document preview feature. The application fetches URLs provided by the user and renders their content. The attacker uses this to reach the EC2 instance metadata service at `http://169.254.169.254/latest/meta-data/iam/security-credentials/`.

### Completed Scoring Session

**Finding Title**: SSRF via Document Preview Enabling AWS Credential Theft via IMDSv1

**Scoring rationale (metric by metric):**

| Metric | Selection | Justification |
|--------|-----------|---------------|
| AV | N | Document preview is accessible to any authenticated user over HTTPS from the internet |
| AC | L | The SSRF fires on every request; no race condition or version-specific behavior required |
| AT | N | IMDSv1 is the default on this EC2 instance — no non-default configuration needed |
| PR | L | A valid user account is required. Any registered AcmeCorp user can trigger the feature |
| UI | N | The attacker sends the crafted URL directly; no victim action required |
| VC | L | The direct component (document preview service) leaks its own IAM role name — limited disclosure |
| VI | N | The preview service cannot be modified via this attack vector |
| VA | N | The preview service remains functional throughout |
| SC | H | The IMDSv1 response returns `AccessKeyId`, `SecretAccessKey`, and `Token` for the `AcmeCorp-Prod-AppRole` IAM role. This role has `s3:GetObject` on all production buckets and `rds:DescribeDBInstances`. Full confidentiality loss on all data reachable by the IAM role. |
| SI | H | The role also holds `s3:PutObject` and `s3:DeleteObject`. An attacker can overwrite or delete production S3 objects, including customer-uploaded documents and application assets. |
| SA | L | Overloading the metadata service with rapid requests caused a 3-second response delay observed in testing. No complete outage was achievable. |
| E | A | SSRF-to-IMDS credential theft is in active exploitation by multiple threat groups (see CISA advisory AA23-144A). IMDSv1 abuse is listed in MITRE ATT&CK T1552.005. |

**Final Vector String:**
```
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:H/SI:H/SA:L/E:A
```

**Score**: 9.1 CRITICAL

**Recommended severity label**: CRITICAL

**finding_tracker.py command:**
```bash
python3 _rtexit/scripts/finding_tracker.py add \
  "SSRF via Document Preview Enabling AWS Credential Theft via IMDSv1" \
  CRITICAL \
  9.1 \
  "app.acmecorp.com/api/v1/preview" \
  --cwe CWE-918 \
  --mitre "T1552.005" \
  --phase "Exploitation" \
  --operator "m.hegazy" \
  --notes "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:H/SI:H/SA:L/E:A"
```

**Output:**
```
[+] Finding added: F-007
    Title:    SSRF via Document Preview Enabling AWS Credential Theft via IMDSv1
    Severity: CRITICAL
    CVSS:     9.1
    Asset:    app.acmecorp.com/api/v1/preview
    Status:   CONFIRMED
    File:     _rtexit-output/docs/findings/F-007.md
```

---

## Quality Checklist

Before finalizing a CVSS score, verify:

### Accuracy
- [ ] Each metric value is supported by observed evidence, not assumption
- [ ] The Attack Vector reflects actual exploitation path tested (not hypothetical)
- [ ] Subsequent System Impact reflects systems actually reachable, not theoretically connected
- [ ] Exploit Maturity matches the current state of public knowledge (check Exploit-DB, NVD, CISA KEV)

### Completeness
- [ ] All 11 Base metrics are explicitly assigned (no defaults left unexamined)
- [ ] Threat metric (E) is set — do not leave as X unless you have no information
- [ ] Environmental metrics are applied if the client has declared asset sensitivity requirements

### Justification Quality
- [ ] Every metric has at least one sentence of concrete justification referencing the specific finding
- [ ] Justifications reference observable facts (tool output, request/response, screenshot filename)
- [ ] Score rationale summary explains the key drivers of the overall numeric score
- [ ] The CVSS vector string is syntactically correct (validate at first.org calculator)

### Documentation
- [ ] Finding is registered in `finding_tracker.py`
- [ ] CVSS vector string is stored in the `notes` field of the finding record
- [ ] Scoring session is logged to the engagement timeline via `autodoc_engine.py`
- [ ] Evidence screenshots that support metric selections are logged to chain of custody

---

## Common Mistakes to Avoid

### Mistake 1 — Confusing AC and AT

**Wrong**: "The application has a WAF, so AC:H"
**Correct**: AC measures conditions the attacker must meet. A WAF the attacker must bypass is an AC:H factor. A WAF that does not actually prevent exploitation does not raise AC.

AT measures pre-existing configuration on the target. If the attack only works because the target has a non-default debug endpoint enabled, AT:P.

### Mistake 2 — Ignoring Subsequent System Impact

Many scorers rate only the directly vulnerable component and leave SC/SI/SA as N. This is the most common source of under-scoring.

Always ask: "If I compromise this component, what else can I reach?" Internal APIs, databases, S3 buckets, identity providers, and other microservices all count as subsequent systems.

### Mistake 3 — Setting E:X (Not Defined) by Default

E:X means you are not providing threat context. Use E:U if you found a novel vulnerability with no public disclosure. Use E:P if a public PoC exists. Use E:A if the vulnerability class appears on the CISA KEV list or is referenced in threat intelligence. Only use E:X when you genuinely have no information and do not want to influence the Base score.

### Mistake 4 — Scoring PR Based on What Was Used, Not What Is Required

If an attacker used an admin account to test a vulnerability but the vulnerability is also exploitable as a regular user, score PR:L (or PR:N if unauthenticated access is possible). Score the minimum privilege required for exploitation, not the privilege level used during testing.

### Mistake 5 — Conflating VC/VI/VA with SC/SI/SA

VC/VI/VA is the impact on the component that directly contains the vulnerability (the API endpoint, the database driver, the file parser).

SC/SI/SA is the impact on everything else the attacker reaches as a consequence of that exploitation.

Example: An XXE in an XML parser (the vulnerable component) that lets an attacker read `/etc/passwd` from the OS:
- VC: L (parser leaks a small amount of its own process data)
- SC: H (the OS, a subsequent system, loses complete confidentiality)

### Mistake 6 — Using CVSS 3.1 Metrics in a CVSS 4.0 Score

CVSS 4.0 removed the Scope (S) metric and added AT. Do not include S:C or S:U in a CVSS 4.0 vector string. If you see a vector with the Scope metric, it is CVSS 3.1.

### Mistake 7 — Rounding the Score

CVSS 4.0 scores are reported to one decimal place as computed by the lookup table. Do not round 7.8 up to 8.0 to push a finding into HIGH. Report the calculator's exact output.

---

## Quick Reference — Severity Decision Tree

```
Is the vulnerability reachable over the network without authentication?
├── YES → Start at AV:N, PR:N — likely HIGH or CRITICAL
│         Does exploitation give access to additional systems beyond the vulnerable component?
│         ├── YES → SC/SI/SA likely H → CRITICAL range
│         └── NO  → Score on VC/VI/VA alone → HIGH or MEDIUM
└── NO  → If local only (AV:L) or physical (AV:P) → MEDIUM or LOW unless impact is extreme
```

---

## Skill Output Summary

After completing this skill, you will have produced:

1. A completed scoring worksheet with per-metric justifications
2. A syntactically valid CVSS 4.0 vector string
3. A numeric score and severity label verified against the FIRST.org calculator
4. A prose justification block ready for the finding document
5. A `finding_tracker.py add` command with all required fields
6. An `autodoc_engine.py log` command for the engagement timeline

Hand these outputs to `rt-agent-scribe` (capability FD — Document Finding) to produce the full finding document with executive summary, technical details, evidence references, and remediation guidance.
