You don’t have to build your detection-as-code system from scratch. Elastic, Panther Labs, Splunk, and the SigmaHQ community have all published their detection repositories publicly. Reading them reveals patterns you can adopt — and trade-offs you should understand before choosing an approach.
Elastic detection-rules
Repository: github.com/elastic/detection-rules
Format
Elastic uses TOML format instead of Sigma YAML:
# rules/windows/credential_access_lsass_memdump.toml
[metadata]
creation_date = "2020/02/18"
integration = ["endpoint"]
updated_date = "2024/03/08"
[rule]
author = ["Elastic"]
description = """
Detects attempts to access credential material stored in the Local Security
Authority Subsystem Service (LSASS) process memory.
"""
from = "now-9m"
index = ["logs-endpoint.events.process-*", "winlogbeat-*"]
language = "eql"
name = "LSASS Memory Dump Handle Access"
rule_id = "208dbe77-01ed-4954-8d44-1e5751cb20de"
severity = "high"
tags = ["Domain: Endpoint", "OS: Windows", "Tactic: Credential Access",
"Data Source: Elastic Endgame", "Use Case: Threat Detection"]
type = "eql"
query = '''
process where host.os.type == "windows" and event.type == "start" and
process.Ext.token.integrity_level_name : "high" and
process.parent.name : ("cmd.exe", "powershell.exe", "rundll32.exe")
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1003"
name = "OS Credential Dumping"
reference = "https://attack.mitre.org/techniques/T1003/"
Testing
# tests/unit/test_all_rules.py
from detection_rules.rule import TOMLRule
def test_rule_format(rule: TOMLRule):
"""Validates all rules pass schema validation."""
errors = rule.validate()
assert not errors, f"Rule {rule.name} failed validation: {errors}"
def test_rule_has_tests():
"""Ensures rules with high severity have test files."""
...
The Python Management CLI
# Elastic provides a full management CLI
python -m detection_rules --help
# Validate all rules
python -m detection_rules validate-all
# Export rules to Kibana API format
python -m detection_rules kibana export-rules
# Import to Kibana
python -m detection_rules kibana import-rules
What Elastic does well:
- End-to-end integration with Kibana API (deploy with one command)
- Rule quality enforcement via the Python validation library
- Comprehensive test suite for the rule management tooling itself
Trade-off: Zero portability — rules only work with Elastic. No conversion to other SIEMs.
panther-analysis
Repository: github.com/panther-labs/panther-analysis
Format
Rules are Python functions:
# aws_cloudtrail_rules/aws_root_activity.py
from panther_base_helpers import aws_rule_context
def rule(event):
"""Detect AWS root account activity."""
return (
event.get("userIdentity", {}).get("type") == "Root"
and event.get("eventType") != "AwsServiceEvent"
)
def title(event):
return f"Root Account Activity: {event.get('eventName')} in {event.get('awsRegion')}"
def severity(event):
return "CRITICAL" if "Login" in event.get("eventName", "") else "HIGH"
Testing
# aws_cloudtrail_rules/aws_root_activity_test.py
from aws_root_activity import rule
class TestRootActivity:
def test_root_login_fires(self):
event = {
"userIdentity": {"type": "Root"},
"eventName": "ConsoleLogin",
"eventType": "AwsConsoleSignIn"
}
assert rule(event) is True
def test_service_event_excluded(self):
event = {
"userIdentity": {"type": "Root"},
"eventType": "AwsServiceEvent"
}
assert rule(event) is False
Run with standard pytest:
pip install panther-analysis-tool
pat test --path aws_cloudtrail_rules/
What Panther does well:
- Arbitrary logic complexity (Python has no YAML-equivalent constraints)
- Standard pytest tests — any Python developer immediately productive
- Dynamic alert titles and severity based on event content
Trade-off: Python knowledge required; no YAML-based cross-SIEM portability; Panther SIEM dependency.
Splunk security_content
Repository: github.com/splunk/security_content
Format
Splunk uses YAML metadata + raw SPL queries:
# detections/endpoint/ssa___windows_lsass_memory_dump_handle.yml
name: Windows LSASS Memory Dump Handle Access
id: 7ac08779-a5a1-4e48-a29a-2b17fd1c53e9
version: 1
date: '2024-01-15'
author: Splunk Threat Research Team
type: Endpoint
description: |
The following analytic detects attempts to access the LSASS memory.
search: >-
| tstats `security_content_summariesonly` count min(_time) as firstTime
max(_time) as lastTime FROM datamodel=Endpoint.Processes
WHERE `process_lsass_access` BY Processes.user Processes.process_name
Processes.process_id Processes.process_path
| `drop_dm_object_name(Processes)`
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
tags:
analytic_story:
- Credential Dumping
attack_technique:
- T1003.001
confidence: 90
impact: 100
risk_score: 90
Attack Range Integration
Splunk’s CI builds an Attack Range environment and validates detections against real Atomic Red Team test output:
# .github/workflows/detection-testing.yml (excerpt)
- name: Build Attack Range
run: |
cd attack_range
terraform init
terraform apply -auto-approve
- name: Run Atomic Red Team Test
run: |
Invoke-AtomicTest T1003.001 -TestNumbers 1
- name: Validate Detection Fired
run: |
python splunk_client.py search \
--query "$(cat detections/endpoint/windows_lsass.yml | yq .search)" \
--expected-results 1
What Splunk does well:
- Full integration testing against real Atomic Red Team output
- Comprehensive content library across all ATT&CK tactics
- Data model abstractions that work across different Splunk deployments
Trade-off: SPL is Splunk-specific; Attack Range requires cloud infrastructure to run CI; heavy Splunk CIM dependency.
SigmaHQ: The Community Standard
Repository: github.com/SigmaHQ/sigma
The reference implementation. 3,000+ rules, all in Sigma YAML, all community-maintained.
What to borrow
- The
sigmarule style guide — consistent field naming conventions, how to write FP filters, how to structure tags - The contributor workflow — PR template with required fields, how to choose
status,level, andfalsepositives - The testing approach — sigma check as the first CI gate
The contribution lifecycle
1. Author writes rule as experimental
2. Open PR to SigmaHQ/sigma
3. CI runs sigma check + conversion to all backends
4. Community review: correctness, FP risk, coverage overlap
5. Merge as experimental
6. Community tests in real environments
7. Status promoted to test (tested in ≥1 environment)
8. Status promoted to stable (tested in multiple environments, FP rate documented)
Choosing Your Approach
| Situation | Recommended approach |
|---|---|
| Single SIEM (Elastic only) | Fork elastic/detection-rules; use their TOML + Python tooling |
| Single SIEM (Splunk only) | Fork splunk/security_content; use Attack Range for CI testing |
| Multi-SIEM environment | Sigma YAML + sigma-cli + custom pipelines per environment |
| Panther SIEM | Fork panther-analysis; use Python rules + pytest |
| Contributing to community | Sigma YAML → submit to SigmaHQ |
| Starting from scratch, no SIEM preference | Sigma YAML — maximum future portability |