Vulnerability Intelligence
CleanLibrary surfaces vulnerability intelligence wherever you query a library: your editor hover, your AI agent's tool result, your terminal pre-install gate. All surfaces return the same verdict envelope, computed from the same data.
This page describes what's inside that envelope so you can use it confidently — whether you're reading a hover tooltip, scripting against the SDK, or wiring a CI gate.
1. What CleanLibrary tells you about a library
When you hover a package.json dependency line in VS Code, ask Claude Code about a package, or run cleanlib check, you get the same answer shape:
- Verdict —
ALLOW,WARN, orDENY. Actionable for install decisions. - Reason code — a stable machine-readable label (e.g.
VERDICT_KEV_LISTED,VERDICT_CLEAN,VERDICT_DEGRADED_STALE) you can branch on in scripts and policies. - Human message — a one-line summary suitable for end-users.
- Recommended upgrade — when a safer version exists, the path to it (with blast-radius and fix-trust signals where available).
- Exploitation signals — top CVEs by exploitation risk, fused from CISA KEV, EPSS, and exploit catalogs.
- Remediation blocks — up to seven sparse blocks describing the fix, the upstream lag, the deadline, reachability, and more.
- Freshness — every field carries an
as_ofdate and an availability flag so you know how recent the underlying data is.
The same envelope feeds your editor, your AI agent, your CLI, and your SDK calls. The presentation differs; the contract does not.
2. The verdict envelope
Every CleanLibrary verdict is wrapped in VerdictEnvelopeV1:
{
"status": "ALLOW | WARN | DENY",
"reason_code": "VERDICT_KEV_LISTED | VERDICT_CLEAN | ...",
"human_message": "log4j-core 2.14.1 is on the CISA Known-Exploited Vulnerabilities list — upgrade to 2.17.0 or later.",
"rich_data": {
/* up to 8 sparse axes of supporting intelligence */
},
"remediation": {
/* up to 7 sparse blocks describing how to fix */
},
"exploitability": {
/* KEV + EPSS + fused exploitation signals */
},
"as_of": "2026-05-28",
"availability": {
/* per-substrate freshness flags */
}
}
Field-by-field
| Field | Type | Meaning |
|---|---|---|
status | ALLOW / WARN / DENY | The action your tooling should take. See §6 for the table. |
reason_code | string (stable) | Machine-readable label. Branch on this in scripts; the set is registered (no ad-hoc strings). |
human_message | string | One-line summary safe for end-user display. |
rich_data | object (sparse) | Up to 8 axes of supporting signal — recommended version, repo health, EOL status, similar packages, top findings, terminal state, source attribution, package-level risk. Absent fields mean "no substrate data," not "no risk." |
remediation | object (sparse) | Up to 7 fix-focused blocks (see §5). |
exploitability | object | The fused exploitation verdict (see §3). |
as_of | ISO date | When this envelope was computed. |
availability | object | Per-substrate freshness flags (live, degraded_stale, unavailable). See §7. |
Sparse-by-design. Both rich_data and remediation carry only the blocks for which substrate data is currently available. An absent block does not mean a clean result — it means we don't have data for that axis. Read availability to disambiguate.
Example envelope — a clean package
{
"status": "ALLOW",
"reason_code": "VERDICT_CLEAN",
"human_message": "cors 2.8.5 — no active CVEs.",
"rich_data": {
"recommended_version": {
"version": "2.8.5",
"source": "latest_stable",
"detected_at": "2026-05-28T14:00:00Z",
"total_versions": 47
},
"package_risk": {
"vulnerability_count": 0,
"has_vulnerabilities": false,
"risk_level": "low",
"risk_score": 0
}
},
"remediation": {},
"exploitability": {
"exploit_maturity": "NONE",
"exploitation_likelihood": "LOW",
"exploit_risk_score": 0,
"top_cves": []
},
"as_of": "2026-05-28",
"availability": {
"kev": "live",
"epss": "live",
"exploitation_fusion": "live",
"remediation": "live"
}
}
Example envelope — a denied package
{
"status": "DENY",
"reason_code": "VERDICT_KEV_LISTED",
"human_message": "log4j-core 2.14.1 is on the CISA Known-Exploited Vulnerabilities list — upgrade to 2.17.0 or later.",
"rich_data": {
"recommended_version": {
"version": "2.22.1",
"source": "latest_stable",
"detected_at": "2026-05-28T14:00:00Z",
"total_versions": 38
},
"package_risk": {
"vulnerability_count": 4,
"has_vulnerabilities": true,
"risk_level": "critical",
"risk_score": 95
},
"top_findings": [
{
"cve_id": "CVE-2021-44228",
"severity": "CRITICAL",
"title": "Log4Shell — JNDI lookup remote code execution"
}
]
},
"remediation": {
"fix": {
"target_version": "2.17.0",
"semver_distance": "minor",
"available_since": "2021-12-18"
},
"blast_radius": {
"estimated_breaking_changes": "low",
"notes": "Configuration-only change for most users."
},
"deadline": {
"kev_due_date": "2021-12-24",
"context": "CISA federal-civilian deadline (informational for non-federal users)."
}
},
"exploitability": {
"exploit_maturity": "HIGH",
"exploitation_likelihood": "CRITICAL",
"exploit_risk_score": 95,
"top_cves": [
{
"cve_id": "CVE-2021-44228",
"severity": "CRITICAL",
"exploit_risk_score": 95,
"in_kev": true,
"ransomware_known": true,
"epss_percentile": 0.99
}
]
},
"as_of": "2026-05-28",
"availability": {
"kev": "live",
"epss": "live",
"exploitation_fusion": "live",
"remediation": "live"
}
}
3. Exploitation verdict — the golden block
The exploitability block is the most actionable signal for install decisions. CleanLibrary fuses multiple sources into a single per-CVE verdict:
"exploitability": {
"exploit_maturity": "NONE | POC | FUNCTIONAL | HIGH",
"exploitation_likelihood": "LOW | MEDIUM | HIGH | CRITICAL",
"exploit_risk_score": 0,
"top_cves": [
{
"cve_id": "CVE-2021-44228",
"severity": "CRITICAL",
"exploit_risk_score": 95,
"in_kev": true,
"ransomware_known": true,
"epss_percentile": 0.99
}
]
}
How the fused signals combine
exploit_maturity— derived from the public exploit catalog.NONE= no public exploit.POC= proof-of-concept available.FUNCTIONAL= working exploit code in the wild.HIGH= weaponized exploit, widely distributed.exploitation_likelihood— derived from EPSS + KEV + ransomware-known signals.LOW(< 5% EPSS, not in KEV) →CRITICAL(KEV-listed AND high EPSS AND ransomware-known).exploit_risk_score— 0–100. Computed asEPSS_percentile × 70 + (in_KEV × 30) + (ransomware_known × 10), capped at 100. Stable across releases; you can threshold against it.
Default thresholds
By default, an exploit_risk_score >= 70 on any top-listed CVE triggers DENY. A WARN is emitted on 40 <= score < 70. Below 40 returns ALLOW (subject to other axes — see §2 verdict envelope).
You can override these thresholds in your CleanLibrary policy (contact your CleanStart account team for policy authoring).
4. EPSS and KEV signals
EPSS — Exploit Prediction Scoring System
EPSS is a maintained probability score (0–1) that a CVE will be exploited in the wild within the next 30 days. CleanLibrary surfaces both the raw probability and its percentile rank.
epss_score: raw probability (e.g.0.92)epss_percentile: rank among all CVEs (e.g.0.99= top 1%)
EPSS is recomputed daily by FIRST.org. Our availability.epss flag indicates how recent our copy is.
KEV — CISA Known-Exploited Vulnerabilities
KEV is the U.S. Cybersecurity & Infrastructure Security Agency's authoritative catalog of vulnerabilities known to be actively exploited. Inclusion in KEV is a strong "patch now" signal:
in_kev: boolean — is this CVE in the KEV catalog?kev_date_added: when CISA added itkev_due_date: federal-civilian patch deadline (informational for non-federal users; still a sharp signal)
When the freshness flag goes stale
The availability block tracks each substrate independently. If your envelope shows availability.epss = "degraded_stale", EPSS data is more than 48 hours old (typically because a downstream feed is degraded). The verdict will still be returned, with reason_code = VERDICT_DEGRADED_STALE — see §7 for handling.
5. Remediation blocks
The remediation object carries up to seven sparse blocks that describe how to fix a DENY or WARN. Each block is present only when CleanLibrary has substrate data to populate it.
| Block | What it tells you |
|---|---|
fix | The recommended next version that resolves the verdict. Includes target version, SemVer-distance, and whether it's a minor or major upgrade. |
upstream_lag | How long the safe version has been available upstream. High lag → more confidence the fix is stable. |
blast_radius | What in your codebase will likely change when you upgrade. Estimated from public API surface diffs. |
fix_trust | A confidence score on the fix itself — derived from upstream adoption + reproducible build signals + author reputation. |
deadline | Where applicable (e.g. KEV-listed), the patch deadline. |
reachability | Where reachability analysis is available, whether the vulnerable code path is reachable from your dependency graph. |
recommended_version | The structured upgrade target — includes version, source, detected_at, and total_versions available. |
Sparse-by-design (restated). Absence of a block means "no substrate data," not "no risk." Always read availability alongside remediation to know whether a missing block reflects a gap in upstream data or a deliberate omission.
6. What to do with each verdict status
| Status | UI cue | Recommended action |
|---|---|---|
ALLOW | green | Proceed with the install. The library is currently judged safe under default thresholds. |
WARN | yellow | Review the remediation block. Decide whether to upgrade now, schedule the upgrade, or accept the risk with a documented justification. |
DENY | red | Block the install by default. Override only with a documented justification (your CleanLibrary policy can require sign-off for overrides). |
In CI / pre-install-gate use, exit codes map to the status:
0→ALLOW1→WARN(configurable: by default warns; can be made fatal via--warn-as-error)2→DENY(fatal)
In editor surfaces (VS Code, Cursor), the verdict appears as an inline diagnostic with the status color. Hover for the full envelope; Cmd/Ctrl+. for one-click remediation actions.
Example CI pre-install gate
A minimal CI snippet that blocks the build on DENY, surfaces WARN to the log but proceeds, and lets ALLOW through silently:
#!/usr/bin/env bash
set -euo pipefail
# Authenticate (cleanlib stores the bearer in the OS keyring on first login;
# in CI, set CLEANLIB_ENRICH_BEARER from your secrets manager instead).
export CLEANLIB_ENRICH_BEARER="${CLEANLIB_ENRICH_BEARER:-$(your-secrets-fetch)}"
# Run the gate. Exit codes: 0 = ALLOW, 1 = WARN, 2 = DENY.
if ! cleanlib check npm "${PACKAGE_NAME}@${PACKAGE_VERSION}"; then
rc=$?
if [ "$rc" -eq 2 ]; then
echo "❌ CleanLibrary returned DENY — blocking install."
exit 1
elif [ "$rc" -eq 1 ]; then
echo "⚠️ CleanLibrary returned WARN — review the remediation block, proceeding."
fi
fi
npm install "${PACKAGE_NAME}@${PACKAGE_VERSION}"
For tighter gates, pass --warn-as-error to make WARN fatal too.
7. Freshness contract
CleanLibrary's verdict envelope is computed from multiple upstream sources (CVE feeds, KEV catalog, EPSS scores, package registries, repository health signals). Each source has its own update cadence and its own failure modes. Rather than blocking on the slowest source, CleanLibrary returns the best available answer and tells you what's stale.
The availability block
"availability": {
"kev": "live",
"epss": "degraded_stale",
"exploitation_fusion": "live",
"remediation": "live"
}
Three states:
| State | Meaning |
|---|---|
live | This substrate is fresh (within its expected update cadence). |
degraded_stale | This substrate is older than its freshness threshold but still usable. Treat the result as a reasonable approximation. |
unavailable | No data for this substrate. Fields derived from it will be absent from rich_data / remediation. |
When reason_code is VERDICT_DEGRADED_STALE
If any substrate goes stale, the envelope's status is unchanged (the fused signal still produces a meaningful verdict), but the reason_code is set to VERDICT_DEGRADED_STALE. This is your signal that you may want to retry shortly, accept a slightly older answer, or fall back to a cached result.
The freshness override is a precedence rule: status follows the underlying signals; reason_code is replaced by VERDICT_DEGRADED_STALE whenever any consumed substrate is in degraded_stale state. This way, you can branch on reason_code for staleness handling without changing your verdict-driven control flow.
Client-side connection status is separate
Your editor / CLI / SDK also tracks connection state independently — whether it can reach the CleanLibrary backend at all. When the backend is unreachable, the client surface (status bar, exit code, error type) shows a connection-degraded indicator. This is a different signal from VERDICT_DEGRADED_STALE — connection-degraded means "I can't reach the backend"; VERDICT_DEGRADED_STALE means "I reached the backend, and one of its upstream sources is older than its freshness threshold."
8. Pre-built integrations
The verdict envelope shows up in every CleanLibrary integration. Choose the surface that fits your workflow:
- VS Code / Cursor extension — inline diagnostics, hover detail, one-click remediation actions.
- MCP server for Claude Code and Claude Desktop — query verdicts from your AI agent's tool surface.
cleanlib-cli— terminal pre-install gate; wrapsnpm/pip/cargo/go.- SDKs for JavaScript/TypeScript, Python, and Go — embed verdict checks in your own tools.
See Integrations for the per-surface setup.
License: CleanStart commercial · Author: CleanStart Inc.