{# Defensive defaults block — placed BEFORE the render-mode gate per the
E.1/E.2/E.3/1c.1 pattern. Mirrors all prior Phase 1b/1c migrations.
Coerces non-mapping / non-iterable upstream values so the template
never crashes on data drift. Assessment Overview returns 16 keys
(17 with exploit_intel) — defensive guards cover all of them. #}
{% set summary = summary | default({}) %}
{% if summary is string or summary is not mapping %}{% set summary = {} %}{% endif %}
{# exploit_intel is in the transform return but not rendered by the
migrated template (the Exploit Maturity 3x3 grid reads from
exploit_maturity_summary; the KEV/EPSS-high KPI cells read from
summary). No defensive coerce needed since we never read it. #}
{% set triage_pipeline = triage_pipeline | default({}) %}
{% if triage_pipeline is string or triage_pipeline is not mapping %}{% set triage_pipeline = {} %}{% endif %}
{% set remediation_progress = remediation_progress | default({}) %}
{% if remediation_progress is string or remediation_progress is not mapping %}{% set remediation_progress = {} %}{% endif %}
{% set scan_metadata = scan_metadata | default({}) %}
{% if scan_metadata is string or scan_metadata is not mapping %}{% set scan_metadata = {} %}{% endif %}
{% set severity_distribution = severity_distribution | default({}) %}
{% if severity_distribution is string or severity_distribution is not mapping %}{% set severity_distribution = {} %}{% endif %}
{% set exploit_maturity_summary = exploit_maturity_summary | default({}) %}
{% if exploit_maturity_summary is string or exploit_maturity_summary is not mapping %}{% set exploit_maturity_summary = {} %}{% endif %}
{% set reachability_summary = reachability_summary | default({}) %}
{% if reachability_summary is string or reachability_summary is not mapping %}{% set reachability_summary = {} %}{% endif %}
{% set sbom_stats = sbom_stats | default({}) %}
{% if sbom_stats is string or sbom_stats is not mapping %}{% set sbom_stats = {} %}{% endif %}
{% set findings_by_tier = findings_by_tier | default({}) %}
{% if findings_by_tier is string or findings_by_tier is not mapping %}{% set findings_by_tier = {} %}{% endif %}
{% set project_cards = project_cards | default([]) %}
{% if project_cards is mapping or project_cards is string or project_cards is not iterable %}{% set project_cards = [] %}{% endif %}
{% set top_security_risks = top_security_risks | default([]) %}
{% if top_security_risks is mapping or top_security_risks is string or top_security_risks is not iterable %}{% set top_security_risks = [] %}{% endif %}
{% set component_risk_ranking = component_risk_ranking | default([]) %}
{% if component_risk_ranking is mapping or component_risk_ranking is string or component_risk_ranking is not iterable %}{% set component_risk_ranking = [] %}{% endif %}
{% set component_license_distribution = component_license_distribution | default([]) %}
{% if component_license_distribution is mapping or component_license_distribution is string or component_license_distribution is not iterable %}{% set component_license_distribution = [] %}{% endif %}
{% set component_inventory = component_inventory | default([]) %}
{% if component_inventory is mapping or component_inventory is string or component_inventory is not iterable %}{% set component_inventory = [] %}{% endif %}
{% import "_console_macros.html" as fs with context %}
{% if render_mode != 'fragment' %}
Assessment Overview
{# Scope-badge precedence mirrors the topbar Scope meta:
folder_filter > project_filter > scan_metadata.project_name.
Version badge only renders when the report is project-
or single-project-scoped (folder rollups span versions). #}
{% if folder_filter %}
Folder: {{ folder_filter }}
{% elif project_label %}
Project: {{ project_label }}
{% elif scan_metadata.get('project_name') %}
{{ scan_metadata.get('project_name') }}
{% endif %}
{% if scan_metadata.get('version_name') and not folder_filter %}
v{{ scan_metadata.get('version_name') }}
{% endif %}
{# ── 1. Executive KPIs ── #}
{{ fs.panel_head("Executive KPIs", meta="findings, components, exploit exposure") }}
{% if summary %}
{% set ao_total_findings = summary.get('total_findings', 0) | int %}
{% set ao_crit = summary.get('critical_count', 0) | int %}
{% set ao_high = summary.get('high_count', 0) | int %}
{% set ao_med = summary.get('medium_count', 0) | int %}
{% set ao_low = summary.get('low_count', 0) | int %}
{% set ao_open = summary.get('open_count', 0) | int %}
{% set ao_triaged = summary.get('triaged_count', 0) | int %}
{% set ao_exploit = summary.get('exploit_count', 0) | int %}
{% set ao_epss = summary.get('epss_high_count', 0) | int %}
{% set ao_components = summary.get('total_components', 0) | int %}
{{ fs.kpi_cell("Total Findings", ao_total_findings) }}
{{ fs.kpi_cell("Critical", ao_crit, dot=("critical" if ao_crit > 0 else None)) }}
{{ fs.kpi_cell("High", ao_high, dot=("high" if ao_high > 0 else None)) }}
{{ fs.kpi_cell("Medium", ao_med, dot=("medium" if ao_med > 0 else None)) }}
{{ fs.kpi_cell("Low", ao_low, dot=("low" if ao_low > 0 else None)) }}
{{ fs.kpi_cell("Open", ao_open) }}
{{ fs.kpi_cell("Triaged", ao_triaged) }}
{{ fs.kpi_cell("Exploit", ao_exploit, dot=("high" if ao_exploit > 0 else None)) }}
{{ fs.kpi_cell("EPSS-high", ao_epss, dot=("high" if ao_epss > 0 else None)) }}
{{ fs.kpi_cell("Components", ao_components) }}
{% else %}
{# Explicit empty-state — preserves the pre-migration single
"No data" fallback rather than rendering ten zero cells
that look like real numbers. #}
No findings data available for this report.
{% endif %}
{# ── 2. Severity Distribution (doughnut). Gated on at least one
bucket being non-zero so the chart doesn't render an empty
frame when the all-zero default dict slips through. #}
{% set _sd_total = (severity_distribution.get('CRITICAL', 0) | int)
+ (severity_distribution.get('HIGH', 0) | int)
+ (severity_distribution.get('MEDIUM', 0) | int)
+ (severity_distribution.get('LOW', 0) | int)
+ (severity_distribution.get('INFORMATIONAL', 0) | int) %}
{% if severity_distribution and _sd_total > 0 %}
{{ fs.panel_head("Severity Distribution", meta="breakdown of all findings by severity") }}
{% if render_mode == 'fragment' and not fragment_scripts_enabled %}
Chart unavailable in fragment view
{% else %}
{% endif %}
{% endif %}
{# ── 3. Top Security Risks ── #}
{% if top_security_risks and (top_security_risks | length) > 0 %}
{{ fs.panel_head("Top Security Risks", meta="top 10 open findings by CVSS") }}
| CVE ID |
Severity |
Component |
Version |
CVSS |
EPSS %ile |
KEV |
Exploit |
{% for f in top_security_risks %}
{% if f is mapping %}
{% if domain and f.get('project_id') and f.get('project_version_id') and f.get('finding_id') %}
{{ f.get('cve_id', '—') }}
{% else %}
{{ f.get('cve_id', '—') }}
{% endif %}
|
{{ f.get('severity', 'UNKNOWN') }} |
{{ f.get('component', '—') }} |
{{ f.get('component_version', '—') }} |
{{ "%.1f"|format(f.get('cvss_score', 0) | float) if f.get('cvss_score') else "—" }} |
{{ "%.1f"|format((f.get('epss_percentile', 0) | float) * 100) if f.get('epss_percentile') else "—" }}{% if f.get('epss_percentile') %}%{% endif %} |
{% if f.get('in_kev') %}KEV{% else %}—{% endif %} |
{% if f.get('has_exploit') %}Exploit{% else %}—{% endif %} |
{% endif %}
{% endfor %}
{% endif %}
{# ── 4. Exploit Maturity (3×3 heat-coded grid) ── #}
{% if exploit_maturity_summary %}
{{ fs.panel_head("Exploit Maturity", meta=((exploit_maturity_summary.get('total_with_exploits', 0)) | string) ~ " finding(s) with known exploit intel") }}
{{ exploit_maturity_summary.get('total_with_exploits', 0) }} finding(s) with known exploit intelligence — heat-coded by count.
{% set cats = [
("kev", "In KEV"), ("vckev", "VulnCheck KEV"), ("weaponized", "Weaponized"),
("poc", "PoC"), ("threatactors", "Threat Actors"), ("ransomware", "Ransomware"),
("botnets", "Botnets"), ("commercial", "Commercial"), ("reported", "Reported")
] %}
{% for key, label in cats %}
{% set count = exploit_maturity_summary.get(key, 0) | int %}
{% if count > 10 %}{% set heat = "ao-heat-3" %}
{% elif count > 3 %}{% set heat = "ao-heat-2" %}
{% elif count > 0 %}{% set heat = "ao-heat-1" %}
{% else %}{% set heat = "ao-heat-0" %}{% endif %}
{% endfor %}
{% endif %}
{# ── 5. Reachability Analysis (gated on has_data) ── #}
{% if reachability_summary.get('has_data') %}
{{ fs.panel_head("Reachability Analysis", meta="static-analysis verdict on whether vulnerable code is invoked") }}
{{ reachability_summary.get('reachable', 0) }}
Reachable
{{ reachability_summary.get('unreachable', 0) }}
Unreachable
{{ reachability_summary.get('inconclusive', 0) }}
Inconclusive
{% endif %}
{# ── 6. Triage Pipeline ── #}
{% if triage_pipeline %}
{{ fs.panel_head("Triage Pipeline", meta="current VEX triage status of findings") }}
{{ triage_pipeline.get('in_triage', 0) }}
Being Investigated
{{ triage_pipeline.get('affected', 0) }}
Confirmed Affected
{{ triage_pipeline.get('exploitable', 0) }}
Open with Known Exploit
{% set _vex = triage_pipeline.get('vex_summary', {}) %}
{% if _vex is mapping and _vex.get('count') %}
Auto-triage recommendations available: {{ _vex.get('count') }} suggestion(s)
{% set _tc = _vex.get('top_components', []) %}
{% if _tc and _tc is iterable and _tc is not string %}
— top components: {{ _tc | join(", ") }}
{% endif %}
{% endif %}
{% endif %}
{# ── 7. Remediation Progress (P0 / P1) ── #}
{% if remediation_progress %}
{{ fs.panel_head("Remediation Progress", meta="prioritized action cards by P0/P1 tier") }}
{{ remediation_progress.get('p0_count', 0) }}
P0 Action Cards
{{ remediation_progress.get('p1_count', 0) }}
P1 Action Cards
{% set _top_p0 = remediation_progress.get('top_p0_cves', []) %}
{% if _top_p0 and _top_p0 is iterable and _top_p0 is not string and (_top_p0 | length) > 0 %}
Top P0 CVEs
| CVE ID | Component | CVSS | Project |
{% for cve in _top_p0 %}
{% if cve is mapping %}
{% if domain and cve.get('project_id') and cve.get('project_version_id') and cve.get('finding_id') %}
{{ cve.get('cve_id', '—') }}
{% else %}
{{ cve.get('cve_id', '—') }}
{% endif %}
|
{{ cve.get('component', '—') }} |
{{ "%.1f"|format(cve.get('cvss_score', 0) | float) if cve.get('cvss_score') else "—" }} |
{{ cve.get('project_name', '—') }} |
{% endif %}
{% endfor %}
{% endif %}
{% set _p0c = remediation_progress.get('p0_components', []) %}
{% if _p0c and _p0c is iterable and _p0c is not string and (_p0c | length) > 0 %}
P0 Vulnerable Components — Critical + Exploit/KEV
{% for card in _p0c %}
{% if card is mapping %}
{{ card.get('component', '—') }}
{{ card.get('finding_count', 0) }} finding(s) ·
Top CVE: {{ card.get('top_cve', '—') }} ·
CVSS {{ "%.1f"|format(card.get('worst_cvss', 0) | float) }}
{% if card.get('project') %}
{{ card.get('project') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% set _p1c = remediation_progress.get('p1_components', []) %}
{% if _p1c and _p1c is iterable and _p1c is not string and (_p1c | length) > 0 %}
P1 Vulnerable Components — High + Network Vector
{% for card in _p1c %}
{% if card is mapping %}
{{ card.get('component', '—') }}
{{ card.get('finding_count', 0) }} finding(s) ·
Top CVE: {{ card.get('top_cve', '—') }} ·
CVSS {{ "%.1f"|format(card.get('worst_cvss', 0) | float) }}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{# ── 8. All Findings by Severity Tier ── #}
{% if findings_by_tier %}
{{ fs.panel_head("All Findings", meta="grouped by severity tier (capped at 2000 rows)") }}
{% set status_labels = {"UNKNOWN": "Open", "NO_STATUS": "Open", "OPEN": "Open", "IN_TRIAGE": "In Triage"} %}
{% set tiers = [
("CRITICAL", findings_by_tier.get('CRITICAL', []) | default([])),
("HIGH", findings_by_tier.get('HIGH', []) | default([])),
("MEDIUM", findings_by_tier.get('MEDIUM', []) | default([])),
("LOW", findings_by_tier.get('LOW', []) | default([])),
("INFORMATIONAL", findings_by_tier.get('INFORMATIONAL', []) | default([]))
] %}
{% for tier_name, tier_findings_raw in tiers %}
{% set tier_findings = tier_findings_raw %}
{% if tier_findings is mapping or tier_findings is string or tier_findings is not iterable %}{% set tier_findings = [] %}{% endif %}
{% if (tier_findings | length) > 0 %}
{{ tier_name }} — {{ tier_findings | length }} finding(s)
| CVE ID |
Severity |
Component |
Version |
CVSS |
EPSS %ile |
KEV |
Exploit |
Status |
{% for f in tier_findings %}
{% if f is mapping %}
{% if domain and f.get('project_id') and f.get('project_version_id') and f.get('finding_id') %}
{{ f.get('cve_id', '—') }}
{% else %}
{{ f.get('cve_id', '—') }}
{% endif %}
|
{{ f.get('severity', 'UNKNOWN') }} |
{{ f.get('component', '—') }} |
{{ f.get('component_version', '—') }} |
{{ "%.1f"|format(f.get('cvss_score', 0) | float) if f.get('cvss_score') else "—" }} |
{{ "%.1f"|format((f.get('epss_percentile', 0) | float) * 100) if f.get('epss_percentile') else "—" }}{% if f.get('epss_percentile') %}%{% endif %} |
{% if f.get('in_kev') %}KEV{% else %}—{% endif %} |
{% if f.get('has_exploit') %}Exploit{% else %}—{% endif %} |
{{ status_labels.get(f.get('status', '—'), f.get('status', '—')) }} |
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{# ── 9. Component Risk Analysis ── #}
{% if component_risk_ranking and (component_risk_ranking | length) > 0 %}
{{ fs.panel_head("Component Risk Analysis", meta="top components by weighted severity score") }}
| Component |
Version |
Critical |
High |
Medium |
Low |
Total |
Risk Score |
{% for c in component_risk_ranking %}
{% if c is mapping %}
| {{ c.get('component', '—') }} |
{{ c.get('component_version', '—') }} |
{% if (c.get('critical', 0) | int) > 0 %}{{ c.get('critical') }}{% else %}0{% endif %} |
{% if (c.get('high', 0) | int) > 0 %}{{ c.get('high') }}{% else %}0{% endif %} |
{{ c.get('medium', 0) }} |
{{ c.get('low', 0) }} |
{{ c.get('total', 0) }} |
{{ c.get('risk_score', 0) }} |
{% endif %}
{% endfor %}
{% endif %}
{# ── 10. Component Licenses (horizontal bar) ── #}
{% if component_license_distribution and (component_license_distribution | length) > 0 %}
{{ fs.panel_head("Component Licenses", meta="top 10 licenses by component count") }}
{% if render_mode == 'fragment' and not fragment_scripts_enabled %}
Chart unavailable in fragment view
{% else %}
{% endif %}
{% endif %}
{# ── 11. SBOM Summary ── #}
{% if sbom_stats %}
{{ fs.panel_head("SBOM Summary", meta="component inventory snapshot") }}
Total Components: {{ sbom_stats.get('total_components', 0) }}
{% if component_inventory and (component_inventory | length) > 0 %}
View component inventory ({{ component_inventory | length }})
| Component | Version | Type | License |
{% for c in component_inventory %}
{% if c is mapping %}
| {{ c.get('name', '—') }} |
{{ c.get('version') if c.get('version') else "—" }} |
{{ c.get('type') if c.get('type') else "—" }} |
{{ c.get('license') if c.get('license') else "—" }} |
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{# ── 12. Per-Project Breakdown (folder scope only) ── #}
{% if project_cards and (project_cards | length) > 0 %}
{{ fs.panel_head("Per-Project Breakdown", meta=((project_cards | length) | string) ~ " project(s)") }}
{% for proj in project_cards %}
{% if proj is mapping %}
{{ proj.get('project_name', '—') }} —
{{ proj.get('critical', 0) }} critical,
{{ proj.get('high', 0) }} high
({{ proj.get('total', 0) }} total)
Critical: {{ proj.get('critical', 0) }} ·
High: {{ proj.get('high', 0) }} ·
Medium: {{ proj.get('medium', 0) }} ·
Low: {{ proj.get('low', 0) }} ·
Open: {{ proj.get('open', 0) }}
{% set _tf = proj.get('top_findings', []) %}
{% if _tf and _tf is iterable and _tf is not string and (_tf | length) > 0 %}
| CVE | Severity | CVSS | Component |
{% for f in _tf %}
{% if f is mapping %}
{# NOTE: project_cards rows from
assessment_overview_transform do NOT
carry project_id / project_version_id,
so an entity-link href is impossible
to construct here without a transform
change (out-of-scope for 1c.2). Render
as plain code; PRs adding project IDs
to project_cards can re-introduce the
anchor wrapper in a future commit. #}
{{ f.get('cve_id', '—') }} |
{{ f.get('severity', 'UNKNOWN') }} |
{{ "%.1f"|format(f.get('cvss_score', 0) | float) if f.get('cvss_score') else "—" }} |
{{ f.get('component', '—') }} |
{% endif %}
{% endfor %}
{% endif %}
{% if proj.get('riskiest_component') %}
Riskiest component: {{ proj.get('riskiest_component') }}
(score: {{ proj.get('riskiest_score', 0) }})
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{# ── 13. Scan Metadata ── #}
{% if scan_metadata %}
{{ fs.panel_head("Scan Metadata", meta="provenance and freshness") }}
{% if scan_metadata.get('project_name') %}Project: {{ scan_metadata.get('project_name') }}{% endif %}
{% if scan_metadata.get('version_name') %}Version: {{ scan_metadata.get('version_name') }}{% endif %}
{% if scan_metadata.get('scan_date') %}Scan Date: {{ scan_metadata.get('scan_date') }}{% endif %}
{% if scan_metadata.get('days_since_scan') is not none %}
{{ scan_metadata.get('days_since_scan') }} day(s) ago
{% endif %}
{% endif %}
{% if render_mode != 'fragment' %}
{{ fs.status_bar(items=[
"Recipe: Assessment Overview",
"Findings: " ~ ((summary.get('total_findings', 0)) | string),
"Open: " ~ ((summary.get('open_count', 0)) | string),
generated_at | default(''),
], version='fs-report ' ~ (fs_report_version | default('dev'))) }}
{% endif %}
{% if render_mode != 'fragment' or fragment_scripts_enabled %}
{% include '_action_buttons.html' %}
{% endif %}