/** * `vuln-gate` capability (#626) — the deploy-time gate that closes the * supply-chain loop: scan the SBOM (./vuln-scan.ts) for known CVEs, suppress * the ones VEX says don't matter (./vex.ts), check licenses (./license-policy.ts), * and **throw** on a policy violation so composing it before an apply phase * fails the deploy — the same throw-to-halt mechanism as ./verify.ts and * `policyGate` (../../lint/policy.ts). No new gate plumbing. * * **Beginner-safe default policy:** fail on `severity >= critical AND fixable * AND not VEX-suppressed`; findings at/above the warn severity (default * `high`) that don't reach the fail bar are reported as warnings, not blocked; * license findings are report-only unless `failOnLicense` is set. Everything * is configurable via `chant.config.ts`'s `vulnPolicy` section (see * ../../config.ts `resolveVulnPolicy`). The intent is that a first-timer who * just adds a `vuln-gate` step gets a sensible, non-noisy gate that blocks the * genuinely actionable (critical + fixable) and reports the rest. */ import type { Capability } from "../capability.js"; import type { SbomDocument } from "./sbom-generator.js"; import { type Severity, type VulnFinding, type VulnScanner } from "./vuln-scan.js"; import { type SuppressedFinding } from "./vex.js"; import { type LicensePolicy, type LicenseViolation } from "./license-policy.js"; /** The gate's policy. Defaults (per `resolveVulnPolicy`, ../../config.ts) are beginner-safe: fail critical+fixable, warn high, license report-only. */ export interface VulnPolicy { /** Minimum severity that FAILS the gate. Default `"critical"`. */ failSeverity: Severity; /** When true (default), only *fixable* findings at/above `failSeverity` fail the gate — an unfixable finding can't be actioned by upgrading, so it warns instead of blocking. */ fixableOnly: boolean; /** Minimum severity reported as a warning (below `failSeverity`). Default `"high"`. */ warnSeverity: Severity; /** License allow/deny policy. Evaluated always; only *blocks* when `failOnLicense` is true. */ license?: LicensePolicy; /** Block the deploy on a license violation. Default `false` (report-only) — license posture is context-dependent. */ failOnLicense: boolean; /** Block on an `unknown`-severity finding (a scanner that didn't report a severity chant could map). Default `false` — but such a finding is ALWAYS at least warned, never silently dropped, regardless of this flag. Set true for a strict shop that won't ship an unclassifiable finding. */ failOnUnknownSeverity: boolean; /** Block any finding in the CISA KEV catalog, regardless of severity. Default `false` — see epic #1461's open decision before flipping. */ failOnKev: boolean; /** Block when EPSS is at or above this (0.0–1.0). Omit to ignore EPSS entirely. */ failEpssAtOrAbove?: number; /** Warn (not block) at or above this EPSS. Omit to ignore. */ warnEpssAtOrAbove?: number; /** Apply `fixableOnly` to exploitability blocks too — an unfixable KEV finding warns rather than blocks. Default `true`. */ exploitabilityFixableOnly: boolean; } /** Beginner-safe defaults, also encoded in `resolveVulnPolicy` (../../config.ts). */ export declare const DEFAULT_VULN_POLICY: VulnPolicy; export interface VulnGateInput { /** The artifact's SBOM. Scanned in-place unless `findings` is supplied. */ sbom: SbomDocument; /** Pre-scanned findings (e.g. from a prior `scan-vulnerabilities` step). If omitted, the gate scans `sbom` itself via the injected scanner. */ findings?: VulnFinding[]; /** VEX documents (OpenVEX or CycloneDX-embedded), as serialized JSON, applied to suppress findings. */ vex?: string[]; /** Policy override; merged over `DEFAULT_VULN_POLICY`. */ policy?: Partial; /** Artifact digest, for reporting. */ digest?: string; } /** A finding that fails the gate, with why. */ export interface BlockingFinding { finding: VulnFinding; reason: "severity-threshold" | "unknown-severity" | "kev" | "epss-threshold"; } export interface VulnGateOutput { /** Always `true` when returned — a violation throws instead (mirrors ./verify.ts's `verified`). */ passed: true; /** Findings at/above `warnSeverity` that did not reach the fail bar. */ warnings: VulnFinding[]; /** Findings suppressed by VEX, with justification (never silently dropped). */ suppressed: SuppressedFinding[]; /** License findings — reported even when `failOnLicense` is false. */ licenseFindings: LicenseViolation[]; } /** * Thrown when the gate blocks a deploy — carries the blocking findings and any * blocking license violations so a reviewer sees exactly what to fix (or VEX). * Distinct from a scanner-not-installed error (`VulnScannerNotImplementedError`/ * `ToolNotAvailableError`) so a caller can tell "policy said no" from "no * scanner." */ export declare class VulnGateFailedError extends Error { readonly blocking: BlockingFinding[]; readonly blockingLicenses: LicenseViolation[]; constructor(blocking: BlockingFinding[], blockingLicenses: LicenseViolation[]); } /** * Build the `vuln-gate` capability. Scans `sbom` (or uses supplied `findings`), * applies VEX, evaluates the license policy, and classifies every gating * finding: it BLOCKS (throws `VulnGateFailedError`) any finding at/above * `failSeverity` that satisfies `fixableOnly`, any KEV finding when * `failOnKev`, any finding at/above `failEpssAtOrAbove` (exploitability * blocks honor `exploitabilityFixableOnly`), plus license violations when * `failOnLicense`; everything at/above `warnSeverity` below the fail bar is a * warning, as are exploitability hits kept from blocking only by fixability * and findings at/above `warnEpssAtOrAbove`. On a clean pass it returns the * warnings/suppressed/license report for logging. */ export declare function createVulnGateCapability(scanner?: VulnScanner): Capability; /** Default `vuln-gate` capability (inject a real/mock scanner, or supply `findings`). */ export declare const vulnGateCapability: Capability; //# sourceMappingURL=vuln-gate.d.ts.map