Security Guides

Automating vulnerability monitoring for your own stack: match on the components you actually use

Build a vulnerability watch that flags only what affects you: an SBOM from lockfiles and OS packages, KEV and EPSS for priority, and AI that only raises urgency

Published 2026-11-01 Updated 2026-11-01 Last verified 2026-11-01 8 min read
On this page

For: anyone who runs their own sites or services and wants vulnerability information picked up without a person watching feeds. This article covers what to collect, what to match it against, and how far to trust AI.

What happened: a human knew first, three times in a row

Within one week, on sites that this site's operator runs, three things happened. In every case the operator learned of it first, via social media or email, and the automated watch had reported nothing at that point.

  1. Case 1

    A PHP vulnerability. The operator learned of it first. The automated watch had not flagged it.
  2. Case 2

    Malicious code inserted into a Python package. The operator learned of it first. The automated watch had not flagged it.
  3. Case 3

    A container base image issue. The operator learned of it first. The automated watch had not flagged it.

The first suspicion was "not enough sources." There was no single cause: official sources can lag behind what is trending (more below), and there was also not enough material to decide that an item concerns our setup. Words like "PHP" or "Python" appear in news text, but that is a different thing from the names of the packages you actually run.

The rebuilt watch

1. Collect

Official advisories / GitHub advisories / malicious-package lists / KEV / news / social media

↓

List A: technology words we use

Wide net

List B: actual component names

Generated from lockfiles and OS packages

↓

2. Rules pick up matches (work without AI)

↓

3. A cheap AI model does first-pass triage

It may raise urgency. It may not lower it.

Collect, match against two lists, pick up with rules, then AI that can only raise urgency. The rule path keeps running on days the AI is unavailable.
  • What it collects: official advisories, GitHub advisories, malicious-package lists, CISA's KEV, news and social media.
  • Two lists to match against: technology words for a wide net, and actual component names for high-confidence matches. The component list is built from the lockfiles of every repository plus the OS packages.
  • Whole-image scanning: it checks the entire image including the base image, not only application dependencies.
  • Runtime lag: it measures how far runtimes such as Node, PHP and the database are behind their latest versions.
  • AI first pass: a cheap AI model makes the first call on "does this affect us?". The AI can only raise urgency.

What the measurements showed, including what went against expectations

First assumption: official sources are enough

We assumed that watching official advisories and KEV would catch what matters. In practice, a topic can start trending before the advisory is published. Official sources alone lose that race.

After measuring: add social media as an entry point

Adding social media let the watch notice things earlier than official sources alone. But social media content is not treated as fact until an official source confirms it. Wide at the entrance, careful at the decision.

About 100
critical vulnerabilities collected over 10 days by a separate article-candidate watch
0
of those that affected the operator's sites and were missed by this watch
About 6 days
how long AI triage paused after the AI quota ran out (rule matching continued)
  1. Checking for misses: about 100 critical vulnerabilities gathered over 10 days by a separate watch (built to find article candidates) were cross-checked against this watch. Misses among those that affected the operator's sites: 0.
  2. AI quota exhausted: the monthly quota ran out and AI triage paused for about 6 days. The rule matching that does not use AI kept running throughout. The design sets a pause end date in advance, and the AI part resumes automatically from that date.
  3. A gap for a new server: the OS packages of a newly added server were missing from the component list. The monthly rebuild of the list found it. A list is trustworthy only if it is regenerated regularly, not just built once.

How to build this for your own environment

1

Generate the component list (SBOM) mechanically

Build it from both the lockfiles of every repository and the OS packages of your servers and containers. CISA describes an SBOM as a nested inventory, a list of ingredients that make up software components. SBOM generators such as the open-source Syft read OS packages and the dependencies of major languages from container images and filesystems and can output CycloneDX or SPDX.

2

Match the list against known vulnerabilities

For dependency matching, the open-source osv-scanner reads lockfiles and containers. Setup and CI integration are covered in osv-scanner: setup and use.

3

Prioritize with KEV and EPSS

When there are many findings you cannot fix them all with equal urgency. Start with what is confirmed exploited (KEV) and what has a high predicted probability of exploitation (EPSS). How to combine them is in CVSS, EPSS and KEV: how to use them together.

4

If you use AI, use it only to raise

Even if the AI says "not affected", do not remove an item a rule picked up. AI can wrongly say "unrelated", and the cost of a miss is larger than the cost of a false alarm.

5

Decide what happens when AI is unavailable

Quotas run out, services fail and providers stop. Decide before operating that the non-AI rules alone still send a minimum set of notifications, and that you set a resume date so the AI part returns automatically.

6

Regenerate the list regularly

Gaps happen when a server or repository is added but the list is not updated. Rebuild it at least monthly and check that what you added is in it.

Do not treat social media as fact until an official source confirms it

Social media is fast, but it mixes in errors and speculation that the vendor has not confirmed. Use it as an entry point, but base your response on verifiable primary sources such as the vendor's advisory or KEV.

This site's view: cast a wide net on technology words, narrow it with component names

In the operator's experience, switching to matching on actual component names reduced both noise hits and misses. But if the component list is stale, it leads directly to misses. You need both: a wide net and an accurate list to narrow it. This article describes the watch built for the sites the operator runs.

Sources (primary and official)

FAQ

QWhat should an automated vulnerability watch collect from?
A

Start with official vendor advisories, CISA's KEV catalog, package-ecosystem advisory databases and lists of malicious packages. Official sources can lag behind what is trending, though. The watch built for the sites this site's operator runs lost the race between a topic trending and the advisory being published, so social media was added as a supplementary entry point. Anything from social media is not treated as fact until an official source confirms it.

QHow do I build the list of components I use (an SBOM)?
A

Build it from both the lockfiles of every repository (package-lock.json, pnpm-lock.yaml and so on) and the OS packages of your servers and containers. Application dependencies alone miss the OS and base-image layer. SBOM generators such as the open-source Syft read OS packages and the dependencies of major languages from container images and filesystems and can output CycloneDX or SPDX.

QIs it safe to let AI decide whether an item affects us?
A

It is, if you restrict the direction. In the operator's setup the AI can only raise urgency; it never lowers an item that a rule has already picked up. AI can wrongly say 'not affected', and the cost of a miss is larger than the cost of a false alarm.

QWhat happens to the watch on days when the AI quota is exhausted?
A

It should keep running. In the operator's watch, the monthly AI quota ran out and AI triage paused for about 6 days, while the rule-based matching without AI kept running throughout. If you set a resume date in advance, the AI part comes back automatically on that date.