← use cases/Security Tools

Add vulnerability context without building an intel pipeline

Most vulnerability scanners output CVSS scores and CVE IDs. They cannot tell you what is being actively exploited right now. Adding that context normally requires a full threat intelligence team. attestd is the API shortcut.

why the naive approach fails

Scanner output without exploitation context creates backlog, not action. Teams sort by CVSS and still miss what is being used in the wild.

  • CVSS measures severity of a vulnerability class, not whether anyone is exploiting this product@version today.
  • Building a KEV + EPSS + registry monitoring pipeline is real engineering work. Most tool vendors should not own that stack.
  • Supply chain compromises often score clean on CVE checks. Enrichment that only joins CVE IDs misses the compromise signal.
  • Enterprise exploit feeds are priced and gated for large buyers. A self-serve API call is the shortcut for product teams shipping a scanner.
what to branch on

Join these fields onto each finding. Keep your CVSS. Add the decision layer your users actually need.

FieldMeaning for this use case
actively_exploitedPromote the finding to P0 / urgent when true. This is the enrichment most scanners lack.
risk_stateAttestd's categorical severity for the product@version. Use for sort order alongside or instead of raw CVSS.
remote_exploitableNetwork-reachable conditions deserve higher priority than local-only findings with the same CVSS.
supply_chain.compromisedSurface as a separate finding type. Confirmed malicious package, not a CVE.
patch_available / fixed_versionGive users an upgrade target in the same enrichment payload, not a second lookup.
the request
bash
curl "https://api.attestd.io/v1/check?product=log4j&version=2.14.1" \
  -H "Authorization: Bearer $ATTESTD_API_KEY"
integration
enrich.py
import os
import attestd

client = attestd.Client(api_key=os.environ["ATTESTD_API_KEY"])

def enrich_finding(product: str, version: str, cve_id: str) -> dict:
    """Enrich a scanner finding with real-world exploitation data."""
    risk = client.check(product, version)

    compromised = bool(risk.supply_chain and risk.supply_chain.compromised)
    priority = "P0" if (
        risk.risk_state == "critical"
        or risk.actively_exploited
        or compromised
    ) else "P2"

    return {
        "cve": cve_id,
        "product": product,
        "version": version,
        "cvss_score": get_cvss(cve_id),          # your existing data
        "actively_exploited": risk.actively_exploited,
        "remote_exploitable": risk.remote_exploitable,
        "patch_available": risk.patch_available,
        "fixed_version": risk.fixed_version,
        "supply_chain_compromised": compromised,
        "attestd_risk_state": risk.risk_state,    # enriched signal
        "priority": priority,
    }
how to wire it
  1. 01

    Resolve product and version per finding

    Map your scanner's package or CPE identity to an Attestd product slug and version string. Call /v1/check once per unique pair.

  2. 02

    Join enrichment onto the finding

    Attach actively_exploited, risk_state, supply_chain.compromised, and fixed_version to the finding object your UI or ticket system already uses.

  3. 03

    Reprioritize the queue

    Sort or filter so actively exploited and compromised findings float above CVSS-only noise. Keep CVSS for users who still want it.

operational outcome

Findings are prioritized by what is actually being exploited.

Instead of presenting a list of hundreds of CVSS scores, your tool can surface a short list of things that matter right now. Vulnerabilities with confirmed active exploitation, plus confirmed supply chain compromises. No threat intel team required.

in the wild

The detection track record is the product argument. Attestd flagged VS Code Fake Font five days before JFrog's disclosure, TanStack and Mistral roughly two and a half hours before BleepingComputer despite valid SLSA Build Level 3 attestations and a passing npm audit, and the AsyncAPI re-compromise via live monitoring rather than a lookup against the original advisory.

Full timestamps live in the detection ledger. For signal-quality and access-model comparisons, see Attestd vs VulnCheck, Attestd vs NVD, and Attestd vs Snyk.