DeepZero: A YAML Pipeline Engine for Windows Driver IOCTL Triage
Find zero-days while you sleep. DeepZero is an automated vulnerability research framework that parses, decompiles, and analyzes thousands of Windows kernel drivers for exploitable IOCTLs natively using AI agents.
At a glance
- What is it?
- DeepZero is an MIT-licensed Python framework that chains ingest, filter, decompile and LLM assessment stages over a corpus of Windows kernel drivers. The engine is the durable part; the driver analysis pipeline is the part you have to assemble and verify yourself.
- Who is it for?
- Adopt DeepZero if you already have a driver corpus and a Ghidra headless setup, and you want the orchestration, resumable state and LLM assessment loop handled for you rather than writing it yourself. Do not adopt it if you expect the repository to hand you a working zero-day finder: the driver pipeline depends on Ghidra, an LLM provider and Semgrep, none of which ship with the package.
- Can I use it commercially?
- Yes. MIT 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 6 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The corpus problem DeepZero is built around
Windows kernel drivers expose functionality through IOCTL codes, and a driver that accepts a user-controlled buffer without validating its length or its caller's privilege is a local privilege escalation primitive. Vendors ship thousands of these binaries, and the Bring Your Own Vulnerable Driver technique means an attacker does not need a new bug in Windows itself, only a signed driver that was already shipped. The volume is the difficulty. Reading one driver by hand is an afternoon; reading a vendor's entire driver directory is not.
DeepZero targets that volume problem rather than the exploit-writing problem. The README describes it as an "automated vulnerability research pipeline engine" and the repository is organised accordingly: an engine, a set of stages, and a pipelines directory containing a demo and a loldrivers pipeline. The intended user is someone with a driver corpus and a triage budget, not someone looking for a finished exploit. That distinction matters, because the framework produces assessments and reports, and the gap between an assessment and a working exploit is entirely the user's to close.
Pipeline-as-YAML and the stage taxonomy
The core abstraction is a pipeline declared in YAML. Stages are chained, and the README lists four kinds of work: ingest, filter, transform and LLM-assess. The engine source tree splits into engine, stages and api, with stages holding the built-in processors (map, reduce, ingest).
Execution uses ThreadPoolExecutor with configurable concurrency per stage, and the README states that runs are resumable through atomic per-sample state written to disk. That combination is the most interesting design decision in the project. Per-sample state means a crash or a Ctrl+C does not discard the work already done on the samples that completed, which for a decompilation-heavy pipeline is the difference between a rerun costing minutes and costing hours. Parallelism is thread-based rather than process-based, which is a reasonable choice when the expensive work happens in a subprocess such as Ghidra headless, and a poor one if a custom processor is CPU-bound in pure Python.
The LLM stage uses Jinja2 prompt templates, with the loldrivers pipeline carrying an assessment.j2 file, and routes to providers through LiteLLM. Custom processors are Python classes referenced by path in YAML, which is the extension point that keeps the engine from being tied to the four shipped processors.
What actually ships in the repository
The processors directory contains four external processors, described in the README as shipped examples: ghidra_decompile (a MapProcessor wrapping the Ghidra headless decompiler), loldrivers_filter (a MapProcessor that excludes hashes listed by loldrivers.io), pe_ingest (an IngestProcessor that parses PE headers and extracts driver metadata), and semgrep_scanner (a BulkMapProcessor running Semgrep in batch).
That set tells you where the analysis actually happens. The engine does not decompile anything itself; Ghidra does. It does not pattern-match IOCTL handlers itself; Semgrep rules under pipelines/loldrivers/rules do. The LLM stage reads the decompiled output through a Jinja2 template and produces an assessment. DeepZero's contribution is the glue, the scheduling and the state, which is a legitimate contribution but a narrower one than the project description suggests.
The loldrivers_filter processor is a filter in the literal sense: it removes drivers whose hashes appear on the loldrivers.io list. That is a sensible first pass to avoid re-triaging known-vulnerable binaries, and it also means the pipeline is oriented toward finding drivers that are not yet on that list.
Getting a first run without an API key
The README gives a demo path that requires Python 3.11 or later and nothing else. No API keys, no Ghidra, no driver corpus.
git clone https://github.com/416rehman/DeepZero.git cd DeepZero python -m pip install -e . deepzero run pipelines/demo/samples -p pipelines/demo/pipeline.yaml deepzero report -p pipelines/demo/pipeline.yaml --open
According to the README, the demo discovers two harmless text files, keeps one, filters the smaller one, and generates a browsable HTML report. Running the same pipeline command again resumes from saved state. The README is explicit that this demonstrates the engine and does not run vulnerability analysis, which is an honest framing and worth taking at face value: a successful demo run tells you the orchestration works, not that the analysis works.
The driver pipeline is a separate setup. The README points to a full setup guide and a pipeline prerequisites page on the project blog, and notes that optional integrations require their own dependencies and configuration. Those prerequisites are not enumerated in the README itself, so treat the blog documentation as required reading rather than supplementary. The two CLI verbs visible here are run, which takes a sample path and a pipeline file, and report, which takes a pipeline file and an --open flag.
The LLM stage is the weakest link in the chain
Feeding decompiled driver code to a language model and asking for an assessment is the part of this pipeline most likely to produce confident nonsense. Decompiler output is not source code: variable names are synthetic, types are reconstructed guesses, and the control flow of a driver dispatch routine can be spread across several functions. A model that misreads a bounds check will report a vulnerability that is not there, and a model that misses one will report nothing.
The Jinja2 template approach means the prompt is at least inspectable and editable, which is more than can be said for a hardcoded prompt string, and the LiteLLM layer means the provider is swappable. Neither of those addresses the underlying reliability question. The repository does not, from the material available, publish an evaluation of the LLM stage's precision or recall on a labelled set of drivers, and without that the assessment output should be treated as a triage signal that routes a human to a file, not as a finding.
The same caution applies to the Semgrep layer. Semgrep rules match patterns, and IOCTL handling bugs are frequently about missing checks rather than present ones, which is the harder case for pattern matching. The rules under pipelines/loldrivers/rules are the concrete artefact to read before trusting a clean result.
What you would otherwise write yourself
The obvious alternative is a shell script or a Makefile that walks a directory, calls Ghidra headless on each binary, pipes the output through Semgrep, and writes results to files. That approach is genuinely simpler and has no Python dependency. Its weakness is exactly the area DeepZero invests in: resumption and concurrency. A shell loop over four thousand drivers that dies at driver three thousand has no memory of what it finished, and adding safe parallelism with per-sample state to a shell script is how you end up writing a worse version of this engine.
A second alternative is a general workflow orchestrator such as Airflow or Prefect, which offers scheduling, retries and observability far beyond what DeepZero implements. The difference in approach is that those tools are built for recurring jobs over time with a scheduler and a metadata database, while DeepZero is built for a single corpus pass with state kept on disk next to the samples. If your driver triage is a one-off sweep, the general orchestrator is infrastructure you do not need. If it is a nightly job feeding a dashboard, DeepZero's engine is not the right layer and you should call its processors from something else. There is also a REST API in the tree, but the README labels it work in progress, experimental and incomplete, so it should not be the basis of an integration decision.
Maintenance, licence and what to check before committing
The project is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. DeepZero's own licence does not extend to what it invokes. Ghidra carries its own licence terms, Semgrep has its own licensing model, loldrivers.io data has its own provenance, and any LLM provider you route through LiteLLM has its own terms and per-token cost. None of that is legal advice, and if you plan to redistribute analysis output or embed the pipeline in a product, the licences of the invoked tools are the ones to read.
Upgrade cost is shaped by the interfaces you touch. Custom processors are Python classes referenced by path in YAML, so a processor written against the current stage base classes is the part most exposed to engine changes. Pipelines are YAML and prompt templates are Jinja2, both of which are data rather than code, so they should survive engine refactors more easily. Two releases are listed, v0.3.0 and v0.4.0, roughly a week apart, which is a fast cadence and a reason to pin a version rather than track main. The REST API being explicitly incomplete is the clearest signal about what is stable: treat the CLI, the YAML schema and the processor base classes as the supported surface, and treat the HTTP layer as something that may change without notice.
The CI configuration runs on Python 3.11 through 3.14, and the contributing guide asks for ruff and bandit to pass before a pull request. That tells you the project holds a linting and static-analysis bar, not that the analysis pipeline is accurate.
Editorial conclusion
Adopt DeepZero if you already have a driver corpus and a Ghidra headless setup, and you want the orchestration, resumable state and LLM assessment loop handled for you rather than writing it yourself. Do not adopt it if you expect the repository to hand you a working zero-day finder: the driver pipeline depends on Ghidra, an LLM provider and Semgrep, none of which ship with the package. Before trusting any finding, run the demo pipeline end to end, then run the loldrivers pipeline against a handful of drivers whose behaviour you already understand, and read the Semgrep rules in pipelines/loldrivers/rules to see exactly what patterns are being matched.
Community notes