Skip to content

About

Supply-chain blast-radius control — predict CVE reach, not just count.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

BlastGuard

Don't count vulnerabilities. Predict their blast radius.

Discover Trace Decide Enforce Verify

CI Release License Case study OpenSSF Scorecard

Evidence: docs/EVIDENCE.md

Case study: BlastGuard · Andrey Lesnikov

What it does

  • Traces CVE → package → image → workload → exposure into an explainable ALLOW / WARN / QUARANTINE / BLOCK decision
  • Combines SBOM, vuln scanners, runtime reachability, and VEX-oriented inputs into a decision layer
  • Supports what-if rehearsal and before/after remediation proof (make demo, make rehearse, make prove)

Why

  • CVE dashboards count findings; operators need reachability and exposure to prioritize
  • Remediation should prove the critical path is closed, not only that a ticket was filed

Quickstart

make demo
make rehearse
make prove

Architecture

flowchart LR
  Ingest[internal/ingest SBOM/vuln] --> Graph[internal/graph]
  Cluster[internal/cluster runtime] --> Graph
  Graph --> Decide[internal/decide]
  Decide --> CLI[cmd/blastguard]
  CLI --> Out[ALLOW / WARN / QUARANTINE / BLOCK]
  CI[.github/workflows/ci.yml] --> Rel[release.yml]
Loading

Why this exists

Ordinary pipeline:

CVE → scan → 147 findings → dashboard → ticket

BlastGuard:

CVE → Dependency Graph → Runtime Reachability → Exposure → Criticality → Decision → GitOps

Example:

CVE-2026-1234
     │
     ▼
openssl
     │
     ├── payment-api:v41 → prod/payment-api → internet exposed
     ├── report-worker:v4.2 → staging only
     └── ml-builder:v2.1 → not running
┌──────────────────────────────────────────────┐
│  BLASTGUARD                                  │
│  CVE-2026-1234                               │
├──────────────────────────────────────────────┤
│  Affected artifacts       3                  │
│  Running workloads        2                  │
│  Internet exposed         1                  │
│  Reachable                1                  │
│  POLICY                   BLOCK              │
│  Reason                   exploitable CVE +… │
│  FIX                      payment-api:v42    │
└──────────────────────────────────────────────┘

No fake Risk 83/100. Decisions are ALLOW / WARN / QUARANTINE / BLOCK with an explicit reason.


Control loop

Stage What happens
Discover SBOM (Syft/CycloneDX/SPDX), vulns (Grype/Trivy/OSV), optional cosign verify-attestation
Trace CVE → package → image → workload → Service selector → Ingress; reachability ≠ exposure (docs)
Decide Policy over CVSS/EPSS/VEX/runtime/exposure/criticality/fix availability
Enforce CI gate via CLI exit codes (0 ALLOW, 1 WARN with --fail-on warn, 2 BLOCK/QUARANTINE). In-cluster admission (Kyverno / policy-controller) is out of tree — emit decisions into your policy engine
Verify After patch: blast radius → 0 · REMEDIATION PROVED

Quickstart

1. Scan an image and ingest results

syft alpine:3.20 -o cyclonedx-json > alpine-sbom.json
grype alpine:3.20 -o json > alpine-vulns.json

blastguard ingest \
  --sbom-cyclonedx alpine-sbom.json \
  --vulns-grype alpine-vulns.json \
  --output alpine-twin.json

2. Scan live Kubernetes cluster

blastguard ingest --from-cluster --output cluster-twin.json

3. Trace CVE blast radius

blastguard ingest \
  --sbom-cyclonedx alpine-sbom.json \
  --vulns-grype alpine-vulns.json \
  --policy config/decision-policy.json \
  --trace CVE-2026-85091

Output:

┌──────────────────────────────────────────────┐
│  BLASTGUARD                                  │
│  CVE-2026-85091                              │
├──────────────────────────────────────────────┤
│  Package          zlib                       │
│  Severity         HIGH                       │
│  CVSS             8.3                        │
│  EPSS             0.00356                    │
│  Running          yes                        │
│  Internet exposed yes                        │
│  POLICY           ● BLOCK                    │
│  Reason           exploitable CVE on         │
│                   internet-exposed service   │
└──────────────────────────────────────────────┘

4. What-if Security Rehearsal

make demo      # trace CVE-2026-1234 → BLOCK on critical path
make rehearse  # what-if for a CVE
make prove     # before/after remediation evidence
./bin/blastguard rehearse CVE-2026-1234
./bin/blastguard rehearse image ghcr.io/justrunme/payment-api:v42
./bin/blastguard demo CVE-2026-1234 --output json   # exit 2 on BLOCK
./bin/blastguard demo CVE-2026-2345 --fail-on warn  # exit 1 on WARN

Ask before production changes: if this becomes exploitable, what is our blast radius?

Demo workload / fix-image defaults live in config/demo.json and fixtures/ — not in core matching logic.


Vulnerability digital twin

Build-time truth + runtime truth on one graph:

Source → Build → Image → Package → SBOM → Deployment → Pod → Service → Ingress
                 + CVE / VEX / Signature / Provenance / Runtime

SBOM says the package exists.
Kubernetes says it is running.
Ingress says it is exposed.
Reachability says the path is live.
VEX says which copies are not_affected.

147 findings become 1 exploitable path.


Layout

cmd/blastguard/              CLI
internal/decide/             Explainable policy engine
internal/graph/              Digital twin model
config/decision-policy.yaml  BLOCK/WARN rules (no scores)
fixtures/demo-graph.json     Offline twin for demos/CI
api/crds/                    BlastRadius, SecurityDecision, SupplyChainPolicy
docs/assets/                 Lifecycle visual

Integrations (not reimplemented here): Syft, Trivy/Grype, OSV, OpenVEX, Cosign/Sigstore, GUAC, OPA, OpenTelemetry, policy-controller/Kyverno.

BlastGuard owns: control plane, data model, decision engine, rehearsal, evidence.


Philosophy

Project Loop Prove
Architecture Rehearsal Predict → Rehearse → Gate → Verify change safety
TwinOps Declare → Compose → Detect → Reconcile convergence
AI Infra Control Plane Evaluate → Decide → Approve → Verify governance
Kanister Recovery Protect → Validate → Restore → Prove recoverability
BlastGuard Discover → Trace → Decide → Enforce → Verify supply-chain safety

Assumptions → evidence.


Demo

Terminal scan showing SBOM/provenance checks and a BLOCK policy decision for CVE-2026-1234, then before/after remediation prove:

make demo
make prove

Blastguard demo: CVE scan with BLOCK decision and REMEDIATION PROVED

Results

Measured from CI (not estimates). Details: docs/results.md · docs/results.json.

Scenario Workload Decision Source run
Fixture demo CVE-2026-1234 payment path BLOCK 38066443627
Kind e2e CVE-2026-93990 payment-api (exposed) BLOCK same run (e2e-kind)
Kind e2e CVE-2026-93990 internal-worker WARN same run (e2e-kind)
Remediation prove after fix ALLOW / REMEDIATION PROVED same run (ci)

\n## License

Apache-2.0 © Andrey Lesnikov

About

Supply-chain blast-radius control — predict CVE reach, not just count.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages