Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions json-schema/sigmahq-regression-data-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema#",
"title": "SigmaHQ Regression Test info.yml",
"description": "Specification for regression test metadata files used by the SigmaHQ regression test runner.",
"type": "object",
"required": [
"id",
"description",
"date",
"author",
"rule_metadata",
"regression_tests_info"
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "A unique UUID for this regression test entry. Different from the rule ID."
},
"description": {
"type": "string",
"description": "Free-text description of what the test verifies. Use \"N/A\" if no description is available."
},
"date": {
"type": "string",
"format": "date",
"description": "ISO date (YYYY-MM-DD) when the regression test was created or last updated."
},
"author": {
"type": "string",
"description": "Full name of the author, optionally followed by organization in parentheses."
},
"rule_metadata": {
"type": "array",
"minItems": 1,
"description": "Metadata linking this regression test to the Sigma rule it validates.",
"items": {
"type": "object",
"required": ["id", "title"],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "The Sigma rule UUID. Must exactly match the id field in the corresponding .yml rule file."
},
"title": {
"type": "string",
"description": "The Sigma rule title. Should match the title field in the corresponding .yml rule file."
}
}
}
},
"regression_tests_info": {
"type": "array",
"minItems": 1,
"description": "List of regression test entries. Currently only Positive Detection Test type is supported.",
"items": {
"type": "object",
"required": ["name", "type", "path"],
"properties": {
"name": {
"type": "string",
"enum": ["Positive Detection Test"],
"description": "Human-readable test name. Currently only \"Positive Detection Test\" is supported."
},
"type": {
"type": "string",
"enum": ["evtx"],
"description": "Test type. Currently only \"evtx\" is supported by the runner. \"raw\", \"json\", and \"log\" are reserved for future use."
},
"provider": {
"type": "string",
"description": "Windows event provider used by the evtx-sigma-checker. All existing tests include it, but the runner does not enforce its presence."
},
"match_count": {
"type": "integer",
"minimum": 1,
"description": "Minimum number of matches required. If omitted, the runner requires at least one match. If actual count exceeds this value, a warning is emitted rather than a failure."
},
"path": {
"type": "string",
"description": "Relative path from the repository root to the test sample file."
}
}
}
}
},
"additionalProperties": false
}
214 changes: 214 additions & 0 deletions sigmahq/sigmahq-regression-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# SigmaHQ Regression Data Specification

This document describes the specification for regression test data in the SigmaHQ repository. Regression tests ensure that Sigma rules correctly detect their intended events by running them against known log samples stored alongside `info.yml`.

<!-- mdformat-toc start --slug=github --no-anchors --maxlevel=6 --minlevel=2 -->

- [Overview](#overview)
- [Directory Structure](#directory-structure)
- [The `info.yml` File](#the-infoyml-file)
- [Required Fields](#required-fields)
- [Field Descriptions](#field-descriptions)
- [Linking Regression Tests to Sigma Rules](#linking-regression-tests-to-sigma-rules)
- [In the Sigma Rule YAML File](#in-the-sigma-rule-yaml-file)
- [Path Convention](#path-convention)
- [Test Sample File Naming Convention](#test-sample-file-naming-convention)
- [Test Types](#test-types)
- [Positive Detection Test](#positive-detection-test)
- [Status Requirements](#status-requirements)
- [Validation](#validation)

<!-- mdformat-toc end -->

## Overview

Regression tests are defined by an `info.yml` file placed alongside log samples in the `regression_data/` directory. The regression test runner (`tests/regression_tests_runner.py`) validates that each Sigma rule produces the expected number of matches against its associated test samples.

## Directory Structure

```
regression_data/
├── rules/
│ ├── windows/
│ │ ├── process_creation/
│ │ │ └── proc_creation_win_cipher_overwrite_deleted_data/
│ │ │ ├── info.yml
│ │ │ └── <rule-id>.<ext>
│ │ ├── registry/
│ │ │ └── registry_set/
│ │ │ └── registry_set_disable_defender_firewall/
│ │ │ ├── info.yml
│ │ │ └── <rule-id>.<ext>
│ │ └── ...
│ ├── process_access/
│ ├── image_load/
│ ├── file/
│ ├── sysmon/
│ ├── builtin/
│ └── cisco/
├── rules-emerging-threats/
│ ├── 2025/
│ │ ├── Exploits/
│ │ ├── Malware/
│ │ └── ...
│ └── 2026/
│ └── Exploits/
└── rules-threat-hunting/
└── windows/
└── image_load/
```

`<ext>` is the file extension determined by the `type` field in `info.yml` (currently only `evtx` is supported by the runner).

The directory name under `regression_data/` must match the rule file name stem (without the `.yml` extension). For example, the rule `proc_creation_win_cipher_overwrite_deleted_data.yml` uses the directory `proc_creation_win_cipher_overwrite_deleted_data/`.

The `regression_data/` directory mirrors the `rules/` directory structure: a rule at `rules/windows/process_creation/proc_creation_win_foo.yml` maps to `regression_data/rules/windows/process_creation/proc_creation_win_foo/`.

**Note:** The `regression_data/` path structure mirrors the corresponding rule's location in `rules/` or `rules-emerging-threats/` or `rules-threat-hunting/`. This means the `info.yml` directory name must match the rule file name stem.

## The `info.yml` File

Every regression test directory must contain an `info.yml` file with the following structure:

### Required Fields

```yaml
id: <uuid> # UUID for the regression test entry (different from rule ID)
description: <free-text description or "N/A"> # Human-readable description of the test scenario
date: YYYY-MM-DD # Date the regression test was added
author: <Author Name> # Author of the regression test
rule_metadata:
- id: <rule-uuid> # Must match the Sigma rule's `id` field exactly
title: <Rule Title> # Must match the Sigma rule's `title` field exactly
regression_tests_info:
- name: Positive Detection Test # Test name (use "Positive Detection Test" for positive tests)
type: evtx # Test type: only `evtx` is currently supported
provider: Microsoft-Windows-Sysmon # Log provider (optional, required for evtx)
match_count: 1 # Minimum number of matches required. Omit to require at least one match.
path: regression_data/<path>/<to>/<rule-dir>/<rule-id>.<ext>
```

### Field Descriptions

| Field | Description |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | A unique UUID for this regression test entry. Different from the rule `id`. |
| `description` | Free-text description of what the test verifies. Use `"N/A"` if no description is available. |
| `date` | ISO date (YYYY-MM-DD) when the regression test was created or last updated. |
| `author` | Full name of the author, optionally followed by organization in parentheses. |
| `rule_metadata.id` | The Sigma rule UUID. **Must exactly match** the `id` field in the corresponding `.yml` rule file. |
| `rule_metadata.title` | The Sigma rule title. **Must exactly match** the `title` field in the corresponding `.yml` rule file. |
| `regression_tests_info[].name` | Human-readable test name. Use `"Positive Detection Test"` for tests that verify the rule matches. |
| `regression_tests_info[].type` | Test type. Currently only `evtx` is supported by the runner. `raw`, `json`, and `log` are reserved for future use. |
| `regression_tests_info[].provider` | Windows event provider used by the evtx-sigma-checker. All existing tests include it, but the runner does not enforce its presence. |
| `regression_tests_info[].match_count` | Minimum number of matches required. If omitted, the runner requires at least one match. If actual count exceeds this value, a warning is emitted rather than a failure. |
| `regression_tests_info[].path` | Relative path from the repository root to the test sample file. |

## Linking Regression Tests to Sigma Rules

### In the Sigma Rule YAML File

Add the `regression_tests_path` field pointing to the `info.yml` file:

```yaml
title: Deleted Data Overwritten Via Cipher.EXE
id: 4b046706-5789-4673-b111-66f25fe99534
status: test
description: |
Detects usage of cipher.exe to overwrite deleted files.
author: Author Name
date: 2025-10-24
tags:
- attack.defense-impairment
- attack.t1070
logsource:
category: process_creation
product: windows
detection:
selection:
CommandLine|contains:
- '/w'
- 'cipher'
condition: selection
falsepositives:
- Legitimate disk cleanup operations
level: medium
regression_tests_path: regression_data/rules/windows/process_creation/proc_creation_win_cipher_overwrite_deleted_data/info.yml
```

### Path Convention

The `regression_tests_path` value is a relative path from the repository root:

- For rules in `rules/windows/`: `regression_data/rules/windows/<category>/<rule-name>/info.yml`
- For rules in `rules-emerging-threats/`: `regression_data/rules-emerging-threats/<year>/<category>/<name>/info.yml`
- For rules in `rules-threat-hunting/`: `regression_data/rules-threat-hunting/<category>/<rule-name>/info.yml`

## Test Sample File Naming Convention

Test sample files are named using the Sigma rule's UUID as the stem:

```
<rule-id>.<ext>
```

The extension depends on the `type` field in `info.yml`:

| `type` | Expected extension | Example |
| ------ | ------------------ | ------------------------------------------- |
| `evtx` | `.evtx` | `4b046706-5789-4673-b111-66f25fe99534.evtx` |
| `json` | `.json` | Not yet supported by the test runner |
| `log` | `.log` | Not yet supported by the test runner |
| `raw` | `.raw` | Not yet supported by the test runner |

For example, for rule `id: 4b046706-5789-4673-b111-66f25fe99534` with `type: evtx`, the file must be:

```
regression_data/rules/windows/process_creation/proc_creation_win_cipher_overwrite_deleted_data/4b046706-5789-4673-b111-66f25fe99534.evtx
```

A companion JSON file may also be included as a human-readable conversion of the `.evtx` file for debugging purposes:

```
regression_data/rules/windows/process_creation/proc_creation_win_cipher_overwrite_deleted_data/4b046706-5789-4673-b111-66f25fe99534.json
```

Companion files are optional. When included, they must follow the same naming convention (rule ID as stem) and must match the rule `id` for the runner to accept them.

## Test Types

### Positive Detection Test

Verifies that the Sigma rule correctly matches the provided test sample.

```yaml
regression_tests_info:
- name: Positive Detection Test
type: evtx
provider: Microsoft-Windows-Sysmon
match_count: 1
path: regression_data/.../4b046706-5789-4673-b111-66f25fe99534.evtx
```

**Match count rules:**

- `match_count: 1` — the default for standard positive detection tests. Explicitly setting it is optional.
- `match_count: N` (where N > 1) — used when the test sample contains multiple events that each produce a match, or when the rule's detection logic has multiple conditions that each match once against the sample. Examples:
- `match_count: 2` — the rule matches twice against the sample (e.g., a rule with two `selection_*` conditions, each triggered by a different event in the same file).
- `match_count: 4` — four matching events are expected.
- `match_count: 7` — seven matching events are expected.

**How to determine `match_count`:** Run the regression test runner and read the output. If the actual match count exceeds `match_count`, a warning is emitted showing the actual count — use that value as your new `match_count`.

## Status Requirements

Rules with `status: test` or `status: stable` **must** have a `regression_tests_path` field pointing to a valid `info.yml`. Rules with `status: experimental` or `status: deprecated` are exempt from this requirement but may still include regression tests.

## Validation

The regression test runner (`tests/regression_tests_runner.py`) performs the following validations:

1. **Rule ID consistency**: `rule_metadata[0].id` in `info.yml` must match the `id` field in the Sigma rule YAML.
1. **File naming**: The test sample file name (without extension) must match the rule `id`.
1. **File existence**: All referenced files (`info.yml` and test samples) must exist.
1. **Match count**: The rule must produce at least the expected number of matches against the test sample. If the actual match count exceeds `match_count`, a warning is emitted (rather than a failure) to encourage updating the `info.yml`.
6 changes: 3 additions & 3 deletions specification/sigma-appendix-tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ The following document defines the standardized tags that can be used to categor

### Namespace: attack

- t*1234*: Refers to a [technique](https://attack.mitre.org/wiki/All_Techniques)
- g*1234*: Refers to a [group](https://attack.mitre.org/wiki/Groups)
- s*1234*: Refers to [software](https://attack.mitre.org/wiki/Software)
- t*1234*: Refers to a [technique](https://attack.mitre.org/techniques/)
- g*1234*: Refers to a [group](https://attack.mitre.org/groups/)
- s*1234*: Refers to [software](https://attack.mitre.org/software/)
- ds*1234*: Refers to [Data sources](https://attack.mitre.org/datasources/)
- m*1234*: Refers to [Mitigations](https://attack.mitre.org/mitigations/)
- a*1234*: Refers to [Assets](https://attack.mitre.org/assets/)
Expand Down
2 changes: 1 addition & 1 deletion specification/sigma-appendix-taxonomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ The field names follow the field names used in [Sysmon](https://docs.microsoft.c
| Product | Google Update | |
| Company | Google Inc. | |
| CommandLine | "C:\\Program Files (x86)\\Google\\Update\\GoogleUpdate.exe" /ua /installsource scheduler | |
| CurrentDirectory | C:\\Windows\\system32\| | |
| CurrentDirectory | C:\\Windows\\system32 | |
| User | NT AUTHORITY\\SYSTEM | |
| LogonGuid | {c1b49677-3fb9-5c09-0000-0020e7030000} | |
| LogonId | 0x3e7 | |
Expand Down
Loading