Skip to main content

07 - AI-Assisted Detection Generation: LLMs for Sigma Rule Authoring

AI-Assisted Detection: LLMs for Sigma Rule Generation. The integration of Large Language Models into detection engineering represents one of the major shifts...

What do you think about this article?

At a Glance

AI-Assisted Detection: LLMs for Sigma Rule Generation. The integration of Large Language Models into detection engineering represents one of the major shifts...

AI-Assisted Detection: LLMs for Sigma Rule Generation

Integrating Large Language Models into detection engineering is one of the most significant shifts in the SOC landscape of recent years. This is not simply about automating a repetitive task: using an LLM to generate Sigma rules means compressing into seconds a process that an experienced analyst completes in hours, from reading a threat report to writing a tested, deployment-ready rule.

Frameworks like SigmaGen, presented at MITRE ATT&CK APAC 2025, demonstrate how fine-tuned models can ingest threat intelligence reports, extract ATT&CK techniques, and produce accurately mapped Sigma rules. At the same time, open-source tools and n8n-based workflows allow smaller teams to build AI-assisted pipelines without enterprise-level investment.

This article walks you through the architecture of an AI-assisted system for detection rule generation: from prompt engineering, to automatic validation, to testing with synthetic logs, and finally integration into an existing CI/CD pipeline.

What You Will Learn

  • Why LLMs reason better over Sigma format than direct SPL output
  • Prompt engineering techniques specific to detection rule generation
  • Architecture of an end-to-end AI-assisted pipeline
  • Automatic validation and testing of generated rules
  • Integration with SigmaGen, pySigma and CI/CD workflows
  • Anti-patterns to avoid and real-world LLM limitations in security contexts

Why LLMs Excel at Generating Sigma Rules

One of the most interesting observations from applied research - confirmed in practice - is that LLMs produce significantly higher-quality output when generating Sigma compared to direct SPL or KQL queries. The reason is structural.

Sigma's YAML format enforces a clear separation between:

  • title and description: the model must articulate what it is detecting and why
  • logsource: specifies the data source (category, product, service)
  • detection: the Boolean matching logic
  • condition: how to combine the selectors
  • falsepositives: explicit reasoning about edge cases

This structure forces the model to think sequentially and declaratively, reducing the logical errors that arise when asking directly for platform-specific query language output. In practice, Sigma acts as an implicit chain-of-thought for LLMs applied to detection.

Benchmark Data

Researchers on the LLMCloudHunter project (2024) demonstrated that generalist LLMs like GPT-4 generate valid Sigma rules in 73% of cases on structured CTI reports, compared to 41% when asking for direct SPL output. The rate rises to 89% with fine-tuning on security-specific datasets.

AI-Assisted Pipeline Architecture

An AI-assisted pipeline for detection rule generation consists of five distinct stages:

  1. Ingestion: ingesting threat reports, CTI blog posts, CVE advisories
  2. Extraction: extracting IOCs, ATT&CK techniques, described behaviors
  3. Generation: generating the Sigma rule via LLM
  4. Validation: automatic syntactic and semantic validation
  5. Testing: testing with synthetic logs and CI/CD integration
# Base architecture of the AI-assisted pipeline
# File: ai_sigma_pipeline.py

import openai
import yaml
from pathlib import Path
from dataclasses import dataclass
from typing import Optional

@dataclass
class ThreatReport:
    content: str
    source_url: str
    report_type: str  # 'cti_blog', 'advisory', 'malware_analysis'

@dataclass
class GeneratedRule:
    sigma_yaml: str
    mitre_techniques: list[str]
    confidence: float
    validation_passed: bool
    test_results: Optional[dict] = None

class AISigmaPipeline:
    def __init__(self, openai_api_key: str, rules_output_dir: str):
        self.client = openai.OpenAI(api_key=openai_api_key)
        self.output_dir = Path(rules_output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)

    def process_report(self, report: ThreatReport) -> list[GeneratedRule]:
        """Full pipeline from report to validated rules."""
        techniques = self._extract_attack_techniques(report)
        behaviors = self._extract_behaviors(report)

        rules = []
        for technique in techniques:
            rule = self._generate_sigma_rule(
                report=report,
                technique=technique,
                behaviors=behaviors
            )
            if rule:
                rules.append(rule)

        return [self._validate_and_test(r) for r in rules]

    def _extract_attack_techniques(self, report: ThreatReport) -> list[str]:
        """Extracts ATT&CK techniques from the report via LLM."""
        response = self.client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {
                    "role": "system",
                    "content": (
                        "You are a threat intelligence analyst expert in MITRE ATT&CK. "
                        "Extract ONLY ATT&CK techniques (format T1234 or T1234.001) "
                        "explicitly described in the text. Reply only with a JSON list."
                    )
                },
                {
                    "role": "user",
                    "content": f"Report:\n{report.content[:4000]}"
                }
            ],
            temperature=0.1
        )

        import json
        try:
            return json.loads(response.choices[0].message.content)
        except json.JSONDecodeError:
            return []

Prompt Engineering for High-Quality Sigma Rules

Output quality critically depends on prompt structure. Three fundamental patterns produce consistent results in Sigma rule generation:

Pattern 1: Structured System Prompt

The system prompt must contain exactly the meta-information the model needs to generate valid Sigma: the YAML structure, valid values for category and product, best practices for falsepositives, and allowed severity levels.

# Optimized system prompt for Sigma rule generation
SIGMA_SYSTEM_PROMPT = """
You are a Detection Engineer expert in writing Sigma rules.
When generating a Sigma rule, ALWAYS follow this YAML structure:

title: [descriptive title, max 80 chars]
id: [UUID v4]
status: experimental
description: [detailed description of the detected behavior]
author: AI-Assisted Detection
date: [today's date YYYY-MM-DD]
tags:
  - attack.[tactic]
  - attack.[technique]
logsource:
  category: [process_creation | network_connection | file_event | registry_event]
  product: [windows | linux | macos]
detection:
  [selector_name]:
    [field]: [value or list of values]
  condition: [selector_name]
falsepositives:
  - [plausible legitimate cases]
level: [informational | low | medium | high | critical]

CRITICAL RULES:
- ALWAYS use wildcards (*) in string values to avoid brittle exact matches
- Prefer fields with high availability (Image, CommandLine, ParentImage)
- Always indicate at least one realistic false positive
"""

Pattern 2: Few-Shot with Quality Examples

Including 2-3 high-quality rule examples in the prompt dramatically improves output consistency, especially for unusual logsources or complex conditions.

Pattern 3: Explicit Chain-of-Thought

For complex techniques, asking the model to reason before writing the rule produces more accurate output. This approach adds latency but significantly reduces the number of iterations needed.

def generate_with_cot(self, technique_id: str, report: ThreatReport) -> str:
    """Generation with explicit Chain-of-Thought."""

    # Step 1: Ask the model to reason first
    reasoning_response = self.client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": SIGMA_SYSTEM_PROMPT},
            {
                "role": "user",
                "content": f"""Before writing the rule for {technique_id}, analyze:
1. What forensic artifacts does this technique leave in logs?
2. What is the most appropriate logsource?
3. Which fields have the highest signal/noise discrimination?
4. What are the most common false positives?

Report: {report.content[:2000]}"""
            }
        ],
        temperature=0.3
    )

    reasoning = reasoning_response.choices[0].message.content

    # Step 2: Use the reasoning to guide generation
    rule_response = self.client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": SIGMA_SYSTEM_PROMPT},
            {"role": "user", "content": f"Technical analysis:\n{reasoning}"},
            {
                "role": "assistant",
                "content": "Based on this analysis, I will generate the optimal Sigma rule:"
            },
            {"role": "user", "content": "Proceed with YAML generation."}
        ],
        temperature=0.1
    )

    return rule_response.choices[0].message.content

Automatic Validation of Generated Rules

An LLM can produce syntactically valid but semantically incorrect YAML: a non-existent logsource, a field with the wrong name, a condition that does not correctly reference the selectors. Automatic validation is the critical gate before a rule enters the repository.

import yaml
from sigma.rule import SigmaRule
from sigma.exceptions import SigmaError
import re, uuid

class SigmaRuleValidator:
    VALID_CATEGORIES = {
        'process_creation', 'network_connection', 'file_event',
        'registry_event', 'dns_query', 'image_load', 'pipe_created'
    }
    VALID_LEVELS = {'informational', 'low', 'medium', 'high', 'critical'}

    def validate(self, sigma_yaml: str) -> tuple[bool, list[str]]:
        """Validates a Sigma rule. Returns (valid, errors)."""
        errors = []

        try:
            rule_dict = yaml.safe_load(sigma_yaml)
        except yaml.YAMLError as e:
            return False, [f"Invalid YAML: {str(e)}"]

        # Required fields check
        for field in ['title', 'description', 'logsource', 'detection']:
            if field not in rule_dict:
                errors.append(f"Missing required field: {field}")

        if errors:
            return False, errors

        # Logsource validation
        logsource = rule_dict.get('logsource', {})
        if 'category' in logsource:
            if logsource['category'] not in self.VALID_CATEGORIES:
                errors.append(f"Invalid logsource category: {logsource['category']}")

        # Detection/condition validation
        detection = rule_dict.get('detection', {})
        if 'condition' not in detection:
            errors.append("Missing 'condition' field in detection")

        # UUID validation
        rule_id = rule_dict.get('id', '')
        if rule_id:
            try:
                uuid.UUID(str(rule_id))
            except ValueError:
                errors.append(f"ID is not a valid UUID: {rule_id}")

        # pySigma deep validation
        try:
            SigmaRule.from_yaml(sigma_yaml)
        except SigmaError as e:
            errors.append(f"pySigma error: {str(e)}")

        return len(errors) == 0, errors

Anti-Pattern: Blindly Trusting LLM Output

A common mistake in teams implementing AI-assisted detection is deploying generated rules without validation. LLMs make specific and repeatable errors in Sigma generation:

  • Using ProcessName instead of Image (Sysmon)
  • Writing conditions referencing non-existent selectors
  • Inventing non-standard logsource categories
  • Using contains on fields that do not support wildcards in the target logsource

Automatic validation and testing with real logs are NON-OPTIONAL.

Automated Testing with Synthetic Logs

After syntactic validation, every rule must be tested against logs that simulate both the expected malicious behavior (true positive test) and normal traffic (false positive test). This approach, called rule unit testing, is what distinguishes a mature pipeline from an experiment.

class SigmaRuleTester:
    def generate_test_events(self, sigma_yaml: str, llm_client) -> dict:
        """Generates test events via LLM based on the rule."""
        prompt = f"""Given this Sigma rule:
{sigma_yaml}

Generate in JSON format two event lists:
1. "true_positives": 3 events that MUST trigger the rule
2. "false_positives": 3 legitimate events that must NOT trigger

Format:
{
  "true_positives": [{"Image": "...", "CommandLine": "..."}],
  "false_positives": [{"Image": "...", "CommandLine": "..."}]
}"""

        response = llm_client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.2
        )

        import json
        try:
            return json.loads(response.choices[0].message.content)
        except json.JSONDecodeError:
            return {"true_positives": [], "false_positives": []}

Alternative Models and Cost Considerations

Model Sigma Quality Cost per 100 rules Avg. latency Data residency
GPT-4o High (87% valid) ~$2.50 3-8s Cloud (OpenAI)
GPT-4o-mini Good (71% valid) ~$0.15 1-3s Cloud (OpenAI)
Claude 3.5 Sonnet High (84% valid) ~$3.00 3-6s Cloud (Anthropic)
Llama 3.1 70B (local) Fair (58% valid) ~$0 (infra) 15-45s On-premise
Mistral 7B fine-tuned Good (69% valid) ~$0 (infra) 5-15s On-premise

Cost-Effective Strategy

Use GPT-4o-mini for initial generation and retry iterations (low cost, good quality), and GPT-4o only when mini fails after 2 attempts. With this hybrid approach, the average cost drops to 30% compared to exclusive use of GPT-4o while maintaining comparable quality.

CI/CD Integration for AI-Generated Rules

Generated and validated rules do not go directly to production: they must pass through human review and CI/CD gates of the Detection-as-Code pipeline. The recommended flow has AI generate a Pull Request, not a direct merge.

# GitHub Actions for AI-generated rules
# .github/workflows/ai-sigma-generation.yml
"""
name: AI Sigma Rule Generation
on:
  schedule:
    - cron: '0 6 * * *'
jobs:
  generate-rules:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - name: Run AI pipeline
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: python scripts/ai_sigma_pipeline.py
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v6
        with:
          title: '[AI-Generated] Detection rules from CTI feed'
          labels: 'ai-generated,needs-review'
"""

Conclusions and Next Steps

AI-assisted detection engineering is not a trend: it is an operational necessity for teams that need to keep pace with the speed at which new attack techniques emerge. The combination of LLMs for generation, rigorous automatic validation, and testing with synthetic logs allows reducing time-to-detection from days to hours on a freshly published threat report.

Key Takeaways

  • LLMs produce higher-quality Sigma rules than direct SPL queries thanks to the YAML structure
  • Prompt engineering (structured system prompt, few-shot, chain-of-thought) is critical for quality
  • Automatic syntactic and semantic validation is non-optional
  • Testing with AI-generated synthetic logs closes the quality loop
  • Generated rules must go through human PR review, not automatic merge
  • RAG with SIEM-specific context reduces field errors and false positives
  • Local models (Llama, fine-tuned Mistral) are a valid alternative for data residency requirements

Related Articles

  • Sigma Rules: Universal Detection Logic and SIEM Conversion
  • Detection-as-Code Pipeline with Git and CI/CD
  • Testing Detection Rules: Unit Testing for Security Logic
  • Threat Intelligence Ingestion: STIX/TAXII Feed Processor

Frequently asked questions

What is the main advantage of using Large Language Models (LLMs) for generating Sigma rules?

LLMs can produce significantly higher-quality output when generating Sigma compared to direct SPL or KQL queries, due to their ability to think sequentially and declaratively.

What are some common mistakes teams make when implementing AI-assisted detection, and how can they be avoided?

Teams often deploy generated rules without validation, which can lead to specific and repeatable errors in Sigma generation. Automatic validation and testing with real logs are NON-OPTIONAL to ensure the accuracy of generated rules.

What is the recommended approach for using different LLM models to balance cost and quality in AI-assisted detection?

Using GPT-4o-mini for initial generation and retry iterations, and GPT-4o only when mini fails after 2 attempts, can reduce the average cost by 30% while maintaining comparable quality.

What is the recommended flow for integrating AI-generated rules into a Detection-as-Code pipeline?

The recommended flow has AI generate a Pull Request, not a direct merge, which allows human review and CI/CD gates to ensure the accuracy and reliability of generated rules.

Sources and further reading

Try These Tools

Free developer tools related to this topic.

Commenti

Caricamento commenti...

Sign in to comment

Discuss this article in the community

Join the Telegram group to discuss with other developers, ask questions and share your experiences.

Did you like this article?

Explore other content on the blog or discover my projects