Rebuild Impact
Get rebuild blast radius estimates for tracked packages with open CVEs. Shows how many packages would need rebuilding when a vulnerable package is patched.
Endpoints
GET /api/v1/rebuild-impact
GET /api/v1/rebuild-impact/:nameThe set covers every package currently named in an open nixpkgs security issue, not a fixed list: a package with no open issue right now, however foundational, has no entry. Asking for one answers 200 with data: null, found: false, reason: "package_not_tracked" -- this says nothing about how many packages depend on it, only that it has no open issue to compute a rebuild estimate for. The dataset being unavailable at all (the computation has never run, say) is a separate case, answered 503, so a caller can tell the two apart.
Response (All Packages)
{
"success": true,
"data": {
"packages": {
"openssl": {
"rdeps": 15000,
"tier": "critical",
"category": "crypto",
"impactScore": 62,
"riskScore": 85,
"cveCount": 3,
"cves": ["CVE-2025-1234", "CVE-2025-1235", "CVE-2025-1236"],
"maxSeverity": "high",
"maxEpss": 0.42,
"issueCount": 2,
"source": "curated"
}
},
"totalPackages": 30,
"summary": {
"foundation": 1,
"critical": 5,
"high": 10,
"medium": 8,
"low": 6
},
"topRisk": [
{
"package": "openssl",
"riskScore": 85,
"tier": "critical",
"rdeps": 15000,
"cveCount": 3,
"maxSeverity": "high"
}
],
"lastUpdated": "2026-02-10T12:00:00.000Z"
},
"timestamp": "2026-02-10T12:00:00.000Z"
}Response Fields
Per-package Data
| Field | Type | Description |
|---|---|---|
rdeps | number|null | Reverse dependency count |
tier | string | Impact tier: foundation, critical, high, medium, low, unknown |
category | string | Package category (crypto, compiler, library, etc.) |
impactScore | number|null | Impact score 0-100 (log-scaled from rdeps + tier bonus); null when the package can't be placed in a tier |
riskScore | number|null | Combined risk 0-100 (impact × severity × exploitability); null whenever impactScore is null (tier unknown) rather than being computed as 0 -- an unmeasured package is not the same claim as a measured, genuinely risk-free one |
cveCount | number | Open CVEs for this package |
cves | array | Up to 10 CVE IDs |
maxSeverity | string | Highest severity among open CVEs |
maxEpss | number|null | Highest EPSS score among open CVEs |
source | string | Data source: curated, issue_body, issue_body_heuristic, issue_body_staging, graph, default |
Impact Tiers
| Tier | Rdeps Range | Description |
|---|---|---|
foundation | 20,000+ | Patching rebuilds nearly everything (glibc, gcc) |
critical | 5,000+ | Major rebuild impact (openssl, python, curl) |
high | 1,000+ | Significant rebuild (rust, nodejs, qt5) |
medium | 100+ | Moderate rebuild (nginx, ffmpeg, git) |
low | < 100 | Minimal rebuild impact |
unknown | n/a | No reverse-dependency count could be placed for this package. impactScore is null here, distinct from the single-package lookup's own found: false for a package with no open issue to track at all |
Risk Score
The riskScore combines three factors:
riskScore = impactScore × severityWeight × exploitMultiplier / 4- Severity weight: critical=4, high=3, medium=2, low=1
- Exploit multiplier: EPSS ≥ 0.5 → 2×, EPSS ≥ 0.1 → 1.5×, else 1×
Single Package
curl https://api.vulnpatch.dev/api/v1/rebuild-impact/openssl{
"success": true,
"data": null,
"found": false,
"reason": "package_not_tracked",
"timestamp": "2026-02-10T12:00:00.000Z"
}| Field | Meaning |
|---|---|
found | true when the package has an open issue this dataset tracked; data carries the same per-package shape documented above |
reason | Present only when found is false: package_not_tracked, the routine case for a package with no open issue right now |
A dataset that could not be read at all (the computation has never completed a run) answers 503 with success: false, rather than 200 with the same found: false shape as a package that simply has no open issue.
Example
# All packages
curl https://api.vulnpatch.dev/api/v1/rebuild-impact
# Single package
curl https://api.vulnpatch.dev/api/v1/rebuild-impact/opensslCode Examples
async function getHighImpactVulns() {
const response = await fetch('https://api.vulnpatch.dev/api/v1/rebuild-impact');
const { data } = await response.json();
// Top risk packages
console.log('Top risk packages:');
data.topRisk.forEach(pkg => {
console.log(` ${pkg.package}: risk=${pkg.riskScore}, tier=${pkg.tier}, rdeps=${pkg.rdeps}`);
});
// Foundation-tier packages (patch carefully!)
const foundation = Object.entries(data.packages)
.filter(([, p]) => p.tier === 'foundation');
console.log(`\nFoundation packages with open CVEs: ${foundation.length}`);
}import requests
response = requests.get("https://api.vulnpatch.dev/api/v1/rebuild-impact")
data = response.json()["data"]
print(f"Tier summary: {data['summary']}")
print(f"\nTop 5 risk packages:")
for pkg in data["topRisk"][:5]:
print(f" {pkg['package']}: risk={pkg['riskScore']}, "
f"rdeps={pkg['rdeps']}, CVEs={pkg['cveCount']}")Data Sources
Impact estimates come from multiple sources (in priority order):
- Curated data - Hand-maintained reverse dependency counts for ~60 core packages
- Issue body - Parsed from rebuild counts mentioned in issue descriptions
- Neo4j graph - Computed from the dependency graph (when available)
- Default - Fallback estimate for unknown packages
Use Cases
- Patch coordination: Plan rebuild schedules for high-impact packages
- Risk prioritization: Focus on CVEs with the largest blast radius
- Communication: Explain rebuild impact to stakeholders
- Resource planning: Estimate Hydra build time for security updates
Caching
Data is computed every 30 minutes via cron.
Related Endpoints
GET /api/v1/fix-etas- Predicted fix timelinesGET /api/v1/package-health- Package maintenance healthGET /api/v1/exploitability- EPSS + KEV data