MITRE ATT&CK matrix
Every Pentestas finding now carries a MITRE ATT&CK technique id. The scan-detail page renders a per-scan ATT&CK matrix — fourteen tactics across, technique cells stacked under each, severity-coloured, click-to-jump. SOC analysts and detection engineers get the same view their threat-modelling tools speak in.
Where it lives
Open any scan in the SPA. The chains card has a List / Mindmap / ATT&CK tab toggle in its header. Click ATT&CK. First switch fetches the scan's findings; subsequent toggles are cached.
Layout
The matrix follows the canonical MITRE Enterprise tactic order, left to right:
- Reconnaissance (TA0043)
- Resource Development (TA0042)
- Initial Access (TA0001)
- Execution (TA0002)
- Persistence (TA0003)
- Privilege Escalation (TA0004)
- Defense Evasion (TA0005)
- Credential Access (TA0006)
- Discovery (TA0007)
- Lateral Movement (TA0008)
- Collection (TA0009)
- Command and Control (TA0011)
- Exfiltration (TA0010)
- Impact (TA0040)
Each tactic column shows:
- Tactic name + ID at the top.
- A finding-count badge (dim when zero).
- Stacked technique cells. Each cell carries the technique ID, name, and a count of matching findings.
Cell colour
Every cell is coloured by the maximum severity of the findings under it:
- Red — at least one CRITICAL finding for this technique.
- Orange — at least one HIGH.
- Yellow — MEDIUM is the worst.
- Green — LOW.
- Blue — INFO.
Click any cell to open the highest-severity finding behind it. Multi-finding cells flash a brief toast announcing the count.
How the mapping works
Two layers run in series:
Server-side enrichment
core/finding_taxonomy.enrich() runs on every persisted finding. It looks up the finding's vuln_type against a curated table that maps each detector's output to a CWE, an OWASP Top-10 category, a WASC v2 id, and a MITRE ATT&CK technique. The technique id lands in the mitre_attck column on the findings table.
Examples of mappings:
- SQL Injection →
T1190(Exploit Public-Facing Application) - Cross-Site Scripting →
T1059.007(JavaScript) - Default credentials →
T1078(Valid Accounts) - Remote Code Execution →
T1059(Command and Scripting Interpreter) - SSRF, XXE →
T1190/T1212 - Path Traversal →
T1083(File and Directory Discovery) - Cookie / session leakage →
T1539(Steal Web Session Cookie) - Plaintext credential dump →
T1552(Unsecured Credentials) - Banner / version disclosure →
T1592(Gather Victim Host Information)
Client-side tactic roll-up
The SPA carries a static technique-to-tactic map covering every technique the taxonomy emits. Findings are bucketed by their mitre_attck field; cells under each tactic show the count + worst severity. Multi-tactic techniques (e.g. T1078 spans Initial Access + Persistence + Privilege Escalation + Defense Evasion) are placed in their most representative tactic to keep the matrix readable.
API
The matrix is built client-side from the existing findings API:
curl -H "Authorization: Bearer $PT_TOKEN" \
"https://app.pentestas.com/api/findings?scan_id=$SID&limit=500" \
| jq '.findings[] | {id, severity, vuln_type, mitre_attck}'
Each finding response now carries mitre_attck + wasc_id alongside the existing cwe_id + owasp_category. NULL values coerce to empty string for backwards compatibility with older scan rows.
Pivoting from the matrix
The ATT&CK view is the fastest way to answer:
- "Where does this scan land on Initial Access?" — look at column 3.
- "Did we cover Credential Access?" — column 8.
- "What CRITICALs in this scan map to T1190?" — click the red Initial Access cell.
- "Are there any unmapped findings?" — the legend shows mapped vs unmapped totals.
When the matrix is empty
If every cell is blank but the scan has findings, the per-finding mitre_attck column likely wasn't populated — older scan rows from before the enrichment was wired. New scans always populate it; existing rows have been backfilled.
See also
- Exploitation chains — the orchestrator that demonstrates impact at the application layer
- Severity scale — how severity drives cell colour
- Findings API — every finding response now exposes
mitre_attck