Skip to main content
Glama
WRG-11

wrg-sigma-rules

WRG Sigma Rules

tests release last commit sigma rules license python 3.12+

Sigma detection-rule authoring, validation and multi-backend conversion, delivered as a Model Context Protocol (MCP) server with a published rule corpus. It runs under Claude Code, Codex, Cursor and any MCP-capable client.

What it does

  • Three MCP tools. draft_rule turns a natural-language description into a Sigma YAML scaffold. validate_rule checks a rule against pySigma plus a best-practice linter. convert_rule compiles a rule to a Splunk, Elastic, OpenSearch, Wazuh or Kibana query.

  • Three Claude Code skills: sigma-rule-writer, sigma-rule-reviewer and threat-coverage-gap-analyzer. The packaged Codex variants retain the same evidence boundaries: coverage counts do not establish missing ATT&CK scope, conversion does not establish deployed semantics, and observed_* public contributions require the sourcing bar in CONTRIBUTING.md.

  • A published corpus of 296 rules across 14 MITRE ATT&CK tactic categories. Every rule carries an honest Sigma status: (see Rule status).

  • Multi-backend conversion on pySigma 1.x: Splunk SPL, Elastic and Kibana Lucene, OpenSearch Lucene and PPL, plus Wazuh. The Lucene-family targets cannot express Sigma correlation rules, so convert_rule reports the

    correlation rules in the corpus as a capability gap and names the backends that can convert them.

The plugin is installed directly from this repository; it is not yet listed in a plugin marketplace.

Related MCP server: Wazuh SIEM Agent System

Install

The server is a single stdio MCP process (server.py). Each client points at it in its own way.

Claude Code

git clone https://github.com/WRG-11/wrg-sigma-rules.git
cd wrg-sigma-rules
pip install -r requirements.txt
claude plugin validate .

requirements.txt is not optional: validate_rule needs pySigma, convert_rule needs the backend packages, and the pipeline packages drive the logsource mapping. The repo ships .claude-plugin/plugin.json and .mcp.json (which wires server.py through ${CLAUDE_PLUGIN_ROOT}). Point your Claude Code plugin configuration at this checkout per the plugin docs.

Codex

codex plugin marketplace add .
codex plugin add wrg-sigma-rules@wrg-11

The Codex plugin carries a self-contained runtime snapshot of the server and corpus, so its installed cache does not rely on checkout-relative paths. Keep it current with python scripts/sync_codex_runtime.py. Check parity without rewriting the snapshot via python scripts/sync_codex_runtime.py --check; CI fails if it drifts. A Codex package may add a local build suffix to its version, but its release base is regression-checked against the server manifest. Snapshot parity proves packaged source and corpus identity, not that a particular client has provisioned a compatible Python environment or refreshed its installed cache. CI installs the bundled runtime requirements on a clean runner and completes a package-wrapper MCP handshake, but that remains a Python-runtime check rather than evidence that a particular client refreshed its installed cache. After installation, verify a real MCP handshake in the target client before treating the package as ready. The repository smoke harness bounds every protocol reply, so an unresponsive server fails the check rather than consuming the workflow timeout.

Cursor

Cursor speaks MCP directly, so the same server works with no plugin manifest. Add it to your project .cursor/mcp.json (or the global ~/.cursor/mcp.json):

{
  "mcpServers": {
    "wrg-sigma-rules": {
      "command": "python",
      "args": ["/path/to/wrg-sigma-rules/server.py"],
      "cwd": "/path/to/wrg-sigma-rules",
      "env": { "PYTHONPATH": "/path/to/wrg-sigma-rules" }
    }
  }
}

Replace the path with your clone, then reload Cursor's MCP servers.

Any MCP client

server.py is a standard stdio MCP server, so Cline, Continue, Zed and Windsurf load it with the same mcpServers block shown for Cursor. MCP is model-agnostic: the client's backend model does not change what the server exposes.

Quick example

Validate and convert a corpus rule end to end, from the repo root:

pip install pysigma pysigma-backend-splunk pysigma-backend-elasticsearch
import sys, json
sys.path.insert(0, '.')
from tools.validate_rule.validate_rule import validate_rule_body
from tools.convert_rule.convert_rule import convert_rule_body

rule = open('resources/examples/command_and_control/observed_mini_shai_hulud_npm_supply_chain_c2_t1071.yml', encoding='utf-8').read()

print(json.dumps(validate_rule_body(rule), indent=2))
print(json.dumps(convert_rule_body(rule, target='splunk'), indent=2))
print(json.dumps(convert_rule_body(rule, target='elasticsearch'), indent=2))

Full captured output (validate JSON, Splunk SPL, Elasticsearch Lucene) is in DEMO.md.

The corpus

Every rule lives under resources/examples/<tactic>/ and is one of two kinds:

  • template_*: a canonical detection shape to adapt to your own environment.

  • observed_*: derived from a specific, cited incident. CONTRIBUTING.md sets the bar these must clear.

resources/examples/INDEX.json enumerates every rule, and the wrg-sigma://coverage/mitre-attack-matrix resource computes the technique-by-tactic breakdown from the corpus at read time. Some rules add a prose write-up under docs/detection-notes/.

Rule status

This corpus uses Sigma's status: field literally rather than aspirationally:

status:

Count

Meaning here

test

82

Derived from a real, cited incident (the observed_* rules)

experimental

214

Canonical detection shapes, many self-described as synthetic exemplars

stable

0

Unused, deliberately

stable in the Sigma specification means a rule runs in production and is well tested. Nothing here has earned that, so nothing claims it. Treat every rule as a starting point to bind to your own logsource and tune; each rule's falsepositives: block names the benign activity to expect first.

Resources

  • wrg-sigma://patterns/canonical-5 and wrg-sigma://patterns/canonical-5/{01..05}: canonical detection-pattern definitions.

  • wrg-sigma://coverage/mitre-attack-matrix: an ATT&CK coverage rollup computed from the corpus at read time. Its Rules-content SHA-256 identifies the exact corpus bytes behind a count, so installed and checkout runtimes can be compared without treating different releases as measurement drift.

Quality and testing

  • modules cover rule validation and tool-integration smoke tests.

  • pySigma 1.x compatibility is verified against the Splunk, Elasticsearch and OpenSearch backend packages.

  • CI runs the full suite on Ubuntu, Windows and macOS runners on every push.

  • The Docker CI smoke exchange compares the container coverage resource's corpus fingerprint with the checked-out corpus, so an otherwise healthy image cannot silently serve stale rule data.

  • README counts are stamped from ground truth: python readme_stamp.py --check fails CI on any drift, so the numbers here cannot silently go stale.

  • To compare an installed or cached Codex runtime with this checkout without modifying either one, run python scripts/runtime_identity.py --runtime-root <runtime-path> --expect-same-as .. A match proves only local runtime/corpus identity. Its rule_tree_sha256 is a file-tree comparison digest, not the live MCP coverage resource's identity; neither value claims marketplace publication or a client cache refresh.

Evidence-review audits

The following local reports make review queues and conversion boundaries visible. They are advisory: none promotes a rule, proves an actor attribution, or replaces reading the cited source. Pass --examples-dir (and, where applicable, --notes-dir) when auditing a copied or isolated corpus; a missing examples directory is an error rather than an empty result. The correlation-conversion audit also fails clearly if any selected corpus YAML file cannot be read, decoded, or parsed; a partial conversion count is not a reproducible measurement. The observed-evidence inventory likewise fails clearly on unreadable or invalid observed-rule YAML and unreadable detection notes, rather than publishing a partial provenance inventory. The detection-note gap report uses the same rule and note input boundary, so a partial documentation queue cannot be mistaken for a complete review queue.

python scripts/observed_evidence_inventory.py --examples-dir resources/examples
python scripts/duplicate_rule_check.py --examples-dir resources/examples --exact-actor-logic
python scripts/duplicate_rule_check.py --examples-dir resources/examples --actor-review-queues
python scripts/correlation_conversion_audit.py --examples-dir resources/examples
python scripts/detection_note_gap.py --examples-dir resources/examples --notes-dir docs/detection-notes

Use --json path/to/report.json with any report when a review needs a machine-readable snapshot; the advisory reports carry their scope limitation inside that JSON so a copied count is not detached from its evidence boundary. Each report creates the parent directory of its --json target, so the same automation path can be used across all four tools. Object-shaped report payloads carry contract.tool and contract.version; consumers should ignore unknown keys and only treat a version change as a compatibility boundary. duplicate_rule_check preserves its legacy bare-list default JSON for existing consumers; pass --json-envelope to receive its versioned {contract, groups, limitations} form. That option only changes the default fingerprint report: the exact-logic and actor-review-queue modes always write their own versioned envelopes when --json is supplied. --actor-review-queues instead writes a versioned envelope with three separate mechanical queues: exact logic, same comparison shape with different numeric thresholds, and shared adjacent sidecar bytes. They are source-review inputs, not semantic-equivalence, attribution, provenance, or consolidation verdicts. Versioned duplicate-report envelopes also carry skipped_files for YAML files that the selected mode could not read, decode, or parse. The legacy default bare-list JSON remains unchanged; use --json-envelope when that visibility is needed in a default-mode automation. For a fixed corpus and option set, report arrays are emitted deterministically; JSON object-member order is not a compatibility guarantee, so consumers should parse fields rather than byte-diff raw JSON. The inventory retains its attribution, platform and telemetry-manifestation fields as not_assessed until a human has documented the three source matches in CONTRIBUTING.md. Those review records live under docs/source-reviews/: each must cite a URL already on the rule, record a review date that is not in the future, and include a source quote for every supported or not-supported conclusion. The inventory rejects malformed or future-dated records rather than treating them as evidence; source or rule drift still requires human re-review. It also records the literal presence of WRG breach catalog and whether a multi-document rule keeps references only in a later document. Both are public traceability review cues, never source-quality or attribution verdicts. The JSON report preserves the public reference lists (including their first/later-document split) for human review, without assigning source ranks. Its summary distinguishes a structured review record, completion of all three source matches, and an explicit unsupported boundary; none of those counts is an attribution or promotion decision. public_traceability_queue is a convenience subset for the two mechanical public-review cues; it is not a verdict about a rule or its sources. For per-rule JSON, prefer reference_shape and is_mentioned_by_detection_note: both are literal inventory facts, not source quality or note-endorsement labels. The older reference_hygiene and has_companion_note fields remain compatibility aliases with identical values.

The correlation audit separately counts a backend's declared capability boundaries (for example, correlation_rules or correlation_type:temporal_ordered). A successful conversion remains syntax evidence only; it does not assert equivalent alert behavior in a deployed SIEM.

Contributing

Contributions are welcome. Add YAML under resources/examples/<tactic>/ with an ATT&CK mapping in tags: (for example attack.t1071), the observed_* or template_* prefix, and a passing validate_rule. Corpus CI rejects broad empty matches, unsafe regex, unroutable logsource blocks, draft scaffolding and deprecated aggregation-pipe syntax.

Read CONTRIBUTING.md before submitting an observed_* rule. It sets the sourcing bar (attribution, platform and manifestation, each matched against the cited source) and documents the three upstream rejections that produced it.

See ROADMAP.md for the repository's current direction, explicit product boundaries and evidence required before an item is considered complete.

License

MIT; see LICENSE. One license covers both the tooling (server.py, tools/, scripts/) and the corpus (resources/). That is a deliberate choice for frictionless reuse by SOC teams adapting a rule into their own tooling, over the attribution-preserving split that some Sigma corpora use.

Runtime dependencies bring in LGPL-2.1/3.0 packages (pySigma and its backends) alongside MIT, BSD and Apache ones. Importing an LGPL library does not make this repo's own code LGPL. The dependency-licenses CI job carries the re-derivable list.

Part of the WRG-11 ecosystem

Full index at github.com/WRG-11.

Available Tools

3 tools
convert_ruleA

Convert a sigma YAML rule into a SIEM-native query string.

Use when the caller has a validated sigma rule and needs the equivalent query for Splunk SPL, Elasticsearch / Kibana Lucene, or Wazuh. Returns the primary converted query plus conversion lossiness warnings (e.g. unsupported modifiers). Missing pySigma or missing backend packages return actionable error envelopes with the exact pip install command.

ParametersJSON Schema
NameRequiredDescriptionDefault
yaml_contentYes
targetNosplunk
configNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description carries the full burden. It discloses successful output (converted query + warnings) and failure modes (missing pySigma or backend packages yield actionable pip install commands). Does not discuss auth or rate limits, but these are irrelevant for a conversion tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the main action and uses a clear structure: purpose, usage, details. It is concise with three sentences, no redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 parameters, no annotations, and an output schema (not shown), the description covers purpose, usage, primary output, and error handling. It lacks parameter explanations but is adequate for a simple conversion tool when combined with the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%. The description only implicitly associates yaml_content with the sigma rule and target with backend names, but does not explain the config parameter or enumerate target options. It adds limited semantic value beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it converts a sigma YAML rule to a SIEM-native query string, specifying three target backends. It distinguishes from sibling tools 'draft_rule' and 'validate_rule' by focusing on conversion rather than drafting or validation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Use when the caller has a validated sigma rule' and lists target SIEMs. Does not explicitly exclude alternatives, but the context is clear. Mentions return of conversion warnings and error envelopes for missing dependencies.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draft_ruleA

Draft a sigma detection YAML rule from a natural-language threat description.

Use when the caller needs a starting-point sigma rule and only has a plain-English threat summary plus optional MITRE TTP hints. Returns a structured envelope with the YAML body, a pySigma round-trip validation result, the inferred MITRE technique IDs, and draft notes covering redactions + open issues. Tool is deterministic and local -- no network, no LLM call.

ParametersJSON Schema
NameRequiredDescriptionDefault
descriptionYes
rule_typeNoprocess_creation
referencesNo
target_platformNowindows
severityNomedium
mitre_ttpsNo
titleNo
authorNoWRG sigma-rule-writer

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses key behavioral traits: deterministic, local, no network or LLM call, and describes the return envelope contents. No annotations are provided, so the description carries the transparency burden well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the core purpose. It efficiently communicates usage context and behavior without unnecessary words, though could be slightly more structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 8 parameters (1 required) and no schema descriptions, the description adequately covers the main input and optional MITRE hints but lacks detail on other parameters. The output schema is mentioned, which adds completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, yet the description only explains the 'description' and 'mitre_ttps' parameters. Other parameters like rule_type, references, target_platform, severity, title, and author are left unspecified, requiring inference from defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool drafts a sigma detection YAML rule from natural language, distinguishing it from sibling tools convert_rule and validate_rule.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: when a starting-point sigma rule is needed from a plain-English threat summary. Does not mention when not to use or discuss alternatives explicitly, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_ruleA

Validate a sigma YAML rule for schema correctness, pySigma compatibility, and best-practices linting.

    Use when the caller has a sigma rule (drafted, pasted, or
    read from disk) and needs to know whether it is parseable, spec
    compliant, and free of common quality smells (empty references,
    missing falsepositives, missing MITRE tag, vague condition).
    ``target_backend`` is informational at this layer; the linter is
    backend-agnostic. ``strict=True`` promotes warnings into the
    error list.
    
ParametersJSON Schema
NameRequiredDescriptionDefault
yaml_contentYes
target_backendNodefault
strictNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It describes specific checks (empty references, missing falsepositives, missing MITRE tag, vague condition). It also notes strict mode behavior and that target_backend is informational. No side effects mentioned but no destructive hints either.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise at ~80 words, front-loaded with purpose. Every sentence adds value. No repetition or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given output schema exists (not shown), return values need not be explained. Description covers validation specifics, sibling differentiation, and parameter roles. Could briefly mention that it returns a list of issues, but output schema likely covers that.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so description compensates. It explains yaml_content is the rule to validate, target_backend is informational, and strict promotes warnings to errors. Adds meaningful context beyond bare parameter names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool validates sigma YAML rules for schema correctness, pySigma compatibility, and best-practices linting. It distinguishes from siblings (convert_rule, draft_rule) by focusing on validation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit use cases are given (rule drafted, pasted, or read from disk). It mentions when to use it: to check parseability, spec compliance, and quality. Does not explicitly state when not to use it but provides clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv1.0.0
    • First observedconvert_rule
    • First observeddraft_rule
    • First observedvalidate_rule

TDQS

A4.3/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clear, non-overlapping purpose: drafting, validating, and converting Sigma rules. There is no ambiguity between them.

Naming Consistency5/5

All tool names follow the consistent verb_noun pattern (convert_rule, draft_rule, validate_rule), making them predictable and easy to understand.

Tool Count5/5

Three tools perfectly cover the core lifecycle of Sigma rules (create, validate, convert) without being too few or excessive.

Completeness5/5

The tool set provides a complete workflow for handling Sigma rules: drafting from description, validating for correctness, and converting to SIEM queries. No obvious gaps exist.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A Claude-powered MCP tool suite for interacting with a Wazuh SIEM manager, enabling triage, health monitoring, threat hunting, rule management, and active response execution.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables natural-language security operations by connecting Wazuh SIEM to Claude Desktop via MCP, allowing querying of alerts, agents, vulnerabilities, and generating security reports with Slack integration.
    1
    -
  • A
    license
    A
    quality
    A
    maintenance
    RSigma is a Rust detection-engineering toolkit for the Sigma standard. Its MCP server (rsigma mcp serve) exposes the toolchain to AI agents over stdio or Streamable HTTP, with tools to author, lint, validate, and convert Sigma rules, evaluate and explain detections against log events, and inspect correlation state.
    15
    138
    MIT