CVE Intelligence Intake

SecurityRecipes treats CVE intelligence as an intake problem before it treats it as a patching problem. A scanner finding, GHSA entry, NVD row, vendor bulletin, or ticket is a signal. It becomes an agent task only after the signal has enough evidence for a reviewer to trust the resulting PR.

The intake gate is intentionally conservative:

  • no primary source, no remediation task;
  • no affected surface, no remediation task;
  • no fix, mitigation, containment, or suppression path, no remediation task;
  • no reviewer-runnable verification, no remediation task.

Artifacts

  • Prompt: CVE intelligence intake gate
  • Policy: data/intelligence/cve-intelligence-intake-gates.json
  • Regression fixtures: data/intelligence/cve-intelligence-intake-fixtures.json
  • Evaluator: scripts/evaluate_cve_intelligence_intake.py
  • Fixture runner: scripts/test_cve_intelligence_intake_decisions.py
  • CVE recipe hub: CVE Recipes
  • Generic dependency workflow: Vulnerable Dependency Remediation

Decision Model

The policy defines five outcomes:

Decision Use when Output
Accept for remediation A stable ID, affected surface, fix path, ownership, and verification all exist. Remediation packet and selected recipe.
Accept for containment Exposure is plausible or confirmed, but full remediation is blocked. Temporary control and follow-up record.
Suppress as not exposed The vulnerable component is absent, unreachable, dev-only, test-only, or below exploit preconditions. Evidence-backed suppression with expiration.
Stop for triage Sources disagree, evidence is missing, ownership is unclear, or safe verification is impossible. TRIAGE.md.
Reject unverified signal The claim has no stable primary source or affected surface. REJECTED_SIGNAL.md.

Source Order

Use the strongest available source for the decision being made:

  1. Vendor advisory, release note, patch commit, or security bulletin.
  2. GitHub Advisory Database.
  3. CVE record or NVD entry.
  4. OSV, package-registry advisory, or ecosystem feed.
  5. CISA KEV, vendor exploitation notice, incident signal, or trusted threat intelligence feed.

Scanner output is valuable repository evidence, but it should not be the only source for a patch decision. It usually tells the team that a package or image may be present. It rarely proves reachability, safe fixed versions, operational side effects, or whether a mitigation is acceptable.

Known-exploited and threat-intelligence feeds raise priority, but they are not standalone remediation sources. Pair them with a vendor advisory or patch, GitHub Advisory Database entry, CVE/NVD record, OSV entry, or package-registry advisory before accepting remediation, containment, or suppression.

For deterministic checks, a primary-source type is not enough by itself. The packet must include an absolute http or https source URL, or the evaluator routes the signal to triage. The reverse is also true: a primary_source_backed: true flag cannot promote a scanner, ticket, social-media, unknown-source URL, or KEV-only exploitation signal into primary evidence. Remediation, containment, and suppression packets also need a named owner. Containment and suppression packets additionally need a parseable YYYY-MM-DD follow-up date that is not earlier than the packet’s evaluation_date, so temporary decisions do not become permanent or start already overdue. Containment must still name the exact control or configuration change; temporary_control: true is not an actionable path by itself.

The evaluator also returns a source_evidence audit block. It lists the source types that can stand alone, the links that counted as valid primary sources, and the links that were preserved only as auxiliary, invalid, or non-standalone evidence. That distinction matters when a KEV or threat intelligence link raises priority but must still be paired with a vendor, GHSA, CVE/NVD, OSV, or package-registry source before remediation starts.

Operating Loop

  1. Start with one advisory signal and one repository or service scope.
  2. Run the intake prompt and require one of the five output files.
  3. If the decision is remediation, hand the packet to the most specific SecurityRecipes prompt:
    • a named CVE recipe when one exists;
    • vulnerable-dependency remediation for routine package CVEs;
    • base-image remediation for OS-package or container-layer CVEs;
    • artifact quarantine for malicious package compromise.
  4. If the decision is containment, keep the containment small and record the owner, expiration, and follow-up patch path.
  5. If the decision is suppression, bind it to evidence and an expiration date.
  6. If the decision is triage or rejection, do not ask an agent to patch.

Evaluate a Packet

The intake gate has a deterministic evaluator for local smoke checks and CI. Use it after a model or analyst drafts a packet, before a remediation prompt is run.

python3 scripts/evaluate_cve_intelligence_intake.py \
  --packet path/to/intake-packet.json

The evaluator can also read a JSON packet with --packet. The packet should use the review fields from the policy: canonical_id, aliases, source_links, affected_surface, affected_range, repository_evidence, fix_or_containment_path, verification_commands, selected_recipe, owner, evaluation_date, and follow_up_date.

Each primary source in source_links should include both source_type and url. Source types are normalized case-insensitively, but packets should still use the policy values so reviewers can compare them directly.

The JSON output includes valid_primary_source_count and invalid_or_non_standalone_source_count so CI logs can show why a packet was accepted or routed to triage without requiring a reviewer to diff the full normalized output.

Stable identifiers include CVE, GHSA, OSV-family and ecosystem advisory IDs such as PYSEC, RUSTSEC, GO, USN, RHSA, ALAS, and VMSA. The canonical_id must match a supported identifier format exactly; a valid alias does not rescue a malformed canonical ID. A value that only starts with a valid CVE or GHSA prefix is routed to triage until the canonical ID is cleaned up. Continuation dates use YYYY-MM-DD; follow_up_date cannot be earlier than the packet’s evaluation_date.

Regression Fixtures

The fixture file contains packets for each supported routing outcome plus evidence-quality regressions: remediation, ecosystem advisory remediation, ownerless remediation, containment, not-exposed suppression, mixed vendor-plus-KEV source auditing, missing or non-URL source links, incomplete containment evidence, scanner links that claim primary-source backing, KEV-only exploitation signals, temporary-control claims without an actionable path, malformed canonical identifiers, malformed follow-up dates, human triage, stale follow-up dates, and rejected unverified signal. Run the full regression set with:

python3 scripts/test_cve_intelligence_intake_decisions.py

Run one case when changing evaluator logic:

python3 scripts/test_cve_intelligence_intake_decisions.py \
  --case triage_on_source_disagreement

Add a fixture whenever a new rule changes routing behavior. The evaluator is small by design, so examples are the clearest contract for reviewers and future automation runs.

What Reviewers Should Demand

A reviewer should reject a CVE remediation PR that cannot answer:

  • Which primary sources were used?
  • Which exact package, image, framework, route, plugin, runtime, or product component is affected?
  • Which resolved version, commit, image digest, configuration, or runtime path proves exposure?
  • What is the selected fixed version, fixed commit, mitigation, containment, or suppression path?
  • Which command or probe proves the risk is gone or not exposed?
  • What changed beyond the target advisory?

June 2026 Iteration

This iteration adds the intake gate because the CVE recipe catalog has grown large enough that “find a named recipe and patch” is no longer the whole workflow. New advisories need a front door that separates actionable remediation from unverified signals, no-fix advisories, not-exposed findings, and source disagreements.

That keeps the CVE catalog focused on reviewer-ready recipes instead of turning it into a vulnerability database.