CLI — Diagnostic et sous-commandes¶
regressiondata-check — validation de la régression (cross-platform)¶
check n'est plus une sous-commande des binaires de collecte : c'est un binaire
standalone, regressiondata-check, compilé pour Linux et Windows, sans collector. Il
charge les règles Sigma et les données de régression, rejoue chaque
événement stocké dans le moteur de détection, et vérifie que la règle attendue matche encore.
Usage :
--json— sortie en JSON au lieu du texte lisible.--ignore— saute les entrées invalides (entrée/données brutes absentes, événements vides) sans les compter comme échecs.--fix— normalise les fins de ligne JSON et l'indentationinfo.yml.--path <DIR>— racine du repo sigma (défaut :./sigma).--help,-h— affiche l'usage et sort.
Fonction : validation approfondie de toutes les données de régression dans le
regression_data/ de la racine sigma (./sigma/regression_data par défaut). Les
entrées sont parses selon leur LogType : .evtx via
evtx_reader::parse_evtx_bytes, .log via le parser auditd, lignes JSON directes.
Le logtype Raw est sauté (compté dans Skipped).
Pipeline¶
- Charge toutes les règles Sigma depuis la racine sigma (
./sigmapar défaut,--path <DIR>pour surcharger) - Construit le
DetectionEngineune seule fois en mode lenient (new_lenient) : les règles qui échouent à la compilation sont sautées avec un avertissement, jamais un échec - Charge les entrées de régression depuis
<DIR>/regression_data - Validation bidirectionnelle du
regression_tests_pathentre règles et entrées : chaque entrée doit correspondre à une règle déclarant ce chemin, et chaque chemin déclaré doit pointer vers une entrée existante (chemins manquants / incohérents comptés). - Avertissements non bloquants : rule ids qui ne sont pas des UUID v4 (l'amont SigmaHQ en publie ; on avertit sans échouer) et règles non compilées (mode lenient)
- Pour chaque entrée
info.yml: - Valide l'
info.yml:rule_metadatanon vide (toujours un échec), indentation au style SigmaHQ 4 espaces,regression_tests_infonon vide (vide → échec, ou ignoré avec--ignore) - Valide le
.jsonauxiliaire s'il est présent : JSON ou JSONL (un objet par ligne) valide, exactement une fin de ligne - Charge la donnée brute selon le
logtype(.evtx,.log, lignes JSON), parse les événements - Évalue les événements contre la règle
- Valide : la règle DOIT matcher (test de détection positive)
- Quand un
.jsonauxiliaire est présent, valide lematch_countdéclaré contre le nombre réel de hits (incohérence de match_count = échec) - Rapport pass/fail par règle + résumé (exit 1 en cas d'échec de détection ou de chemin)
Sortie¶
[PASS] 1 alert(s), rule matched
[PASS] 1 alert(s), rule matched
...
[FAIL] EMPTY — no events produced from raw data
[PASS] 1 alert(s), rule matched
...
[FAIL] RULE NOT MATCHED — expected '460479f3-80b7-42da-9c43-2cc1d54dbccd' (0 alert(s), matched: )
============================================================
VALIDATION SUMMARY
============================================================
Total entries: 202
Passed: 200
Failed: 2
Pass rate: 99.0%
============================================================
Le résumé affiche aussi, quand non nuls : Missing paths, Mismatched, Ignored,
Skipped, Dropped lines et Warnings, suivi de la liste Failed rules
(FAIL <rule_name> — <error>) quand des entrées ont échoué. Un résumé en échec sort
avec exit 1 (échecs de détection ou chemins manquants/incohérents).
Exemple :
regressiondata-check
regressiondata-check --json --ignore
# depuis la racine d'un checkout du repo sigma (ex. CI/CD sur SigmaHQ/sigma) :
regressiondata-check --path .
regressiondata-check --fix --path .
Sortie JSON¶
--json produit :
{
"total": 202,
"passed": 200,
"skipped": 0,
"ignored": 0,
"missing_path": 0,
"mismatched_path": 0,
"failed_count": 2,
"pass_rate": 99.0,
"failed": [
{
"rule_name": "registry_event_add_local_hidden_user",
"error": "RULE NOT MATCHED — expected '460479f3-...' (0 alert(s), matched: )"
},
{
"rule_name": "cisco_cli_dot1x_disabled",
"error": "EMPTY — no events produced from raw data"
}
],
"warning_count": 1,
"warnings": [
"1 rule(s) failed to compile (lenient mode): [7]"
]
}
Les warnings regroupent les rule ids non-v4 et les règles non compilées (mode lenient) ;
elles n'entraînent jamais l'exit 1.
--evtx — input EVTX one-shot (run unique)¶
Feature evtx : un CollectorKind avec live_capture() = false qui
passe par le même pipeline run() que les collecteurs continus. Il scanne récursivement
un dossier pour des fichiers .evtx, parse chaque événement en pur Rust, les pousse à travers le
moteur de détection, écrit les données de régression SigmaHQ pour chaque règle matchée (writer
EVTX pur Rust — jamais EvtExportLog, car les événements statiques ne sont pas dans le journal
d'événements live), puis commit et push par règle vers la branche de travail configurée
(défaut sigmacatch/<date>) sur le fork
configuré. Comme EventProducer::run() se termine une fois tous les fichiers drainés, le
sender tombe et la boucle partagée sort — une passe : lecture → détection → génération →
commit/push, sans boucle de collecte. Un échec de l'upload final sort avec un statut non nul.
Utilisation :
sigmacatch --evtx <EVTX_PATH> [OPTIONS]
--evtx <EVTX_PATH> Dossier de fichiers .evtx, scanné récursivement
(défaut : C:\Windows\System32\winevt\Logs)
-v, --verbose Journalisation info sur stderr
-h, --help Affiche l'aide et quitte
--evtx est parsé par le CLI partagé mais n'est utilisé que par l'input evtx. Comme
toujours, la config est lue depuis le dossier de travail (config.yaml dans le CWD — pas
de flag --config). Il supporte les flags communs ci-dessous (-a, -c, -o, -v,
-n, --author, --branch) ; -r/--max-runs est accepté mais ignoré (auto-terminant), et -n/--dry-run
garde sa sémantique lecture seule.
Le repo sigma et la sortie de régression proviennent de la config
(git.sigma_repo_path, chemins relatifs résolus depuis le dossier du fichier de config) ;
les données de régression sont écrites sous <sigma_repo_path>/regression_data.
Flags du binaire de collecte¶
Le binaire unique sigmacatch (quels que soient les inputs compilés) partage ces flags :
sigmacatch [OPTIONS]
-a, --all-rules Charge toutes les règles (ignore les données de régression existantes)
-c, --contrib Active le push sur le fork (neutralisé par --offline)
-o, --offline Aucune opération git (fichiers sur disque tels quels, pas de commit/push)
-r, --max-runs <N> Quitte après N cycles de collecte (0 = illimité)
-v, --verbose Journalisation info sur stderr
-n, --dry-run Vérification en lecture seule : charge les règles de ./sigma et
construit le moteur — aucune donnée écrite, aucune opération git/réseau
--author <NOM> Remplace l'auteur git du config.yaml pour ce run
--branch <NOM> Nom de la branche de travail (défaut : sigmacatch/<date du jour>)
--evtx <CHEMIN> Dossier de fichiers EVTX à traiter (input one-shot evtx ;
échoue si la feature `evtx` n'est pas compilée)
--hir-cache <CHEMIN> Fichier de cache HIR persistant (warm-start : saute la
recompilation des règles au run suivant ; vide = recompilation à chaque run)
--help, -h Affiche l'aide et quitte
--dry-run s'exécute avant l'initialisation du logger : il ne crée ni config.yaml
ni logs/, saute la validation git (author/email/token) et se limite au chargement des
règles de ./sigma + à la construction du moteur de détection.
Sous-commandes de diagnostic du binaire¶
Les commandes ci-dessous sont des sous-commandes de sigmacatch, toujours compilées
(la feature tools a été supprimée) :
| Binaire | Sous-commandes |
|---|---|
sigmacatch (toute plateforme) |
check-filter, list-rules |
Une sous-commande inconnue ou absente → sigmacatch démarre sa boucle de collecte normale
(ou, avec --evtx, la passe one-shot EVTX). La valeur de filter.product vient de la
config.
Prérequis commun : chaque sous-commande charge
config.yamlviaConfig::load, qui exécute la validation complète (git.author/email/token compris) — pas seulement la sectionfilter. Sur une machine neuve avec leconfig.yamlpar défaut, une sous-commande diagnostic peut donc échouer sur une erreur git avant d'atteindre son propre travail.
check-filter¶
Usage : sigmacatch check-filter [--json]
Fonction : valide SigmaFilterConfig (product / status / level / author) contre le vrai jeu
de règles Sigma. Aucun argument CLI au-delà de --json — exécute toutes les combinaisons de filtres automatiquement.
Pipeline¶
- Charge toutes les règles depuis
./sigmaune seule fois (SigmahqRules::new()) - Pour chaque combinaison de filtres : applique le filtre et lit
LoadStats - Recalcule indépendamment les comptages ground-truth par dimension (
count_ground_truth) - Compare chaque bucket :
loaded,product,status,level,author,total - Rapport pass/fail par test + résumé (exit 1 si écart)
Ce n'est pas circulaire : les stats viennent de filter(), le ground-truth est compté
directement depuis les règles brutes — donc un stats() auto-cohérent mais faux échouerait quand même.
Exemple¶
list-rules¶
Usage : sigmacatch list-rules [--json] [--coverage]
Fonction : liste les règles chargées avec leur chemin. Avec --coverage, affiche aussi
le ratio de règles ayant des données de régression locale (with_data / total, pas un
pourcentage) ; les ids des branches remote sigmacatch/* en attente sont comptés dans le
skip set sans être listés séparément.
Pipeline¶
Config::load("config.yaml")(section filter)- Charge les règles Sigma depuis
./sigma+ filtre config - Pour chaque règle : id, titre, status, niveau, techniques (tags
attack.*), chemin, lien ART (première sous-technique)
Exemple¶
Les sous-commandes get-atomic et check-channels ont été retirées. get-atomic est
remplacé par la liste des techniques manquantes produite par list-rules --json --coverage
et la génération des données de régression ; les tests Atomic Red Team sont désormais
orchestrés directement sur la VM (module Invoke-AtomicRedTeam dans C:\AtomicRedTeam)
en ciblant les règles sans données. check est remplacé par le binaire standalone
regressiondata-check (voir plus haut).