Metadata-Version: 2.4
Name: cvehound
Version: 1.5.0
Summary: A tool to check linux kernel source dump for known CVEs
Author-email: Denis Efremov <efremov@linux.com>
License: GPLv3
Project-URL: Homepage, http://github.com/evdenis/cvehound
Keywords: cve,linux,kernel,spatch,cve-scanning,coccinelle
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: sympy
Requires-Dist: pyyaml
Provides-Extra: spatch
Requires-Dist: cvehound-spatch>=1.3.2; (sys_platform == "linux" and platform_machine in "x86_64 aarch64") and extra == "spatch"
Dynamic: license-file

[![GitHub Actions status](https://github.com/evdenis/cvehound/workflows/test/badge.svg)](https://github.com/evdenis/cvehound/actions?query=workflow%3Atest)
[![Supported Versions of Python](https://img.shields.io/pypi/pyversions/cvehound.svg)](https://pypi.org/project/cvehound)
[![PyPI package version](https://img.shields.io/pypi/v/cvehound.svg)](https://pypi.org/project/cvehound)

# CVEhound

CVEhound is a tool for checking Linux sources for known CVEs.
The tool is based on [coccinelle](https://coccinelle.gitlabpages.inria.fr/website/)
rules and grep patterns. The tool checks sources for vulnerable
code patterns of known CVEs and missing fixes for them.

- **What:** The tool tries to find "unfixed" code of known CVEs;
- **How:** The tool uses [coccinelle/grep](cvehound/cve) rules with patterns that helps to detect known CVE bugs or their fixes. Thus, sources are checked either for a presence of "unfixed" code pieces (e.g. [CVE-2020-12912](cvehound/cve/CVE-2020-12912.cocci)), or for an absence of a fix (e.g. [CVE-2020-26088](cvehound/cve/CVE-2020-26088.cocci));
- **Why:** If you have a git log then it's easier to check what CVEs are fixed based on a git history. However, many vendors (samsung, huawei, various iot, routers manufacturers) publish kernel sources as archives without a development log. In most cases their kernels are based on LTS kernels, but versions are far from upstream. Linux version string from Makefile will only give you information about what CVEs were fixed by kernel developers up to this version. It will not help you to understand what fixes were backported by a vendor itself. In this case it's possible to apply the tool and check "missing" CVE fixes.

### CVEHound: Audit Kernel Sources for Missing CVE Fixes

[Linux Security Summit 2021 Presentation (EN)](docs/LSS2021_CVEhound_en.pdf)

<p align="center">
  <a href="https://www.youtube.com/watch?v=jIDnVeZNUA8">
    <img src="https://img.youtube.com/vi/jIDnVeZNUA8/0.jpg" alt="Linux Security Summit 2021 Presentation"/>
  </a>
</p>

[ZeroNights 2021 Presentation (RU)](docs/ZN2021_CVEhound_ru.pdf)

<p align="center">
  <a href="https://www.youtube.com/watch?v=-QwLkpYzQIk">
    <img src="https://img.youtube.com/vi/-QwLkpYzQIk/0.jpg" alt="ZeroNights 2021 Presentation"/>
  </a>
</p>

### Found issues in stable trees

 - CVE-2020-27825 fix [missing backports](https://lkml.org/lkml/2021/1/21/1278) for [5.4, 4.19, 4.14, 4.9, 4.4 kernels](https://www.spinics.net/lists/stable/msg440412.html)
 - CVE-2021-4149 fix [missing backports](https://lore.kernel.org/stable/d1a3f31f-2205-6dce-0f33-6611972e48cd@gmx.com/T/#t) to [4.19, 4.14, 4.9 kernels](https://lore.kernel.org/stable/20220309064748.160978-1-denis.e.efremov@oracle.com/)
 - CVE-2022-26490 fix [missing backports](https://lore.kernel.org/all/20220321174006.47972-1-denis.e.efremov@oracle.com/)
 - CVE-2023-1989 fix missing backports for [6.1, 5.15, 5.10, 5.4, 4.19, 4.14 kernels](https://lore.kernel.org/stable/20230902102200.24474-1-efremov@linux.com/)
 - Similar to CVE-2021-28660 [fix in r8188eu driver](https://lore.kernel.org/all/20220518070052.108287-1-denis.e.efremov@oracle.com/#r)
 - Similar to CVE-2021-28660 [fix in rtl8723bs driver](https://lore.kernel.org/all/20220520035730.5533-1-efremov@linux.com/)
 - Similar to CVE-2022-26490 [fix](https://lore.kernel.org/all/20221122004246.4186422-4-mfaltesek@google.com/) in [st-nci driver](https://lore.kernel.org/all/fc85ff14-70d6-0c3e-247d-eda2284a5f6b@oracle.com/)
 - Security [regression CVE-2020-10781](https://lkml.org/lkml/2023/4/17/744)
 - See [tests exceptions](https://github.com/evdenis/cvehound/blob/master/tests/test_01_on_branch.py#L7) for more examples

## Installation

``` shell
$ python3 -m pip install --user 'cvehound[spatch]'
```

That brings a prebuilt, tailored `spatch` along with the tool
([cvehound-spatch](https://github.com/evdenis/cvehound-spatch)), so there is
nothing else to install and no coccinelle build to keep in step. It is used
automatically unless you name another `spatch` explicitly.

Prerequisites: Python 3.11+, `grep` with PCRE support (`-P`), and `diffutils`
(spatch renders what it matched by running `diff`).

The wheel covers Linux on x86_64 and aarch64. Anywhere else, drop the
`[spatch]` part and provide coccinelle (>= 1.1.0) yourself — `apt install
coccinelle`, `dnf install coccinelle`, `brew install coccinelle`. A development
install from a clone takes the extra too: `pip install -e '.[spatch]'`.

### Updating rules and metadata

Detection rules and CVE metadata evolve much faster than the tool. To refresh
both without upgrading cvehound:

``` shell
$ cvehound update
```

Updates are downloaded from the project's rolling `content-latest` GitHub
release, verified against a checksummed manifest, and installed atomically
under `~/.local/share/cvehound/` — the installed package is never modified.
`cvehound update --check` only reports whether an update is available
(exit code 10 when one is, handy for cron), and `cvehound --version` shows
exactly which rules and metadata are in use. If the downloaded content is
missing or invalid, cvehound falls back to the rules and metadata bundled
with the package.

The metadata location can also be pinned with `--metadata <file>` or the
`CVEHOUND_METADATA` environment variable, and default CLI options can be set
in `/etc/cvehound.ini` or `~/.config/cvehound.ini` (see `--config`).

Which `spatch` runs is chosen the same way: `--spatch <path>` (or a `spatch`
key in the config file), else the `CVEHOUND_SPATCH` environment variable, else
the bundled `cvehound-spatch` package if it is installed, else whatever is on
`PATH`. A binary you name explicitly is never silently replaced by a fallback —
if it does not resolve, cvehound stops and says so.

## How to use

The simplest way to start using CVEhound is to run the following command:

``` shell
$ cvehound --kernel ~/linux
Found: CVE-2020-27830
Found: CVE-2020-27152
Found: CVE-2020-29371
Found: CVE-2020-26088
```

where *dir* should point to the Linux kernel sources. CVEhound will check the
sources for all cve patterns that you can find in [cve dir](/cvehound/cve/).
To check the sources for particular CVEs one can use:

``` shell
$ cvehound --kernel ./linux --kernel-config --cve CVE-2020-27194 CVE-2020-29371
Checking: CVE-2020-27194
Found: CVE-2020-27194
MSG: bpf: Fix scalar32_min_max_or bounds tracking
FIX DATE: 2020-10-08 09:02:53
https://www.cve.org/CVERecord?id=CVE-2020-27194
Affected Files:
 - linux/kernel/bpf/verifier.c: CONFIG_BPF & CONFIG_BPF_SYSCALL
   linux/.config: affected
Config: ./linux/.config affected

Checking: CVE-2020-29371
Found: CVE-2020-29371
MSG: romfs: fix uninitialized memory leak in romfs_dev_read()
FIX DATE: 2020-08-21 16:52:53
https://www.cve.org/CVERecord?id=CVE-2020-29371
Affected Files:
 - linux/fs/romfs/storage.c: CONFIG_ROMFS_FS
   linux/.config: not affected
Config: ./linux/.config not affected
```

Other args:
 - `--report` - will produce json file with found CVEs
   Most of the metainformation in the generated report is taken from kernel.org
   vulns.git and CIP kernel-sec. Rules that could not be checked are listed
   separately under `errors` (a rule that blew its time budget, a spatch failure,
   a rule needing a newer spatch), so an empty `results` can be told apart from a
   scan that did not finish
 - `--kernel-config` or `--kernel-config <file>` - will infer the kernel configuration required to
   build the affected code (based on Kbuild/Makefiles, ifdefs are not checked) and
   check kernel .config file if there is one. Files the parser can't map to CONFIG_
   options are reported as `unknown` and counted as affected
 - `--check-strict` - with `--kernel-config`, report only CVEs whose affected files are
   enabled in the .config. A CVE is dropped only when the evaluation explicitly rules
   every affected file out (e.g. the option is disabled, or the file belongs to another
   architecture); files unknown to the Kbuild parser are still reported with a warning
 - `--arch` - kernel architecture to analyze (x86, arm64, ...; ARCH spellings like
   x86_64 are normalized to the arch/ source directory). Defaults to the architecture
   from the .config banner, or x86
 - `--files` - will limit the scope of checked cves to the kernel files of interest
 - `--exploit` - check only for CVEs that are known to be exploitable (according to
   the CISA Known Exploited Vulnerabilities catalog)

## Contributing

### Development Setup

The project uses [uv](https://docs.astral.sh/uv/) for dependency and
environment management.

``` shell
# Install uv (once, globally)
$ curl -LsSf https://astral.sh/uv/install.sh | sh

# Clone and create the dev environment
$ git clone https://github.com/evdenis/cvehound.git
$ cd cvehound
$ uv sync                         # creates .venv and installs dev deps

# Install pre-commit hooks
$ uv run pre-commit install

# Run all linters, formatters, and type checks
$ uv run pre-commit run --all-files

# Run the test suite
$ uv run pytest
```

The project uses:
- **uv** for dependency and environment management
- **ruff** for linting and formatting
- **ty** (beta) for static type checking — replaces mypy; version is pinned via `uv.lock`
- **pre-commit** for automated code quality checks

### Writing CVE Detection Rules

If you'd like to contribute new CVE detection rules, please see our comprehensive guides:

- **[Writing Coccinelle Detection Rules for CVE Patterns](docs/WRITING_RULES.md)** - Complete guide with step-by-step instructions, patterns, and examples
- **[Coccinelle CVE Detection Cheat Sheet](docs/COCCINELLE_CHEATSHEET.md)** - Quick reference for common patterns

Templates:
- `contrib/template.cocci` - Enhanced template with examples and comments
- `contrib/blank.cocci` - Minimal template for new rules

If you use a coding agent, the repository ships a `write-cve-rule` skill in
`.agents/skills/` (picked up by OpenAI Codex, and by Claude Code via `.claude/skills/`).
It drives the workflow above and runs `.agents/skills/write-cve-rule/scripts/validate-rule.sh`,
which you can also call by hand — see [AGENTS.md](AGENTS.md).

## License

Python code is licensed under GPLv3. All rules in cvehound/cve folder are licensed under GPLv2.

## Acknowledgements

I would like to thank the following projects and people behind them:
 - [coccinelle](https://coccinelle.gitlabpages.inria.fr/website/) for the program matching engine
 - [kernel.org vulns.git](https://git.kernel.org/pub/scm/linux/security/vulns.git/) and
   [CIP kernel-sec](https://gitlab.com/cip-project/cip-kernel/cip-kernel-sec) for information
   about Linux CVEs
 - [undertaker](https://vamos.informatik.uni-erlangen.de/trac/undertaker) for mapping kernel configs to .c files
 - [sympy](https://www.sympy.org/) for the symbolic logic solver
