User Guide

AppSec — Application Security Add-on

How to use V/ergent's AppSec module: signing in from V/ergent, reading the findings dashboard, uploading SARIF from any scanner, the four-tab finding view, automated triage, exploit-intelligence enrichment, merge-gate policies, and demo data for first-time exploration.

6+Scanner formats
KEV + EPSSLive enrichment
4-tabPer-finding view
Open AppSec

1 What AppSec does

AppSec is V/ergent's application-security add-on. You send it findings from any scanner that emits SARIF; it normalises them into one schema, deduplicates across runs, enriches each with live exploit intelligence, risk-scores everything, auto-triages true vs false positives, and pushes the real ones into your CyberCore assessment or your GitHub pull requests.

SAST: Semgrep SAST: CodeQL SCA: Trivy SCA: OSV SCA: Grype Secrets: Gitleaks Secrets: TruffleHog IaC: Checkov IaC: KICS DAST: OWASP ZAP DAST: Nuclei

2 Signing in

AppSec lives at a separate subdomain but shares identity with V/ergent — no second login.

  1. 1
    Sign in to V/ergent at app.vergent.co.ke.
  2. 2
    Click AppSec in the top nav (bug icon, next to CyberCore).
  3. 3
    V/ergent mints a short-lived token, auto-submits it to AppSec's handoff endpoint, and drops a session cookie. You land on the dashboard without typing credentials again.
Sessions expire after 15 minutes. Click AppSec in V/ergent again to refresh — you won't lose context.

3 Trying it with demo data

First visit? Click Load demo findings on the empty dashboard. AppSec populates 15 curated sample findings — Log4Shell, subprocess command injection, SQL injection, hardcoded Stripe keys, overly permissive IAM, a few confident false positives — so you can explore every feature before wiring up a real scanner. Clear demos removes them (real ingested findings are never touched — demos are scoped by fingerprint prefix).

4 Uploading a SARIF file

  1. 1
    Run any supported scanner with SARIF output (e.g. semgrep --sarif, trivy --format sarif).
  2. 2
    On the dashboard, drag the .sarif (or .json) file onto the orange Upload SARIF zone, or click Choose file.
  3. 3
    Fill in repo (required) — the canonical identifier like acme/webapp. Commit SHA and skip triage are optional.
  4. 4
    Upload completes, AppSec responds with {ingested, new, duplicates}, and the page refreshes showing your findings sorted by risk.
From CI: skip the UI and POST the SARIF JSON directly with a bearer token. See For your CI below.

5 Reading the dashboard

Findings are listed by risk score — a 0–100 number that combines severity, EPSS exploit probability, CISA KEV listing, and reachability. Ten thousand raw findings become the thirty-seven that genuinely matter this sprint.

  1. 1
    Top cards summarise counts: total, critical, high, true-positive, false-positive, needs-review.
  2. 2
    Click any row to expand into the four-tab detail view. See next section.
  3. 3
    The KEV red badge means CISA lists this CVE as actively exploited. The unreachable green badge means reachability analysis thinks the vulnerable code isn't hit from production entry points.

6 The four-tab finding view

Each expanded finding has four tabs matching the review convention used across V/ergent:

  • Observation — raw scanner output: title, description, scanner + rule + severity, file path and line, CVE with EPSS percentile and KEV status, reachability.
  • Rationale — why it matters (or doesn't): the triage engine's reasoning plus the verdict, confidence, and risk score.
  • Action — concrete remediation steps in plain language.
  • Remediation — where the engine is confident, a unified-diff patch you can review and apply.

7 Triage verdicts

Every triaged finding lands in one of three buckets:

True positive
A real, exploitable issue in the shown code. The engine stakes its reputation on this.
False positive
Scanner misfired — pattern is safe in context, test fixture, unreachable, already mitigated.
Needs review
Engine can't decide from the information given. A human should look. Safer than a wrong guess.
Verdicts are cached across tenants by scanner + rule + normalised code pattern. The same subprocess(shell=True) pattern isn't re-triaged from scratch for every customer — one verdict serves all, and every re-run is free. Cross-tenant caching is intentional: the verdict is a property of the code pattern, not the customer's tenancy.

8 Live exploit intelligence

Findings with CVE identifiers get two extra signals fed into the risk score:

  • CISA KEV — the Known Exploited Vulnerabilities catalogue. If your CVE is on it, someone is actively exploiting it. Flagged in red.
  • EPSS — first.org's Exploit Prediction Scoring System. A 0–1 probability that the CVE will be exploited in the next 30 days. 94%+ is very high.

Both feeds are cached in Postgres with a 24-hour TTL and a retry-with-backoff pattern — if CISA is down, the dashboard keeps serving whatever was last known to be true instead of blanking out.

9 Merge-gate policies

Block merges when they'd introduce unacceptable risk. Rules are declarative — YAML or JSON — and evaluated via a single API call from your CI:

POST /policy/evaluate
{
  "rules": [
    { "id": "block-kev-confirmed",
      "block_when": { "kev_listed": true, "triage_verdict": "true_positive" } },
    { "id": "block-many-highs",
      "block_when": { "severity": ["critical","high"], "count_at_least": 6 } }
  ]
}

Response is {allowed, violations[]}. Fail the CI step if allowed=false. Untriaged findings never trip gates, so flaky triage doesn't break the merge pipeline.

10 For your CI

Every data endpoint accepts the same V/ergent JWT — no second identity plane. Mint a token, attach it as a bearer header, done.

POST /ingest/sarif         — SARIF + repo + optional PR → queued for triage
POST /ingest/sarif/upload  — multipart; same semantics as above
GET  /findings             — org-scoped list, sorted by risk
POST /policy/evaluate      — rules → allow/deny decision
GET  /health               — liveness + enrichment metrics (unauth)
The JWT's org_id claim is the tenant boundary. Findings never cross orgs — if your CI uses the wrong org_id you'll see "no findings" on the dashboard when you expect some.

11 Troubleshooting

"No findings yet" — either nothing has ingested for your org, or your JWT's org_id doesn't match. Click Load demo findings first to confirm the service works, then check the CI's token configuration.
Upload returns 400 — the file must be a valid SARIF 2.1.0 JSON document. Validate with jq . file.sarif first. Very large files (>50 MB) are rejected.
Every finding says "needs review" — the triage engine had no ANTHROPIC_API_KEY configured or it failed transiently. Ingest + enrichment + scoring still work without it; you just don't get TP/FP classification. Set the key in Railway to unlock verdicts.
Session expired — the HttpOnly cookie's TTL is 15 minutes. Click AppSec in V/ergent's nav again to re-mint.
Questions or gaps in this guide? Email support@vergent.co.ke.