{% extends "base.html" %} {% block title %}Findings · ai-protect{% endblock %} {% block content %} {% if system_status %}
{% set lamp_color = {'green':'#23c45e', 'yellow':'#eab308', 'red':'#ef4444'}[system_status.level] %} {{ system_status.level }} system status {% for comp_name, comp in system_status.components.items() %} {% set c = {'green':'#23c45e', 'yellow':'#eab308', 'red':'#ef4444'}[comp.level] %} {{ comp_name }} {% endfor %}
{% endif %}
{% if stats_scope == "filtered" %}
Showing filtered view {% if filter_app %} · app {{ filter_app }}{% endif %} {% if filter_severity %} · severity {{ filter_severity }}{% endif %} {% if filter_adapter %} · adapter {{ filter_adapter }}{% endif %} {% if filter_category %} · category {{ filter_category }}{% endif %} {% if filter_fixable %} · ⚡ has fix{% endif %} · numbers below reflect this filter ({{ global_total }} total across all apps · clear) {# Bulk-dismiss: writes a manual_dismiss Change per finding in the current filter. Reason required. Useful for the unverified-intel cleanup case: filter to adapter=intel_match&app=X then dismiss the lot with one well-documented reason. #}
Bulk-dismiss {{ stats.total }} filtered
{% if filter_app %}{% endif %} {% if filter_severity %}{% endif %} {% if filter_adapter %}{% endif %} {% if filter_category %}{% endif %}
{% endif %}
{{ stats.total }}
findings{% if stats_scope == "filtered" %} (filtered){% endif %}
{{ stats.high_or_above }}
HIGH or CRITICAL
{{ stats.by_app|length }}
{% if stats_scope == "filtered" %}apps in view{% else %}apps scanned{% endif %}
{{ stats.by_adapter|length }}
adapters firing
{# _url(): build a / URL preserving every currently-active filter while overriding one. Passing None for `value` clears that single filter. Used by every pill / dropdown so navigation never silently drops filters the user has set (e.g. clicking the "critical" pill while viewing app=example-ads-studio must stay on that app). #} {% macro _url(severity=None, category=None, app=None, adapter=None, fixable=None, override=None, clear=None) -%} {%- set qs = {} -%} {%- if filter_severity %}{% set _ = qs.update({'severity': filter_severity}) %}{% endif -%} {%- if filter_category %}{% set _ = qs.update({'category': filter_category}) %}{% endif -%} {%- if filter_app %}{% set _ = qs.update({'app': filter_app}) %}{% endif -%} {%- if filter_adapter %}{% set _ = qs.update({'adapter': filter_adapter}) %}{% endif -%} {%- if filter_fixable %}{% set _ = qs.update({'fixable': 1}) %}{% endif -%} {#- override `clear` first (drop the named filter), then apply explicit set -#} {%- if clear %}{% set _ = qs.pop(clear, None) %}{% endif -%} {%- if override == 'severity' %}{% set _ = qs.update({'severity': severity}) %}{% endif -%} {%- if override == 'category' %}{% set _ = qs.update({'category': category}) %}{% endif -%} {%- if override == 'app' %}{% set _ = qs.update({'app': app}) %}{% endif -%} {%- if override == 'adapter' %}{% set _ = qs.update({'adapter': adapter}) %}{% endif -%} {%- if override == 'fixable' %}{% set _ = qs.update({'fixable': 1}) %}{% endif -%} {{ url_for('index', **qs) }} {%- endmacro %}
{#- "all" pill = drop severity + fixable, keep everything else (app/adapter/category remain sticky). -#} all {{ pill_all_count }} {% for sev in severities %} {% set cnt = pill_severity_counts.get(sev, 0) %} {{ sev }} {{ cnt }} {% endfor %} ⚡ has fix {{ fixable_count }} {# Unverified-intel toggle: by default the dashboard hides intel_match_unverified findings (token-overlap noise that grows to hundreds per app and drowns real scanner signal). Click to re-include in the active view; click again to hide. #} {% if include_unverified %} intel unverified: shown · hide → {% elif hidden_unverified_count %} intel unverified hidden {{ hidden_unverified_count }} {% endif %}
{% if filter_severity or filter_app or filter_adapter or filter_category or filter_fixable %} clear filters {% endif %} ⬇ CSV{% if filter_severity or filter_app or filter_adapter or filter_category or filter_fixable %} (filtered){% endif %} ⬇ PDF{% if filter_severity or filter_app or filter_adapter or filter_category or filter_fixable %} (filtered){% else %} (full){% endif %}
{% if findings %} {% for f in findings %} {% set tool_meta = catalog.get(f.adapter, {}) %} {% endfor %}
Severity App Tier Adapter Category Title Affected Fix
{% if fixable.get(f.finding_id) %} {% endif %} {{ f.severity.value }} {% if f.evidence.get('intel_match_unverified') %} unverified {% endif %} {{ f.app_name }} T{{ f.tier }} {{ f.adapter }} {{ f.category.value }} {{ f.title }} {% if f.evidence.get('file') %}{{ f.evidence['file'] | replace('/opt/app/', '') }} {% if f.evidence.get('line') %}:{{ f.evidence['line'] }}{% endif %} {% if f.evidence.get('start_line') %}:{{ f.evidence['start_line'] }}{% endif %} {% elif f.affected.get('file') %}{{ f.affected['file'] | replace('/opt/app/', '') }} {% elif f.affected.get('target') %}{{ f.affected['target'] }} {% elif f.affected.get('app') %}— {% endif %} {% if fixable.get(f.finding_id) %}
{% else %} {% endif %}
{% else %}
No findings yet. Run a scan:
python -m pipeline.cli --findings <path> run <manifest> --stage build
{% endif %}
{% endblock %}