Writing Sigma Rules logo

Writing Sigma Rules

Community
trilwu
writing-sigma-rules

Author and maintain Sigma detection rules — structure, logsource taxonomy, detection logic with modifiers, false-positive filtering, backend conversion with pySigma, and offline validation with Hayabusa or Chainsaw. Use when translating threat intel into vendor-agnostic detection logic, building a detection-as-code pipeline around Sigma, reviewing or tuning existing Sigma rules, or converting rules across SIEM backends.

Overview

Publishertrilwu
Repositorysecskills
Skill namewriting-sigma-rules
Stars
144
Forks
15
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by trilwu on GitHub. Read the source before you install it.

Installation

Install the Writing Sigma Rules AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/trilwu/secskills.git /tmp/secskills
mkdir -p .claude/skills
cp -r /tmp/secskills/secskills-defense/skills/writing-sigma-rules .claude/skills/writing-sigma-rules
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Writing Sigma Rules in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Writing Sigma Rules on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Writing Sigma Rules is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Writing Sigma Rules

Sigma is the common language for detection logic -- write once, convert to any SIEM. The value is portability and reviewability, but only if the rule is precise: a Sigma rule that matches everything is worse than no rule, because it consumes analyst time and trains the team to ignore alerts. The work is specificity without brittleness.

When to Use

  • Translating a TTP, threat intel report, or incident finding into a portable detection rule
  • Writing vendor-agnostic detection logic that converts to multiple SIEM backends
  • Building or maintaining a detection-as-code pipeline centered on Sigma
  • Reviewing or tuning existing Sigma rules for precision and false-positive reduction
  • Converting Sigma rules between backends (Splunk, Elastic, Sentinel, CrowdStrike, Chronicle)
  • Contributing rules upstream to SigmaHQ or maintaining a private rule repository

When NOT to Use

  • Broader detection engineering including YARA, Suricata, and the full detection lifecycle -- use engineering-detections
  • The signature belongs on files or memory, not log telemetry -- use writing-yara-rules
  • Hypothesis-driven threat hunting, not rule writing -- use hunting-threats
  • Active incident response, not rule development -- use responding-to-incidents

Sigma Rule Structure

Every rule is a YAML document with these fields in order:

The specification requires only three fields: title, logsource, and detection (which must contain a condition). Everything else is optional to the spec. Do not confuse that with the SigmaHQ rule repository, which requires far more — id, status, description, author, date, level, and ATT&CK tags — before it will accept a contribution. Write to the stricter SigmaHQ convention by default, because a rule without an id or a level is unmanageable in a real pipeline, but know which constraint you are meeting when a converter accepts a rule your reviewer rejects.

yaml
title: Short Descriptive Name              # REQUIRED by spec, max ~100 chars
id: a1b2c3d4-0000-4000-8000-000000000001  # optional to spec; UUIDv4, never reuse
related:                                    # optional, link to predecessor rules
  - id: <uuid>
    type: derived | obsoletes | merged | renamed | similar
status: experimental                        # optional; see lifecycle below
description: >                              # optional to spec, expected by SigmaHQ
  Detects X behaviour consistent with Y technique.
references:                                 # optional, strongly recommended
  - https://attack.mitre.org/techniques/T1059/001/
author: Your Name                           # optional to spec
date: 2026-07-26                            # optional; ISO 8601 YYYY-MM-DD
modified: 2026-07-26                        # optional; same format, on update
tags:                                       # optional to spec, expected by SigmaHQ
  - attack.execution                        #   tactic (lowercase, dotted)
  - attack.t1059.001                        #   technique (lowercase)
logsource:                                  # REQUIRED by spec
  category: process_creation
  product: windows
detection:                                  # REQUIRED by spec
  selection:
    CommandLine|contains: 'some-indicator'
  condition: selection                      # REQUIRED inside detection
falsepositives:                             # optional to spec
  - Legitimate admin scripts using the same flag
level: medium                               # optional; informational|low|medium|high|critical

Date format. The spec mandates ISO 8601 with hyphens — YYYY-MM-DD. Older rules and much online material use the legacy YYYY/MM/DD; that form is outdated, and some tooling now rejects it.

Status lifecycle. The permitted values are experimental, test, stable, deprecated, and unsupported. In practice: experimental = observation only, no alerting. test = validated against emulation, ready for limited deployment. stable = tuned in production with documented FPs. deprecated = replaced, no longer accurate. unsupported = not usable as written (e.g. depends on homemade fields). Never promote without the corresponding work.

Logsource Taxonomy

The logsource block abstracts the data source. Specify only what is needed.

Categories: process_creation, file_event, file_access, network_connection, registry_event, dns_query, image_load, pipe_created, process_access, driver_load, create_remote_thread.

Product: windows, linux, macos.

Service: sysmon, security, system, powershell, powershell-classic, application, taskscheduler, windefend, firewall-as.

Use category when you care about the event type regardless of collection method. Use product + service when targeting a specific log channel. Do not combine category and service unless the backend requires it.

Detection Logic

Selection and filter pattern

Define what to match (selection), what to exclude (filter_*), combine in condition:

yaml
detection:
  selection:
    ParentImage|endswith: '\explorer.exe'
    CommandLine|contains|all:
      - 'powershell'
      - '-enc'
  filter_legitimate:
    CommandLine|contains: 'company-deploy-script'
    User|startswith: 'SVC_'
  condition: selection and not filter_legitimate

Condition syntax

condition: selection                           # simple match
condition: selection and not filter            # match minus exclusions
condition: selection1 or selection2            # either pattern
condition: (sel1 and sel2) and not (fp1 or fp2)
condition: all of selection*                   # all blocks starting with "selection"
condition: 1 of selection*                     # any one block

Keywords

Match against the full log event (all fields). Blunt instrument -- prefer field-specific selections for production rules:

yaml
detection:
  keywords:
    - 'Invoke-Mimikatz'
    - 'sekurlsa::logonpasswords'
  condition: keywords

Modifiers

Chain with |. Example: CommandLine|contains|all.

ModifierEffect
containsSubstring match
startswith / endswithPrefix / suffix match
reRegular expression (PCRE)
base64offsetMatch base64-encoded variants at all three offsets
allAll list values must match (default is any)
cidrCIDR network range match on IP fields
windashMatch both - and / as argument prefix
expandExpand environment variables like %SystemRoot%
wide / utf16le / utf16be / utf16Match the wide (UTF-16) encoding of the value; wide is an alias for utf16le. There is no utf8 modifier
existsField present (true) or absent (false)

Common Detection Patterns

Process creation -- suspicious command line

yaml
detection:
  selection:
    CommandLine|contains|windash|all: ['bypass', 'hidden', 'noprofile']
  filter_admin:
    ParentImage|endswith: ['\sccm.exe', '\intune_agent.exe']
  condition: selection and not filter_admin

Parent-child relationship (Office spawning shell)

yaml
detection:
  selection:
    ParentImage|endswith: '\winword.exe'
    Image|endswith: ['\cmd.exe', '\powershell.exe', '\wscript.exe', '\mshta.exe']
  condition: selection

File creation in suspicious paths

yaml
detection:
  selection:
    TargetFilename|contains: ['\AppData\Local\Temp\', '\ProgramData\', '\Users\Public\']
    TargetFilename|endswith: ['.exe', '.dll', '.scr', '.hta']
  condition: selection

Registry persistence (run keys)

yaml
detection:
  selection:
    TargetObject|contains: ['\CurrentVersion\Run\', '\CurrentVersion\RunOnce\']
    EventType: SetValue
  filter_installers:
    Image|startswith: 'C:\Windows\Installer\'
  condition: selection and not filter_installers

Named pipe creation (C2 indicators)

yaml
detection:
  selection:
    PipeName: ['\MSSE-*', '\postex_*', '\msagent_*', '\status_*']
  condition: selection

WMI event subscription and scheduled task creation

WMI: logsource product: windows, service: sysmon, match EventID: 21, Operation: Created. Scheduled tasks: logsource category: process_creation, match Image|endswith: '\schtasks.exe' with CommandLine|contains|all: ['/create', '/sc'], filter on SYSTEM + known management tools.

False Positive Handling

The filter pattern

Exclusions go in named filter_* blocks, never inline with the selection. Use condition: selection and not 1 of filter_* to apply all filters.

Known-good exclusions

Filter on properties the attacker cannot control: full file paths of signed vendor binaries (not filenames alone), service account SIDs (not usernames), parent-child pairs from specific software workflows, verified certificate subjects. Never filter on filenames alone, attacker-controllable command-line fragments, or hostnames without justification.

Severity calibration

LevelResponse expectation
informationalAutomated tagging, correlation input only
lowBatch review, daily triage
mediumAnalyst queue, investigate within hours
highPrompt investigation, likely malicious
criticalImmediate response, active compromise

Set level based on expected TP rate and business impact, not on how dangerous the technique sounds. A noisy critical rule causes more damage than a precise medium one.

Correlation rules

When a single event is too common to alert on, use Sigma correlation rules that reference other rules by ID, group by a field (e.g., ComputerName), and require a threshold within a time window:

yaml
title: Correlation - Multiple Suspicious Events from Same Host
type: correlation
rules:
  - id: <uuid-of-rule-1>
  - id: <uuid-of-rule-2>
group-by: [ComputerName]
timespan: 15m
condition:
  gte: 2
level: high

Backend Conversion

sigma-cli with pySigma

bash
pip install sigma-cli pySigma-backend-splunk pySigma-backend-elasticsearch \
  pySigma-backend-kusto pySigma-backend-qradar

sigma convert -t splunk -p sysmon rules/rule.yml
sigma convert -t elasticsearch -p ecs_windows rules/rule.yml
sigma convert -t kusto -p microsoft_xdr rules/rule.yml
sigma convert -t qradar rules/rule.yml
sigma convert -t splunk -p sysmon rules/                     # entire directory
sigma convert -t splunk -p sysmon -f savedsearches rules/    # output format

Pipeline selection

BackendCommon pipelines
Splunksysmon, splunk_windows, splunk_cim
Elasticecs_windows, ecs_zeek, filebeat
Sentinel/XDRmicrosoft_xdr, azure_monitor
CrowdStrikecrowdstrike
Chroniclechronicle_default

Always verify converted output against your actual field names. Pipeline defaults may not match custom parsing configurations.

Testing and Validation

Schema validation

bash
sigma check rules/rule.yml       # single rule
sigma check rules/               # entire directory

Common failures: missing or duplicate id, invalid level, malformed YAML, undefined modifier, empty detection block.

Offline validation against EVTX

bash
hayabusa csv-timeline -d ./sample_evtx/ -r rules/rule.yml
chainsaw hunt ./sample_evtx/ -s rules/rule.yml --mapping mappings/sigma-mapping.yml

Testing workflow

  1. Collect sample logs. Run the technique in a lab (Atomic Red Team, Caldera) and capture EVTX or JSON.
  2. Verify detection. Run Hayabusa/Chainsaw -- rule must fire on the TP log.
  3. Verify exclusion. Run against clean baseline. Every hit characterized.
  4. Convert and test. Run the backend query against 7+ days of production data. Characterize every match.
  5. Document. Record TP/FP counts, FP causes, filters added. Update the rule's falsepositives field and the PR description.

Quality Standards

SigmaHQ requirements: valid UUIDv4 id; status set appropriately (experimental for new); date/modified in YYYY/MM/DD; at least one ATT&CK tag; non-empty falsepositives (even Unknown); level based on TP rate; descriptive description; references linking to source intel.

YAML formatting: two-space indent, no tabs; pipe-separated modifiers without spaces (field|contains|all); dash-space lists; single-quoted strings with special characters; folded scalar (>) for long descriptions; one rule per file, snake_case filename matching the title.

Field naming: use Sigma standard names (Image, ParentImage, CommandLine, User, TargetFilename, TargetObject, DestinationIp, DestinationPort, SourceIp, PipeName, Hashes). Backend conversion handles translation. Writing backend-specific field names defeats portability.

Tag compliance: attack.<tactic> (lowercase, hyphenated) and attack.t<number> (lowercase, dotted sub-technique). Add cve.YYYY.NNNNN when applicable. Verify IDs against the current ATT&CK release -- stale IDs from retired techniques create mapping errors downstream.

Rationalizations to Reject

  • "The rule is simple enough, it does not need testing." Simple rules have the widest match surface. The simpler the logic, the more important the FP analysis.
  • "We will add filters after it goes live." Every hour a noisy rule runs in production erodes analyst trust. Test and filter before deployment.
  • "Just use keywords, field-specific matching is too narrow." Keywords match across all fields. A hit on a hostname that contains the string is noise.
  • "The converted output looks right, no need to test it." Conversion assumes your field mappings match pipeline defaults. Verify against actual data.
  • "One rule per technique is enough." Techniques have many procedures. T1059 covers PowerShell, cmd, bash, Python, VBScript -- each needs its own logic.
  • "The rule works in Splunk, so it works everywhere." Portability requires correct logsource abstraction. Backend-specific field names break it.
  • "Set it to critical -- credential dumping is always critical." Severity reflects signal quality, not technique category. A noisy critical rule causes more damage than a precise medium one.

Reading External Sources

Fetch public advisories, specifications, and vendor reports as Markdown:

bash
curl -sL "https://defuddle.md/<url>"      # scheme in the path is optional

This strips page boilerplate — roughly 78% fewer tokens on a prose page — and returns the full text rather than a summary, so you can grep it and trust a negative result.

Three things it is not for. Fetch JSON and API responses raw, because readability extraction mangles structured data. Fetch authenticated or JavaScript-rendered pages directly, because it retrieves them anonymously. And never route adversary infrastructure (phishing links, C2, malware hosting), client-owned hosts, or engagement URLs through it — the request leaves your machine to a third party, and for live adversary infrastructure it also tips off the operator.

Some sites block the extractor and return an error blob rather than the page — {"error":"Failed to fetch: 418 I'm a teapot"} from freedesktop.org, for instance. That is the fetch being refused, not the source saying the thing does not exist. Re-fetch the URL directly before drawing any conclusion from it.

References

  • engineering-detections -- the full detection lifecycle including YARA, Suricata, and coverage measurement
  • hunting-threats -- hypothesis-driven hunting that produces the findings rules are built from
  • mapping-attack-techniques -- ATT&CK technique resolution and the purple-team loop
  • reporting-security-findings -- writing up what the detection found

Frequently asked questions

What does the Writing Sigma Rules AI skill do?

Author and maintain Sigma detection rules — structure, logsource taxonomy, detection logic with modifiers, false-positive filtering, backend conversion with pySigma, and offline validation with Hayabusa or Chainsaw. Use when translating threat intel into vendor-agnostic detection logic, building a detection-as-code pipeline around Sigma, reviewing or tuning existing Sigma rules, or converting rules across SIEM backends.

Why use Writing Sigma Rules on TypingMind?

Because you install it once and use it with any model. Writing Sigma Rules is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Writing Sigma Rules in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/trilwu/secskills/tree/main/secskills-defense/skills/writing-sigma-rules. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Writing Sigma Rules?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Writing Sigma Rules?

As many as you like. As long as a model supports skills, you can use Writing Sigma Rules with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Writing Sigma Rules AI skill free?

Yes. It is published on GitHub by trilwu under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇