Skip to content
Merged
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
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Install Poetry
run: pipx install poetry
- name: Set up Python 3.12
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Verify versioning
Expand All @@ -28,4 +28,4 @@ jobs:
run: poetry build
- name: Publish to PyPI
if: ${{ github.event_name == 'release' }}
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@release/v1
18 changes: 11 additions & 7 deletions .github/workflows/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Install Poetry
run: pipx install poetry

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: poetry

- name: Install check-jsonschema
run: pip install check-jsonschema
- name: Install dependencies
run: poetry install --no-interaction

- name: Validate JSON files
run: |
check-jsonschema --schemafile ./json-schema/schema_sigmahq_taxonomy.json ./tools/sigmahq_taxonomy.json
check-jsonschema --schemafile ./json-schema/schema_sigmahq_filename.json ./tools/sigmahq_filename.json
check-jsonschema --schemafile ./json-schema/schema_sigmahq_windows_validator.json ./tools/sigmahq_windows_validator.json
poetry run check-jsonschema --schemafile ./json-schema/schema_sigmahq_taxonomy.json ./tools/sigmahq_taxonomy.json
poetry run check-jsonschema --schemafile ./json-schema/schema_sigmahq_filename.json ./tools/sigmahq_filename.json
poetry run check-jsonschema --schemafile ./json-schema/schema_sigmahq_windows_validator.json ./tools/sigmahq_windows_validator.json
6 changes: 4 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ jobs:
cache: poetry
- name: Install dependencies
run: poetry install
- name: Lint with black
run: poetry run black --check .
- name: Install ruff
run: pip install "ruff>=0.12,<1"
- name: Lint with ruff
run: ruff format --check .
- name: Run tests
run: poetry run pytest --cov=sigma --cov-report term --cov-report xml:cov.xml -vv
- name: Store coverage for badge
Expand Down
45 changes: 0 additions & 45 deletions .github/workflows/update_data.yml

This file was deleted.

12 changes: 7 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
repos:
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
2,764 changes: 1,689 additions & 1,075 deletions poetry.lock

Large diffs are not rendered by default.

58 changes: 48 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "pySigma-validators-sigmahq"
version = "0.20.2"
version = "0.20.3"
description = "pySigma SigmaHQ validators"
license = "LGPL-2.1-only"
readme = "README.md"
Expand All @@ -10,16 +10,16 @@ authors = [
{name = "François Hubaut", email = "frack113@users.noreply.github.com" }
]

maintainers =[
maintainers = [
{name = "François Hubaut", email = "frack113@users.noreply.github.com" },
{name = "Christian Burkard", email = "phantinuss@users.noreply.github.com" }
]

keywords = [ "pySigma", "SigmaHQ", "validators"]

dependencies = [
"pysigma >=1.0",
"requests >=2.32"
"pysigma >=1.3",
"requests >=2.34"
]

[project.urls]
Expand All @@ -31,15 +31,53 @@ packages = [
]

[tool.poetry.group.dev.dependencies]
black = "^25.0"
ruff = ">=0.12,<1"
defusedxml = "^0.7"
pytest = "^9.0"
pytest-cov = "^7.0"
mypy = "^1.18"
types-requests = "^2.32"
pytest = "^9.1"
pytest-cov = "^7.1"
mypy = "^2.0"
check-jsonschema = "^0.29"

[tool.black]
[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = ["E", "F", "W", "I001", "S", "PLR"]

[tool.ruff.lint.per-file-ignores]
# F401: Import not used (intentional in __init__.py to expose public API)
"__init__.py" = ["F401"]

# S101: assert is acceptable in tests
# PLR2004: Magic values (e.g., 2) sometimes make more sense than introducing a constant for a one-off comparison
# S108: /tmp usage is acceptable in test fixtures
"tests/**" = ["S101", "PLR2004", "S108"]

# S101: assert is acceptable in tools
"tools/**" = ["S101"]

# PLR0912: Too many branches - complex validation logic in field validators
"sigma/validators/sigmahq/field.py" = ["PLR0912"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

[tool.mypy]
python_version = "3.10"
warn_return_any = false
warn_unused_configs = false
disallow_untyped_defs = false
disallow_incomplete_defs = false
check_untyped_defs = false
disallow_untyped_decorators = false
no_implicit_optional = false
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = ["pytest.*"]
ignore_missing_imports = true

[build-system]
requires = ["poetry-core"]
Expand Down
7 changes: 4 additions & 3 deletions sigma/validators/sigmahq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import re
from importlib import import_module
from inspect import getmembers, isabstract, isclass
from pathlib import Path
from pkgutil import iter_modules
from inspect import getmembers, isabstract, isclass
import re

from sigma.validators.base import SigmaRuleValidator


def validator_classname_to_identifier(name: str) -> str:
"""Convert a validator class name (e.g. NameOfSomeCheckValidator) to an identifier (e.g. name_of_some_check)."""
"""Convert a validator class name (e.g. NameOfSomeCheckValidator) \
to an identifier (e.g. name_of_some_check)."""
return re.sub("([A-Z]+)", "_\\1", name.replace("Validator", ""))[1:].lower()


Expand Down
2 changes: 1 addition & 1 deletion sigma/validators/sigmahq/author.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from dataclasses import dataclass
from typing import ClassVar, List

from sigma.rule import SigmaRule
from sigma.correlations import SigmaCorrelationRule
from sigma.rule import SigmaRule
from sigma.validators.base import (
SigmaRuleValidator,
SigmaValidationIssue,
Expand Down
17 changes: 8 additions & 9 deletions sigma/validators/sigmahq/condition.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
from dataclasses import dataclass
import re
from dataclasses import dataclass
from typing import ClassVar, List

from sigma.correlations import SigmaCorrelationRule
from sigma.rule import SigmaRule
from sigma.validators.base import (
SigmaRuleValidator,
SigmaValidationIssue,
SigmaValidationIssueSeverity,
SigmaRuleValidator,
)


@dataclass
class SigmahqOfthemConditionIssue(SigmaValidationIssue):
description: ClassVar[str] = (
"Rule uses the ' of them' keyword in the condition with only one selection in the detection section"
)
description: ClassVar[str] = "Rule uses the ' of them' keyword in the condition with only one \
selection in the detection section"
severity: ClassVar[SigmaValidationIssueSeverity] = SigmaValidationIssueSeverity.LOW


Expand Down Expand Up @@ -42,9 +42,8 @@ def validate(self, rule: SigmaRule | SigmaCorrelationRule) -> List[SigmaValidati

@dataclass
class SigmahqOfselectionConditionIssue(SigmaValidationIssue):
description: ClassVar[str] = (
"Rule uses the 'All/X of ' format in the condition with only one selection in the detection section"
)
description: ClassVar[str] = "Rule uses the 'All/X of ' format in the condition with only one \
selection in the detection section"
severity: ClassVar[SigmaValidationIssueSeverity] = SigmaValidationIssueSeverity.LOW
selection: str

Expand Down Expand Up @@ -79,7 +78,7 @@ def validate(self, rule: SigmaRule | SigmaCorrelationRule) -> List[SigmaValidati
for selection_name in detection.detections:
if re.match(name, selection_name):
selection_count += 1
if selection_count < 2:
if selection_count < 2: # noqa: PLR2004
return [SigmahqOfselectionConditionIssue([rule], name)]
return []

Expand Down
14 changes: 8 additions & 6 deletions sigma/validators/sigmahq/config.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import json
from pathlib import Path
from typing import Dict, List, Optional

import requests
from sigma.rule import SigmaLogSource

from .data.sigmahq_data import (
taxonomy_version,
ref_sigmahq_logsource_filepattern,
file_pattern_version,
ref_sigmahq_fieldsname,
ref_sigmahq_redundant_field,
ref_sigmahq_logsource_definition,
windows_version,
ref_windows_provider_name,
ref_sigmahq_logsource_filepattern,
ref_sigmahq_redundant_field,
ref_windows_no_eventid,
ref_windows_provider_name,
taxonomy_version,
windows_version,
)
import requests


def core_logsource(source: SigmaLogSource) -> SigmaLogSource:
Expand Down
7 changes: 5 additions & 2 deletions sigma/validators/sigmahq/correlation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ class SigmahqCorrelationRulesMinimumValidator(SigmaRuleValidator):

def validate(self, rule: SigmaRule | SigmaCorrelationRule) -> List[SigmaValidationIssue]:
if isinstance(rule, SigmaCorrelationRule):
if rule.type in [SigmaCorrelationType.TEMPORAL, SigmaCorrelationType.TEMPORAL_ORDERED]:
if len(rule.rules) < 2:
if rule.type in [
SigmaCorrelationType.TEMPORAL,
SigmaCorrelationType.TEMPORAL_ORDERED,
]:
if len(rule.rules) < 2: # type: ignore[arg-type] # noqa: PLR2004
return [SigmahqCorrelationRulesMinimumIssue([rule])]
return []

Expand Down
Loading
Loading