Skip to content

Findings Overview

The Findings view is the central triage surface in Vygl. Every issue from every scan is here, deduplicated per (project, branch, fingerprint) so the same problem detected across multiple scans of the same branch appears as a single row.

Each row is a unique finding with:

  • Severity — critical / high / medium / low / info.
  • Type — SAST, SCA, Secrets, IaC, Malware, or Container.
  • Title — human-readable summary from the rule.
  • File locationpath/to/file.py:42.
  • Statusopen / acknowledged / fix_claimed / fixed / false_positive / ignored / suppressed / auto_fixed (the last is system-applied).
  • AI verdict — true positive / false positive / uncertain (when AI verification has run).
  • First seen / last seen — when the issue first appeared on this branch and most recently re-detected.

Combine filters to narrow the list:

  • Severity — multi-select.
  • Status — open by default; flip to include suppressed/fixed for historical views.
  • Scan type — focus on secrets, dependencies, etc.
  • Project — single project or org-wide.
  • Rule — drill into one specific rule.
  • AI verdict — show true_positive, false_positive, uncertain, or unanalyzed.
  • Branch — sentinels default (project default with fallback) or all, or a literal branch name. Works org-wide as well as per-project.
  • Originscan vs cve_watch vs manual.
  • Created / resolved time windowscreated_after, resolved_after.

Filters persist in the URL — bookmark or share a triage view directly.

Findings are uniquely keyed by (project_id, branch, fingerprint). Within a branch, the same fingerprint detected by multiple scans collapses into one row; across branches, the same fingerprint is one row per branch — but sticky triage decisions (false_positive, ignored, fixed, suppressed) and AI verdicts are seeded onto a sibling-branch row the first time the fingerprint is detected there, so triage doesn’t get re-litigated when a finding spreads from a feature branch to main.

The fingerprint formula varies by scan type — for SAST/Secrets/IaC it’s sha256(scan_type || rule_id || file_path || start_line || normalized_snippet); SCA and Container have engine-specific recipes that incorporate ecosystem and package identity instead of source-line position. See Inline Suppression for what’s stable and what isn’t.

Select multiple rows and pick a status from the bulk-action dropdown — every user-settable status is supported, including fix_claimed, false_positive, ignored, suppressed, and acknowledged. Optionally set a reason text, which is recorded on each row’s status_reason field and on the audit-log entry.

You can also queue AI verification across many findings: Analyze unverified dispatches verifications for every unverified finding matching the current filter (capped at 500 per click); selecting rows and clicking Re-Analyze forces re-verification on already-verified rows.

Two export formats from the Findings view:

  • CSV — assembled client-side by paginating every finding matching the active filter (no row cap; the export hits the API once per page until done). Columns: Severity, Type, Rule ID, Title, File, Line, Status, AI Verdict, Confidence, Project, Created.
  • SARIF 2.1.0 — server-side, applies the active filter, capped at 25,000 findings (the endpoint returns 413 above that). Compatible with GitHub Code Scanning, Azure DevOps, JFrog Xray.

See Exports for the full schema.