Self-hosted service
Ostorlab/KEV avatar
Ostorlab/KEV

Ostorlab KEV turns a CVE list into a one command exposure check

Ostorlab KEV: One-command to detect most remotely known exploitable vulnerabilities. Sourced from CISA KEV, Google's Tsunami, Ostorlab's Asteroid and Bug Bounty programs.

620 stars40 forksUnknownApache-2.0

At a glance

What is it?
The Ostorlab KEV repository is an agent group definition, a YAML file listing which scanners to run, that wires CISA's Known Exploited Vulnerabilities catalog, Google's Tsunami scanner, Ostorlab's own Asteroid agent and the usual tooling into a single ostorlab scan run command. Its own coverage table is as useful as the tool, because it records which known exploited vulnerabilities it can and cannot detect.
Who is it for?
Adopt Ostorlab KEV if you want a repeatable check for known exploited vulnerabilities against assets you own, and you can live with the fact that it is a configuration bundle over agents you would otherwise install and tune yourself. Do not adopt it as a complete exposure programme, because the coverage table shows most entries it tracks are not detected, and some are undetectable by design, and do not run it against assets you do not own.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 23 days ago.
What is it written in?
GitHub does not report a main language for this repository.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It is a config file that names five agents

The first thing to understand about Ostorlab KEV is that it is not a scanner. The README says it plainly: this repo is an Agent Group Definition of the open-source ostorlab scanner, and an agent group is nothing but a config file that defines the list of components to run during the scan.

So the repository contains agent_group.yaml, a nuclei/ directory holding the templates, an images/ directory, a CONTRIBUTING.md, a LICENSE and the README. The scanning work is done by ostorlab, which is installed as a Python package, and by the individual agents the group names.

The default group uses five agents: Agent Nuclei, Agent Tsunami, Agent Nmap, Agent Asteroid and Agent Metasploit. Each brings a different detection approach, which is the point of bundling them. Nuclei runs the template checks, Tsunami is Google's scanner for remotely exploitable vulnerabilities, Nmap covers service and version discovery so the other agents know what they are looking at, Asteroid is Ostorlab's own agent, and Metasploit brings module based checks.

The project is dedicated to automating the detection of known exploited vulnerabilities through a single command, with the sources being the CISA Known Exploited Vulnerabilities Catalog, Google's Tsunami, Ostorlab's Agent Asteroid and the Bug Bounty programs. The licence is Apache-2.0, the default branch is main, there are no GitHub releases, and the last push was on 2026-10-01.

The audience is a security team that has to answer a specific question quickly: is this host or domain exposed to a flaw that is already being exploited in the wild?

Installing the scanner and pointing it at a target

Two requirements are stated. Python 3.9 or greater is needed to install KEV via pip, and Docker is required to run scans locally, because the agents themselves run as containers.

The install is one command:

shell
pip install -U ostorlab

Then you run a scan with the group definition. For an IP address:

shell
ostorlab scan run --install -g agent_group.yaml ip 8.8.8.8

Several addresses can be given at once, separated by spaces, and a CIDR range works too:

shell
ostorlab scan run --install -g agent_group.yaml ip 8.8.8.8 1.1.1.1 4.4.4.0/24

For a domain:

shell
ostorlab scan run --install -g agent_group.yaml domain-name www.example.com

and for a link, where you also give the HTTP method:

shell
ostorlab scan run --install -g agent_group.yaml link --url https://www.example.com --method GET

The --install flag is the part that matters for a first run. It downloads and installs the agents named in the YAML file, which is why the README describes these commands as downloading and installing the required agents specified in the YAML file and then performing the scan.

The commands in the README are all aimed at 8.8.8.8, 1.1.1.1 and www.example.com, which is a good indication of the intent: these are examples against infrastructure you are entitled to test, not targets.

Subdomain enumeration widens the scope, and adds its own caveats

The scope of a domain scan can be widened by adding subdomain enumeration agents to the group definition. The README describes adding subfinder and/or dnsx to the agent_group.yaml file:

yaml
agent:
  ...
  - key: agent/ostorlab/subfinder
  - key: agent/ostorlab/dnsx
  ...

and then running the same kind of command against the domain:

shell
ostorlab scan run --install -g agent_group.yaml domain-name example.com

The tip that follows is the useful part. The default settings use public DNS servers, which can affect enumeration results for very large domains because of rate limiting and caching, so the README suggests using a custom list of DNS resolvers, set through resolver arguments in the Amass and Subfinder agents.

That is a real operational point rather than a footnote. On a domain with thousands of subdomains, a scan against public resolvers will find a different set of hosts than the same scan against your own resolvers, and a difference in findings that nobody can explain is a bad afternoon.

It also changes the risk profile. Enumeration multiplies the number of hosts the agents will touch, and the agents in this group are not all passive, so the wider the scope, the more traffic the target sees.

The container image and the socket mount it requires

There is a containerised route, using the publicly available oxo image:

shell
docker run -v /var/run/docker.sock:/var/run/docker.sock -v ./agent_group.yaml:/agent_group.yaml  ostorlab/oxo:latest scan run --install -g /agent_group.yaml link --url https://www.example.com --method GET

The two notes under it explain the shape of the command. It starts directly with scan run because the ostorlab/oxo image has oxo as its entrypoint, so the container's own entrypoint supplies the tool name.

The second note is the one to pay attention to: it is important to mount the docker socket so oxo can create the agent in the host machine. In other words, the container is not sandboxing the agents, it is using the host's Docker daemon to launch sibling containers that do the actual scanning. The agent_group.yaml file is mounted too, so the same group definition drives the run.

That design is what makes the local scan work with a single command, and it is also the reason to think about where you run it. The socket mount grants effective control of the host Docker daemon to the container, so the security of that machine becomes part of your threat model for the scan.

Reading the results after the scan finishes

Three commands cover the reporting side, and the README gives all of them.

Progress is visible with the scan list command:

shell
ostorlab scan list

Findings for a particular scan are listed with vulnz list and a scan id:

shell
ostorlab vulnz list -s <scan-id>

and the detail of a single finding is shown with vulnz describe and a vulnerability id:

shell
ostorlab vulnz describe -v <vuln-id>

The naming is a little awkward to read at first, since vulnz is a two-part word that looks like a typo, but the flow is straightforward: list the scans, pick the id of the one you want, list its findings, then describe the finding that concerns you.

Because the group includes several agents, a finding in the list can come from any of them, and the describe command is where you find out which detector fired and what it actually saw. For a KEV oriented workflow, that distinction matters: a template match on a version string is a weaker signal than a template that confirms exploitation, and the output format is what tells the two apart.

The coverage table admits what it cannot detect

The most valuable part of this repository is the coverage table at the end of the README, because it is a candid accounting of a detector's blind spots.

The legend explains the symbols: a check mark means detected by this agent group, a cross means not detected with the Detail column giving the reason, and a clock means in progress. The visible rows show a mix. CVE-2026-94127, CVE-2026-93952 and CVE-2026-93616, all published on 2026-09-22, are marked as not detected because no public Nuclei template is available. CVE-2026-87902 from the same day is detected, via an official Nuclei template. And CVE-2026-87886 from 2026-09-17 is not detected because it is a local attack vector, which is to say it is a vulnerability that cannot be found by scanning a remote host at all.

Two more exclusions are explained. Templates tagged intrusive modify the target, for example by uploading a file or creating an account, and new ones are not accepted, so those rows read Template modifies the target (intrusive). And templates that use interactsh confirm exploitation only when the target can reach the out-of-band callback server, which means a detection can be inconclusive purely because of network rules on your side.

The project also states where its focus is: for the moment it is focused on the CISA KEV database and Google Tsunami.

That focus has a cost. The most recent exploited vulnerability in your estate is the one most likely to be published with a template, and the lag between an exploit appearing in the wild and a template existing is where the exposure window lives.

Contributing detectors, and what this is not

Contributions are welcome, and the README is specific about what is wanted: new detectors for recently exploited vulnerabilities, with the process for adding and testing a detector in CONTRIBUTING.md.

The constraint from the coverage table carries into that process, because intrusive templates are not accepted. A detector that uploads a file or creates an account to prove a vulnerability is exactly the kind of check a scanner running against production would do most damage with, and the project has decided the value of a detection does not justify the side effects.

There is a limit to what any of this replaces. A KEV check answers whether known exploited flaws are present and reachable. It does not tell you about the vulnerability that has not been catalogued yet, about misconfiguration, about weak credentials, or about the missing patch that has no CVE. The Nmap agent contributes service and version discovery, which is a prerequisite for the template checks rather than a finding in itself.

The other boundary is authorisation. Every command in the README targets hosts and domains, and the project is built to run agents that actively probe. Running it against infrastructure you do not own is not a use case the documentation supports, and the intrusive template policy is a reminder that the tool's designers thought about what a scanner should not do to a target.

So the sensible framing is this. Ostorlab KEV is a packaging convenience and a shared configuration with an unusually honest coverage report. If your team already uses ostorlab, adopting this group is a way to get a broad known-exploitation check in one command, and the coverage table tells you which parts of the KEV catalog that check will actually cover.

Editorial conclusion

Adopt Ostorlab KEV if you want a repeatable check for known exploited vulnerabilities against assets you own, and you can live with the fact that it is a configuration bundle over agents you would otherwise install and tune yourself. Do not adopt it as a complete exposure programme, because the coverage table shows most entries it tracks are not detected, and some are undetectable by design, and do not run it against assets you do not own. Before you deploy, read the coverage table for the CVEs you care about, remove any intrusive template from the group, and confirm the scan runs inside the network boundary where the affected service is actually exposed.

Frequently asked questions

How do I install Ostorlab KEV?

KEV is an agent group definition rather than a package of its own, so you install the scanner with `pip install -U ostorlab`, which needs Python 3.9 or greater. Docker is required to run the scans locally, because the agents run as containers.

What does the Ostorlab KEV agent group actually run?

By default the agent_group.yaml file lists Agent Nuclei, Agent Tsunami, Agent Nmap, Agent Asteroid and Agent Metasploit. Nuclei and Tsunami carry the vulnerability checks, Nmap provides the service discovery the other agents need, and Asteroid and Metasploit add their own coverage.

Which known exploited vulnerabilities does Ostorlab KEV detect?

The README's coverage table records the answer per CVE. The visible rows show several entries as not detected because no public Nuclei template is available, one detected by an official template, and one that is not detected because it is a local attack vector. The project says its current focus is the CISA KEV database and Google Tsunami.

Why does the Docker command mount /var/run/docker.sock?

The README notes it is important to mount the docker socket so oxo can create the agent in the host machine. The container therefore launches sibling containers through the host's Docker daemon to perform the scan, and the agent_group.yaml file is mounted in the same way.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Ostorlab/KEV on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ostorlab-kev.svg)](https://hysenlabs.com/projects/ostorlab-kev)

Was this useful?