The thing nobody checks#
In a SOC, detection rules exist in two shapes. There is the generic, vendor-neutral Sigma format: thousands of rules written and shared by the community, versionable, readable and SIEM-agnostic. Then there is whatever the SIEM speaks natively. For IBM QRadar, that is AQL, the Ariel Query Language, which drives saved searches, building blocks and custom rules.
The gap between those two shapes is a manual translation job. Someone reads the Sigma rule, figures out which QRadar/Ariel field each Sigma field maps to, hand-writes the AQL, pastes it into the console, and moves on. It’s slow and error-prone, and almost nobody goes back afterward to check that the translated rule still catches the attack once it’s live in the SIEM.
That last step is where translations fail quietly. The AQL parses, the saved search runs, and it returns zero results forever. Everyone reads that as “no attacks” when it may mean the rule was never going to fire. A detection that looks deployed but detects nothing is worse than no detection, because it creates false confidence.
So I built What The Sigma, a detection-as-code pipeline that runs the whole cycle end to end:
Sigma rule -> AQL -> QRadar -> simulated attack -> did it fire? -> ATT&CK coverage map
(YAML) (IBM backend) (REST API) (Atomic Red Team) (Ariel search) (Navigator layer)The name is a joke. The last two boxes are the entire point.
Why translation isn’t the interesting part#
Converting Sigma to AQL is already solved, and IBM solved it. IBM maintains an official, open-source pySigma backend, IBM/pySigma-backend-QRadar-AQL, published on PyPI as pysigma-backend-qradar-aql. I do not need to reinvent the translator, and doing so would only produce a less capable one.
What I can build, and what most detection programmes skip, is everything around the translation: deploying the converted rules into QRadar automatically, without piling up duplicate copies every time a rule changes upstream; simulating the actual MITRE ATT&CK technique each rule claims to detect, using Atomic Red Team; verifying by re-running the rule’s own converted query over the attack window and asking it, directly, whether it matched anything; and reporting the result as a colour-coded ATT&CK Navigator layer where green means proven, not hoped for.
That reframing, from translation speed to evidence that the translated rule works, is what the rest of this series is about.
The numbers, so far#
I ran the conversion side against the full SigmaHQ corpus. This measures IBM’s backend more than it measures my code, but it sets the scene:
| Count | Share | |
|---|---|---|
| Rules processed | 3144 | |
| Converted | 3041 | 96.7 % |
| via mapped-field pipeline (fast) | 2079 | 66.1 % |
| via payload-scan fallback | 962 | 30.6 % |
| Failed | 103 | 3.3 % |
| Distinct ATT&CK techniques | 388 |
The focused, lab-testable subset I committed to the repository contains 25 rules, curated one per technique for Windows endpoints:
| Sigma rules | 25 |
| Converted to AQL | 25 / 25 (100 %) |
| On the fast mapped-field path | 25 / 25, no payload scans |
| Distinct ATT&CK techniques | 37 |
| Conversion warnings | 0 |
Those 25 rules convert in under three seconds. Doing the same work by hand, reading the rule, finding the QRadar field names, writing the AQL, testing it and pasting it into the console, took 20 to 40 minutes per rule, even with experience in both formats. Minutes instead of days is the basic business case for the pipeline.
What is built#
I’m not going to pretend the whole thing is live. Detection-as-code has a hard dependency: a real SIEM. QRadar Community Edition wants 24 GB of RAM and 250 GB of disk, and the disk is the part my lab machine doesn’t have yet. So here’s the real status, no rounding up:
| Phase | State |
|---|---|
| 0 - Research & backend validation | done, measured against 3144 rules |
| 2 - Conversion pipeline | done, 55 offline tests |
| 3 - Deployment | code done, dry-run works, waiting on a live instance |
| 5 - Coverage reporting | done |
| 6 - CI/CD | workflow written |
| 1 - Lab build | not yet, QRadar CE isn’t deployed |
| 4 - Attack validation | blocked on the lab |
Everything that does not need a running SIEM is built and tested. Everything that does is waiting on the lab. I would rather state that plainly than paint a coverage map green on a machine that has never spoken to a SIEM. The pipeline enforces the same rule on its own output, and it comes up again throughout the series.
A design decision that runs through everything#
Each phase is its own command-line tool. It reads one JSON file, writes another, and hands off:
rules/sigma/**.yml
| convert.py (phase 2, offline)
v
converted/manifest.json
| deploy.py (phase 3, needs QRadar)
v
state/deployments.json
| validate.py (phase 4, needs QRadar + a Windows endpoint)
v
state/validation.json
| report_navigator.py (phase 5, offline)
v
reports/attack-navigator-layer.jsonNothing is passed around in memory. Any stage can be rerun or inspected on its own, and if the lab falls over during a validation run it doesn’t cost me the conversion work. That decoupling is what let me build and test two-thirds of the pipeline before the SIEM even exists.
What the series covers#
Seven posts, following the pipeline:
- This one: the problem, the thesis and the current status.
- Phase 0: interrogating QRadar’s API before trusting it: what the REST API actually lets you create, measured against a live instance rather than assumed from the docs.
- Two pipelines, one choice: Sigma to AQL: IBM’s backend, the fast path, the payload-scan fallback and a fail-open behaviour worth catching before production.
- The ATT&CK v18 renumbering trap: how a 2025 taxonomy change makes coverage tools silently report gaps that do not exist.
- Deploying detections without making a mess: idempotence by Sigma UUID and status reporting that reflects reality.
- Proving a detection actually fires: Atomic Red Team, re-running the rule’s own query and why
not_triggeredis the correct answer. - A coverage map that tells the truth: folding three phases into one Navigator layer and building a console around the same evidence.
If you only take one idea from all of it, take this: a detection you haven’t simulated is a hypothesis, not a control. Everything else in the series is engineering built to back that up.