# cwe_checker binary analysis for ELF vulnerability discovery

> cwe_checker applies configurable static checks to ELF binaries through Ghidra's intermediate representation, with Docker and local Rust installation paths for analyst use.

**fkie-cad/cwe_checker** — cwe_checker finds vulnerable patterns in binary executables

- Repository: https://github.com/fkie-cad/cwe_checker
- Website: https://docs.cwe-checker.io
- Stars: 1,362 · Forks: 147
- Language: Rust
- License: LGPL-3.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/fkie-cad-cwe-checker

## Where cwe_checker fits in ELF security analysis

cwe_checker addresses a specific problem: finding potentially vulnerable code paths in compiled binaries without requiring the original source code. It is aimed at reverse engineers, malware analysts, firmware specialists, and other security professionals who work with executable artifacts. Rather than searching source for known CWE patterns, it applies static analyses after Ghidra has disassembled a binary.

The checks cover classes including null pointer dereferences, buffer overflows, externally controlled format strings, integer overflow, use after free, double free, and predictable random-number generation. The repository also lists OS command injection, but the README says that check is disabled during standard runs. Results are CWE warnings rather than proof that an attacker can exploit the binary. The project describes them as potentially vulnerable paths for analysts to investigate.

Its main format is ELF, which covers binaries commonly used on Linux and Unix systems. Because Ghidra supplies the disassembly and cwe_checker performs its analyses on a common intermediate representation, the documented architecture coverage includes x86, ARM, MIPS, and PPC. This makes the project relevant to firmware analysis, where source may be unavailable and the same program can be examined across CPU architectures.

There is experimental support for Linux loadable kernel modules and bare-metal binaries. The former uses a subset of the user-space checks and a separate `src/lkm_config.json`. Bare-metal analysis requires a configuration passed through `--bare-metal-config`, with `bare_metal/stm32f407vg.json` documented as an example created and tested for an STM32F407VG MCU. Those qualifiers matter. Linux kernel modules and bare-metal targets are not interchangeable with normal user-space ELF analysis.

## Ghidra extraction and the cwe_checker analysis pipeline

The central architectural choice is to place Ghidra before cwe_checker's Rust analyses. The repository includes a Ghidra plugin directory, a headless Ghidra base image, and an extractor whose built artifact is copied into the Docker image. The native installer likewise locates a local Ghidra installation when `GHIDRA_PATH` is not supplied.

The data flow starts with a binary supplied to the `cwe_checker` executable. Ghidra disassembles it into its intermediate representation. cwe_checker then runs checks over that representation using techniques that range from heuristics to abstract interpretation-based data-flow analysis. Findings are emitted as a list of CWE warnings. The README also says that results can be viewed in an annotated Ghidra environment and that cwe_checker can be integrated as a plugin into FACT.

The plugin-based design is a practical extension point, although the excerpt does not document the complete plugin API. Checks can also be configured, including adaptation to new APIs. Configuration is not limited to a single execution mode: ordinary user-space analysis uses `src/config.json`, while Linux loadable kernel module analysis uses `src/lkm_config.json`. A modified configuration must be selected explicitly with `--config=src/config.json`.

That separation has an important consequence. A check can only recognize behavior represented by its models, library knowledge, configuration, and the information available after disassembly. The README does not claim source-to-source precision or guarantee that every implementation of a vulnerable pattern is found. It presents cwe_checker as a way to direct analysts toward code paths for review.

## Docker setup and the first binary scan

Docker is the shortest documented route because the official image packages the Rust binary, Ghidra components, default configurations, and the p-code extractor. For a repeatable release-oriented setup, use the `stable` tag. The README also publishes `latest`, which follows the current `master` branch, and a version-specific `v0.9` tag.

Pull the stable image:

```bash
docker pull ghcr.io/fkie-cad/cwe_checker:stable
```

Docker should report that the image has been downloaded. The prebuilt images are x86-based. For an ARM-based machine, such as a newer Apple Mac, the README recommends building the image locally instead of assuming that the published image has the required architecture.

Scan a binary by mounting it at `/input`:

```bash
docker run --rm -v /PATH/TO/BINARY:/input ghcr.io/fkie-cad/cwe_checker /input
```

Replace `/PATH/TO/BINARY` with the path to an ELF file on the host. The container's entry point is `/home/cwe/cwe_checker`, and the command-line argument names the mounted analysis target. The documented output is a list of detected CWE warnings. A finding should prompt inspection of the reported code path, not automatic acceptance as a confirmed vulnerability.

For an initial deployment, `stable` is easier to reason about than `latest`: the README defines `latest` as the current `master` branch, while `stable` tracks the latest stable release. The latest listed stable release is v0.9, published on 2024-08-20.

## Native Rust installation and configuration selection

A native installation is appropriate when the analyst already manages Rust and Ghidra on the host. The README requires Rust 1.82 or newer and Ghidra 10.2 or newer. The build uses the Cargo workspace and the `cwe_checker_install` package, then invokes the installer with an optional Ghidra path.

Install locally by running this from the repository root and replacing the path with the actual Ghidra directory:

```bash
make all GHIDRA_PATH=/path/to/ghidra_folder
```

If `GHIDRA_PATH` is omitted, the installer searches the file system for a local Ghidra installation. An explicit path removes ambiguity about which installation will be used. After installation, run the analyzer directly:

```bash
cwe_checker BINARY
```

Replace `BINARY` with the target path. The README also documents Nix flakes:

```bash
nix run github:fkie-cad/cwe_checker -- BINARY
```

Default user-space configuration is stored at `src/config.json`. To use a modified copy, pass it explicitly:

This is the same path named by the README, but it represents a configuration the reader has modified. Changing it without adding `--config=src/config.json` does not select that file. The README does not document a documented rollback procedure for configuration changes, so users should retain their own prior copy before editing it. Additional flags can be inspected with `cwe_checker --help`.

## Check coverage, disabled analyses, and result boundaries

CWE coverage gives the tool breadth, but the enabled set must be read carefully. The README lists buffer overflows under CWE-119, CWE-125, and CWE-787. It also lists OS command injection under CWE-78, with that check disabled on standard runs. Other documented checks address format strings, integer overflow, debug information exposure, unsafe `chroot` handling, random-number weaknesses, TOCTOU races, use after free, and double free.

Configuration matters because checks can be adapted to APIs and selected rules need not have identical maturity or applicability to every target. A standard run should not be described as including every implemented check, since CWE-78 is explicitly disabled there. Likewise, Linux loadable kernel modules receive only a subset of the checks available for user-space programs. An analyst moving from a normal executable to an LKM must account for both a separate configuration and a smaller analysis set.

Static warnings also have an evidence boundary. The analyzer works from disassembly and inferred data flow rather than original source semantics. The README does not document symbol recovery accuracy, interprocedural completeness, proof obligations, or false-positive rates. It also does not provide a procedure for exploiting a result. Accordingly, the output is best treated as triage data for reverse engineering.

The wrong fit is substantial here. A PE binary is outside the stated ELF focus. A source-code audit has richer context, including comments, build configuration, and source-level abstractions. A system requiring proof of exploitability also needs more than a CWE warning. cwe_checker is more relevant when the artifact is a binary and the immediate goal is finding candidate paths efficiently.

## Manual Ghidra review versus automated cwe_checker checks

The clearest alternative is a Ghidra-centered manual review. Ghidra is still part of cwe_checker's pipeline, so this is not a comparison between unrelated technologies. It is a comparison between automated CWE-oriented passes and analyst-led inspection of the disassembly and intermediate representation.

Manual Ghidra review can concentrate attention on a known subsystem, follow a questionable data path in context, and incorporate knowledge that is not encoded in a configuration file. It is slower for broad triage, though, and its coverage depends heavily on the questions the analyst remembers to ask. cwe_checker applies multiple checks consistently and can direct attention across a binary without requiring every analyst to reconstruct each data-flow pattern.

The two approaches also produce different kinds of evidence. A cwe_checker result is tied to an implemented check and configured API knowledge. Manual review can document control flow and program semantics, but that interpretation remains analyst-dependent. A hybrid use fits the project's stated goal: use warnings to locate candidate paths, then inspect those paths in Ghidra before assigning severity or exploitability.

This boundary is more useful than treating the scanner as a replacement for review. The README says its goal is to help analysts quickly find potentially vulnerable code paths. It does not claim that review becomes unnecessary after warnings appear.

## Release cadence, upgrades, and LGPL distribution work

The repository is not archived, and its last push was on 2026-09-28. The latest listed release is v0.9 from 2024-08-20, after v0.8 from 2024-02-22 and v0.7 from 2023-06-22. This indicates commits beyond the newest published release, but the release list does not establish what changes are present on `master` or whether a newer stable tag is available.

That distinction affects upgrades. The README recommends moving to newer stable releases because improvements between stable versions can be significant. Users who need repeatable analysis can pin `ghcr.io/fkie-cad/cwe_checker:v0.9`; users following the stable channel can use `stable`. The `latest` image follows `master`, so it should not be assumed equivalent to a stable release. Before changing tags, review `CHANGES.md` and validate representative binaries because a different image can change check behavior or results.

The project is licensed under `LGPL-3.0`. This identifier matters to organizations that redistribute the image or incorporate the software, but this review does not provide legal advice. Distribution and modification terms should be checked against the repository's `LICENSE` and `NOTICE` obligations as applicable. Upgrading to a new release image also means reviewing the files shipped in that image rather than only the source checkout.

## Conclusion

Security analysts and firmware teams should consider cwe_checker when they need repeatable CWE-oriented checks over ELF binaries, especially across architectures supported by Ghidra. Teams needing source-level guarantees, non-ELF formats, or confirmed exploits should keep Ghidra-led manual analysis in view. Verify first that the target is an eligible binary, choose the `stable` image for repeatable deployment, and inspect how each selected check models the relevant APIs before treating its warnings as findings.

## FAQ

### How do I install and run cwe_checker for the first time?

Pull `ghcr.io/fkie-cad/cwe_checker:stable`, then mount an ELF binary into the container and pass `/input` as the target. The output is a list of CWE warnings produced by static analysis.

### Does cwe_checker support binaries other than ELF?

The documented main focus is ELF binaries for Linux and Unix systems. The project also describes experimental support for Linux loadable kernel modules and bare-metal binaries under specific conditions.

### Why is OS command injection missing from a standard cwe_checker run?

The implemented CWE-78 OS Command Injection check is disabled on standard runs. The README lists it as implemented, but its status means analysts cannot assume every documented check runs with the default configuration.

### How do I configure cwe_checker for new APIs?

Checks are configurable through `src/config.json`, and the modified file must be selected with `--config=src/config.json`. Linux loadable kernel module analysis uses the separate `src/lkm_config.json`.

### Can cwe_checker analyze ARM, MIPS, and PPC binaries?

The README states that cwe_checker analyzes ELF binaries for x86, ARM, MIPS, and PPC. This support depends on the binary being dislatable by the included Ghidra-based pipeline.

## Sources

- [fkie-cad/cwe_checker on GitHub](https://github.com/fkie-cad/cwe_checker)
- [License: LGPL-3.0](https://github.com/fkie-cad/cwe_checker/blob/master/LICENSE)
- [Project website](https://docs.cwe-checker.io)
- [README](https://github.com/fkie-cad/cwe_checker/blob/master/README.md)
- [Releases](https://github.com/fkie-cad/cwe_checker/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fkie-cad-cwe-checker
