diff --git a/AGENTS.md b/AGENTS.md index 5c0e5f03d..dd3a2daef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -108,7 +108,7 @@ handoff details in `docs/worklog/` until they are no longer useful. and 95%+ for the core generation engine. **Format Support:** -- json-logic-qubit for format definition validation rules +- Pydantic-validated bounded record predicates for format validation - Standard library json/csv for text formats - XML output via string templates (no python-evtx dependency) @@ -701,7 +701,7 @@ All emitters inherit from `LogEmitter` ABC (`src/evidenceforge/generation/emitte ### Format Definitions -Format definitions are YAML files in `src/evidenceforge/config/formats/`, not code. Each defines fields, variants, JSON Logic validators, and Jinja2 output templates. Loaded via `formats/loader.py`. Adding a new format requires only a new YAML file. +Format definitions are YAML files in `src/evidenceforge/config/formats/`, not code. Each defines fields, variants, typed record validators, and Jinja2 output templates. Loaded via `formats/loader.py`. Adding a new format requires only a new YAML file. ### YAML Data Directory Convention diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f4dee3d..d7f6b549d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,41 @@ Detailed development history for the EvidenceForge project. Transferred from TOD ## Unreleased +## v2.1.1 (2026-09-16) + +This patch release makes record validation representation-aware, preserves complete Windows Snare +facts, corrects failed-logon requester semantics, and updates the external parser harness to the +current validated SOF-ELK rules. Existing authored schemas and public APIs remain unchanged. + +**Record validation and evaluation** + +- Replace the external JSON-logic dependency with package-owned typed record predicates and apply + the same validation contracts across CLI preflight, generation, and evaluation. Cover incomplete + Windows XML wrappers and every successful proxy CONNECT response (`0ca530b2`, `c7a7517f`, + `3c4323fb`). +- Route artifacts to their native validators, distinguish malformed evidence from evaluator + execution faults, and add reproducible compatibility, mutation, and readiness evidence + (`ef7175b8`, `9c89e83d`, `54cf6ac3`). +- Parse Splunk web and proxy evidence during evaluation and normalize anonymous identities before + applying Windows Snare projections (`68cd5dd8`, `2c899b06`). + +**Windows Snare and external parser compatibility** + +- Preserve canonical Windows facts through typed Snare projections for all supported event + variants, with frozen compatibility tests and documented field dispositions (`1e91cf1b`, + `7b2ea369`, `e9beeca2`, `39615693`, `f5847ed8`). +- Update the SOF-ELK pin and harness for the newer parser filenames and scoped generic-syslog probe + tags while retaining fatal handling for malformed source records (`d25e71ba`). + +**Checkpoint and authentication correctness** + +- Decode recognized legacy validation snapshots and resolve checkpoint scratch paths before + mixed-format hydration (`cd6463f7`, `2526cda3`). +- Preserve failed-logon requester identity independently from the authentication target and domain + controller, including coherent optional 4771 and 4776 evidence (`2619b865`). +- Normalize ordinary host-log framing to LF so Windows checkpoint resume matches uninterrupted + generation (`1146b5a3`). + ## v2.1.0 (2026-09-14) This release adds native Windows generation and checkpoint recovery on local NTFS, including diff --git a/README.md b/README.md index 039e3fcd2..e9c52eaa5 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,12 @@ composition and lifecycle contract, see ## Data Quality Evaluation +Input validation and evidence evaluation are separate. `validate-config`, `validate`, `resolve`, +and `generate` preflight packaged contracts; `eval` checks emitted records. Acceptance requires +100% schema compliance and objective record correctness. Realism diagnostics do not relax these +gates. Existing scenario/overlay/pack interfaces remain supported; rules and thresholds are +package-owned. See [record validation](docs/reference/RECORD_VALIDATION.md). + EvidenceForge can evaluate a generated bundle across four complementary quality pillars: | Pillar | Weight | What it measures | diff --git a/TODO.md b/TODO.md index 6a7881908..88e381c75 100644 --- a/TODO.md +++ b/TODO.md @@ -58,6 +58,21 @@ without turning `TODO.md` back into a high-conflict work journal. ### Active and Near-Term +- [x] **P1** Preserve Windows facts in Snare and validate its native representation. All 43 variants + have typed projections and field-level gates against both frozen SOF-ELK revisions; historical + ambiguity remains explicit. See the [validation worklog](docs/worklog/2026-09-15-record-validation.md). +- [ ] **P2** Follow up upstream Snare extraction limitations: ParentImage/CurrentDirectory patterns + require backslashes after the pipeline replaces them, and POSINT patterns omit zero ports. + EvidenceForge preserves these raw values; structured indexing needs upstream parser work and + renewed compatibility gates. No upstream changes are part of this branch. +- [ ] **P1 — deferred** Investigate the existing iteration-scenario temporal-integrity failure + (40/48 visible events, 83.33%, below the unchanged 85% gate). Separate expected-time matching, + ordering, missing traces, and source-observation timing before assigning fixes to their owning + layer. Baseline/candidate evidence bytes match; this predates the validation refactor and is + deferred from this branch by user decision. See the same worklog for the eight findings. +- [ ] **P2** Investigate generation coverage for Zeek packet-filter/reporter/weird diagnostic + sources separately from their dedicated renderer/parser/validator fixture coverage. + - Prepare the 2.1.0 release from `dev` to `main`, including the version/changelog bump and routine, coverage, slow, and checkpoint portability gates. See the [release worklog](docs/worklog/2026-09-14-2.1.0-release.md). diff --git a/commands/eforge/config.md b/commands/eforge/config.md index 8ee9a0d10..3b9c63858 100644 --- a/commands/eforge/config.md +++ b/commands/eforge/config.md @@ -147,4 +147,4 @@ selected. Use composition explanation when pack and overlay precedence matters. State the project root, whether the operation remained read-only, files changed, directly implied repairs, validation result, and unresolved pre-existing or semantic decisions. Mention the effective -merge behavior when it could surprise the user. +merge behavior when it could surprise the user. Read `/eforge:references:record-validation` for validation policy and compatibility. diff --git a/commands/eforge/evaluate.md b/commands/eforge/evaluate.md index 7576a5c71..e9207d4f3 100644 --- a/commands/eforge/evaluate.md +++ b/commands/eforge/evaluate.md @@ -61,7 +61,8 @@ Treat these exits as distinct outcomes: - `0`: parse the JSON report; its acceptance verdict may still be `FAIL` or `INDETERMINATE`. - `1`: input/path error or a legacy dataset missing `--scenario`; correct the invocation. - `2`: scenario/include, bundle-integrity, or comparison-mismatch error; report it and stop. -- `22`: evaluation engine or capacity failure; report the diagnostic without inventing scores. +- `22`: evaluation engine, scoring-pillar, or capacity failure; no completed report is emitted. + Diagnostics use stderr; successful JSON stdout contains exactly one report object. - `130`: interrupted; report that no completed evaluation is available. ### Override gates @@ -148,3 +149,8 @@ emitter layer. Finish with the verdict, available score, failed gates, strongest evidence, and smallest useful next action. Keep recommendations read-only unless the user asks to act. + +## Validation policy + +Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance, +structured findings, or compatibility with existing projects. diff --git a/commands/eforge/generate.md b/commands/eforge/generate.md index 69a558cd2..439368b2f 100644 --- a/commands/eforge/generate.md +++ b/commands/eforge/generate.md @@ -150,3 +150,5 @@ Read only the smallest relevant reference when exact paths, fields, joins, or li - `/eforge:references:evidence-network-ids` for Zeek, IDS, and Cisco ASA. - `/eforge:references:evidence-web-email` for HTTP/files, web, proxy, email, and SMTP. - `/eforge:references:evidence-endpoint-linux` for eCAR, Linux syslog, and bash history. + +Read `/eforge:references:record-validation` for validation policy and compatibility. diff --git a/commands/eforge/industry-pack.md b/commands/eforge/industry-pack.md index 6a26685ea..47341ddea 100644 --- a/commands/eforge/industry-pack.md +++ b/commands/eforge/industry-pack.md @@ -183,3 +183,8 @@ when the user requests an example or regression fixture. Return the exact reference, version rationale, files and exports authored, final digest, validation result, consumer-harness result, and specific runtime evidence observed. Identify any intentionally empty catalog and why it remains empty. + +## Validation policy + +Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance, +structured findings, or compatibility with existing projects. diff --git a/commands/eforge/organization-pack.md b/commands/eforge/organization-pack.md index e39aae31b..9ee30091f 100644 --- a/commands/eforge/organization-pack.md +++ b/commands/eforge/organization-pack.md @@ -215,3 +215,8 @@ only when the user requests an example or regression fixture. Return the exact organization reference, exact industry dependencies, version rationale, standalone or partial status, files and exports authored, final digest, validation result, consumer-harness result, and representative runtime evidence observed. State what remains scenario-owned. + +## Validation policy + +Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance, +structured findings, or compatibility with existing projects. diff --git a/commands/eforge/pack-release.md b/commands/eforge/pack-release.md index 80e8f53c6..17384e80a 100644 --- a/commands/eforge/pack-release.md +++ b/commands/eforge/pack-release.md @@ -29,3 +29,8 @@ set`; never derive identity from a username, hostname, repository, or pack name. `eforge pack hydrate publisher:type:name@version --scope project|user --json`. `.efpack` files are local release artifacts; this skill does not upload to a registry or remote host. + +## Validation policy + +Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance, +structured findings, or compatibility with existing projects. diff --git a/commands/eforge/pack.md b/commands/eforge/pack.md index db2e042d5..4f68a5a1e 100644 --- a/commands/eforge/pack.md +++ b/commands/eforge/pack.md @@ -187,3 +187,8 @@ Return: 5. Final digest and exports. 6. Versioning or dependency decisions. 7. The specialized skill to use next when substantive authoring remains. + +## Validation policy + +Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance, +structured findings, or compatibility with existing projects. diff --git a/commands/eforge/references/checkpoint-recovery.md b/commands/eforge/references/checkpoint-recovery.md index 2aa788078..2ab19cd91 100644 --- a/commands/eforge/references/checkpoint-recovery.md +++ b/commands/eforge/references/checkpoint-recovery.md @@ -7,6 +7,14 @@ description: "Checkpoint inspection, drift verification, and safe resume referen Read this reference for interrupted generation, resume compatibility, environment drift, recovery wheels, OOB authorization, or a verifier that appears idle. +## Contents + +- [Preserve first](#preserve-first) +- [Interpret compatibility](#interpret-compatibility) +- [Migration and provenance](#migration-and-provenance) +- [uv tool recovery builds](#uv-tool-recovery-builds) +- [Validation metadata upgrades](#validation-metadata-upgrades) + ## Preserve First Stop the generator before copying or inspecting a bundle. Preserve a filesystem snapshot or backup @@ -92,3 +100,13 @@ bundle back. When a recovery wheel is only an exact-behavior backport, keep using it for that interrupted run. Do not replace its immutable release tag or infer that a displayed package version alone identifies the source build; compare the recorded build digest. + +## Validation metadata upgrades + +Compatible recovery recognizes the exact package-owned validation snapshots from the pre-typed-rule +2.1.0 baseline. It decodes those validation documents in memory only when their native rendering +templates still match. Stored checkpoint and resolved input documents remain immutable; arbitrary +old internal rule syntax remains unsupported. The runtime's exact correctness policy applies when +subsequently evaluating evidence. This decoder does not bypass checkpoint integrity, hydration, +provenance, or resume-policy checks. Dependency/build drift still means `not-guaranteed` output +equivalence, even when a particular resumed run matches uninterrupted evidence byte for byte. diff --git a/commands/eforge/references/config-evaluation.md b/commands/eforge/references/config-evaluation.md index 8509b9f56..c0b009fb5 100644 --- a/commands/eforge/references/config-evaluation.md +++ b/commands/eforge/references/config-evaluation.md @@ -5,8 +5,8 @@ engine-owned. `.eforge/config/evaluation`, pack catalogs, scenario YAML, and env cannot replace them. Packaged rule files live under `src/evidenceforge/config/evaluation/` and include thresholds, -co-occurrence, distributions, causal/timing checks, and cross-source rules. They must remain aligned -with evaluator code, parsers, ground-truth contracts, observation semantics, and format definitions. +distributions, causal/timing checks, and cross-source rules. They must remain aligned +with typed record rules in `config/formats/`, evaluator code, parsers, ground-truth contracts, observation semantics, and format definitions. Use the evaluate skill to run or interpret `eforge eval`. A request to change scoring policy is a source-code development task, not an `eforge-config` overlay task. For an authorized developer diff --git a/commands/eforge/references/config-formats.md b/commands/eforge/references/config-formats.md index 2b706aeef..bce5048d3 100644 --- a/commands/eforge/references/config-formats.md +++ b/commands/eforge/references/config-formats.md @@ -15,3 +15,6 @@ documentation, and round-trip tests together. Do not place format YAML under `.eforge/config`, expose it through a pack, or treat a copied package file as a supported project override. + +Field schemas and bounded record predicates are validated with Pydantic at load time. Legacy JSON +Logic is no longer supported. See `/eforge:references:record-validation` for acceptance policy. diff --git a/commands/eforge/references/record-validation.md b/commands/eforge/references/record-validation.md new file mode 100644 index 000000000..6ed40ad24 --- /dev/null +++ b/commands/eforge/references/record-validation.md @@ -0,0 +1,67 @@ +# Input validation and evidence validation + +`validate-config` checks effective supported configuration and packaged record contracts. +`validate`, `resolve`, and `generate` preflight the required package contracts alongside their +existing scenario and configuration checks. Passing input validation does not mean that generated +evidence has been evaluated. `generate` does not automatically run dataset evaluation. + +Run `eforge eval --format json` to assess evidence. Schema compliance and objective +record correctness require 100%: a single malformed or contradictory record fails acceptance. +A completed report still exits 0 even when `acceptance_passed` is false. Engine failures exit 22 +and must never be presented as successful acceptance. Existing report keys remain; sub-scores +also expose bounded `sample_findings` with rule ID, format/variant, fields, category, severity, +outcome, and message. Counts cover all records, not just these diagnostic samples. + +Realism diagnostics are separate from objective correctness. Sparse endpoint metadata, zero-duration +observations, and unusual certificate validity intervals can be legitimate evidence. Specialized +lifecycle, collection-visibility, cryptographic, and cross-record evaluators retain their ownership; +partial observation does not excuse contradictions within a visible record. + +Rules and thresholds are package-owned developer interfaces. They cannot be overridden in scenario +YAML, `.eforge/config`, pack catalogs, or environment variables. Supported Scenario 1.0/2.0, overlay +syntax and merge precedence, pack/release schemas, and project-root resolution are unchanged. +Do not add a threshold override or weaken a rule to make a dataset pass. + + +## Validation coverage and execution failures + +Every parser source has an explicit package-owned validation route. Native log sources require a +format schema; email artifact manifest entries use structural artifact validation and retain their +specialized email consistency checks. An unknown source or unavailable native schema is an engine +error, never an implicitly passing record. Empty email sections and optional metadata remain valid. + +A failed scoring pillar stops evaluation with exit 22 and no quality report. Successful JSON mode +writes one report object to stdout; warnings and progress go to stderr. A completed report may still +fail acceptance and exit 0. Use `--verbose` for an execution-failure traceback. Do not interpret a +partial collection of pillar scores as an overall quality result. + +Developer coverage checks reconcile all parser routes, native schemas, emitter registrations, and +rendering paths. Routine tests render, parse, and validate every native format and supported Windows +variant. The slow iteration-scenario gate checks fresh-process byte equality, bundle integrity, +complete evaluation, and exact record validation, including email artifacts and observation gaps. + +Returned `evaluation_error` findings abort evaluation just like raised exceptions, including +realism diagnostics and artifact validators. The diagnostic identifies the rule, source, variant, +and fields. The library `validate_event` API still returns `valid=False`, errors, and findings; +the scoring boundary raises the execution error. + +Malformed records remain in source counts and exact schema acceptance. After those failures are +recorded, malformed records are omitted from the typed distribution and cross-source indexes used +by later pillars. Those pillar scores describe the usable evidence; they cannot override failed +schema acceptance. Cross-field contradictions in otherwise well-typed records remain available to +specialized evaluators. Missing optional observations and source-native conversions retain their +existing semantics. + +## SOF-ELK® Windows Snare + +Snare has an explicit representation contract. Current output preserves available canonical Windows +fields and compatible SOF-ELK display aliases; XML requirements remain unchanged for XML. A field +present in raw Snare is not necessarily indexed by SOF-ELK. Historical repeated account labels are +retained without inventing subject/target scope. Inspect `unavailable_check_count` and +`sample_unavailable_findings` for historical coverage limits; do not describe those checks as passed. +Malformed fields and contradictory aliases still fail exact acceptance. Projection definitions, +like rules and thresholds, are package-owned and are not configuration overlays. Temporal-integrity +findings remain independent of representation/schema results. +The frozen upstream parsers do not index zero ports or the preserved ParentImage/CurrentDirectory +paths; do not infer absence of those facts from missing indexed fields. Supplied Sysmon UtcTime +remains distinct from TimeCreated and controls the upstream event timestamp. diff --git a/commands/eforge/scenario.md b/commands/eforge/scenario.md index 638271b4a..9338c8b73 100644 --- a/commands/eforge/scenario.md +++ b/commands/eforge/scenario.md @@ -158,3 +158,5 @@ generated output. If the user wants logs, hand off to `/eforge generate`. If they want a focused validation or repair explanation, hand off to `/eforge validate`. Do not silently generate logs as part of authoring. + +Read `/eforge:references:record-validation` for validation policy and compatibility. diff --git a/commands/eforge/validate.md b/commands/eforge/validate.md index 8dc7aa37c..d14da1c3f 100644 --- a/commands/eforge/validate.md +++ b/commands/eforge/validate.md @@ -146,3 +146,5 @@ eforge validate --json --oob-host Validation makes no callback. A fresh matching flag is independently required for each validate, resolve, or generate invocation that needs it. + +Read `/eforge:references:record-validation` for validation policy and compatibility. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 8542f57e2..a11346c3e 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -954,7 +954,7 @@ checkpoint publication. ### Format Definition System -Log formats are defined declaratively in YAML files (`src/evidenceforge/formats/definitions/`), not in code: +Log formats are defined declaratively in YAML files (`src/evidenceforge/config/formats/`), not in code: ```yaml # Example: zeek_conn.yaml @@ -974,10 +974,16 @@ fields: ``` Each format YAML defines fields (name, type, constraints), event variants (for multi-event formats like Windows Security), and Jinja2 output templates. Adding a new log format requires: -1. A new YAML definition in `formats/definitions/` +1. A new YAML definition in `config/formats/` 2. An emitter class in `generation/emitters/` 3. A parser class in `evaluation/parsers/` (for eval support) +Record contracts use Pydantic schemas and a bounded evaluator, with cached field plans per +format/variant. Dotted source field names are literal keys. Findings carry structured categories; +schema/correctness failures gate every record at 100%, while context-dependent realism rules stay +diagnostic. JSON Logic and the separate co-occurrence interpreter have been removed. See +[record validation](reference/RECORD_VALIDATION.md) for the developer contract. + ### Evaluation Engine The evaluation system (`src/evidenceforge/evaluation/`) scores generated data across 4 pillars: diff --git a/docs/design/PRD.md b/docs/design/PRD.md index 350f9223a..5cbe32929 100644 --- a/docs/design/PRD.md +++ b/docs/design/PRD.md @@ -1,3 +1,6 @@ +> Historical design: the JSON Logic sketches below are superseded by +> [the typed record contract](../reference/RECORD_VALIDATION.md). + # PRD: EvidenceForge > **Naming conventions:** "EvidenceForge" is the product name, `evidenceforge` is the Python package name, `eforge` is the CLI command name. diff --git a/docs/external-parser-validation/coverage-matrix.md b/docs/external-parser-validation/coverage-matrix.md index a2667da70..ee07038ac 100644 --- a/docs/external-parser-validation/coverage-matrix.md +++ b/docs/external-parser-validation/coverage-matrix.md @@ -31,8 +31,8 @@ app config and optional caller-supplied apps for CIM checks. | Zeek `pe` | `sof-elk-zeek` | Supplemental EvidenceForge input | JSON preprocess and Zeek postprocess filters | JSON ingestion and count validation. | | Zeek `reporter` | `sof-elk-zeek` | Supplemental EvidenceForge input | JSON preprocess and Zeek postprocess filters | JSON ingestion and count validation. | | Cisco ASA `cisco_asa.log` | `sof-elk-cisco-asa` | `syslog.yml` | `1000-preprocess-all.conf`, `1100-preprocess-syslog.conf`, `6018-cisco_asa.conf`, `8999-postprocess-all.conf` | `sof-elk` target only; generated under `//cisco_asa.log`, staged under `/logstash/syslog///cisco_asa.log`, and requires `got_cisco` plus `parse_done`. | -| Web access `web_access.log` | `sof-elk-web-access` | `httpdlog.yml` | `1000-preprocess-all.conf`, `6100-httpd.conf`, `8060-postprocess-useragent.conf`, `8110-postprocess-httpd.conf`, `8999-postprocess-all.conf` | Optional page classification miss `_grokparsefail_8110-01` is ignored. | -| Proxy access `proxy_access.log` | `sof-elk-proxy-access` | `httpdlog.yml` | `1000-preprocess-all.conf`, `6100-httpd.conf`, `8060-postprocess-useragent.conf`, `8110-postprocess-httpd.conf`, `8999-postprocess-all.conf` | Combined proxy access rows are staged under `/logstash/httpd//proxy_access.log`; count, fatal tags, source IP, method, and status are validated. | +| Web access `web_access.log` | `sof-elk-web-access` | `httpdlog.yml` | `1000-preprocess-all.conf`, `6100-httpd.conf`, `8054-postprocess-useragent.conf`, `8004-postprocess-httpd.conf`, `8999-postprocess-all.conf` | Optional page classification miss `_grokparsefail_8110-01` is ignored. | +| Proxy access `proxy_access.log` | `sof-elk-proxy-access` | `httpdlog.yml` | `1000-preprocess-all.conf`, `6100-httpd.conf`, `8054-postprocess-useragent.conf`, `8004-postprocess-httpd.conf`, `8999-postprocess-all.conf` | Combined proxy access rows are staged under `/logstash/httpd//proxy_access.log`; count, fatal tags, source IP, method, and status are validated. | | Linux `syslog.log` | `sof-elk-syslog` | `syslog.yml` | `1000-preprocess-all.conf`, `1100-preprocess-syslog.conf`, `6012-dhcpd.conf`, `6013-bindquery.conf`, `6015-sshd.conf`, `6016-pam.conf`, `6017-iptables.conf`, `8100-postprocess-syslog.conf`, `8999-postprocess-all.conf` | `sof-elk` target only; generated RFC3164 files live under `//syslog.log`, and staged year is validated against parsed `@timestamp`. | | Windows Security `windows_event_security_snare.log` | `sof-elk-windows-security-snare` | `syslog.yml` | `1000-preprocess-all.conf`, `1010-preprocess-snare.conf`, `1100-preprocess-syslog.conf`, `6010-snare.conf`, `8999-postprocess-all.conf` | `sof-elk` target only; generated under `//windows_event_security_snare.log`, staged under `/logstash/syslog///...`, and requires `snare_log`, `parse_done`, and normalized `winlog.*` fields. | | Sysmon `windows_event_sysmon_snare.log` | `sof-elk-windows-sysmon-snare` | `syslog.yml` | `1000-preprocess-all.conf`, `1010-preprocess-snare.conf`, `1100-preprocess-syslog.conf`, `6010-snare.conf`, `8999-postprocess-all.conf` | `sof-elk` target only; validates `winlog.event_id`, provider, channel, computer, and staged source year. | diff --git a/docs/external-parser-validation/ignored-parser-tags.md b/docs/external-parser-validation/ignored-parser-tags.md index ffe75eb65..0e3ddd04a 100644 --- a/docs/external-parser-validation/ignored-parser-tags.md +++ b/docs/external-parser-validation/ignored-parser-tags.md @@ -8,9 +8,10 @@ record still parsed. Unknown `_grokparsefail*` tags remain fatal by default. | --- | --- | --- | --- | --- | --- | | `_grokparsefail_6200-01` | `sof-elk-zeek` | `zeek_dns` | Only when `dns.question.type` is a non-address type; address answers (`A`/`AAAA`) must preserve `dns.answers.ip` and keep this tag fatal | `configfiles/6200-zeek_dns.conf` | Optional `dns.answers.ip` extraction from `dns.answers.data`; non-address answer types such as `NS`, `PTR`, `MX`, and `SOA` are valid DNS records. | | `_dateparsefailure` | `sof-elk-zeek` | `zeek_x509` | Only when raw `certificate.not_valid_before` and `certificate.not_valid_after` are valid epoch seconds and at least one is after the signed 32-bit Unix timestamp boundary but still within RFC 5280's UTCTime window through 2049 | `configfiles/6204-zeek_x509.conf` | Zeek `x509.log` correctly represents certificate validity as epoch seconds. RFC 5280 permits UTCTime certificate dates through 2049, but this SOF-ELK/Logstash date path cannot parse post-2038 epoch values. | -| `_grokparsefail_8110-01` | `sof-elk-web-access` | `web_access` | Always, after required HTTP access fields validate | `configfiles/8110-postprocess-httpd.conf` | Optional page/not-page URL path classification after the HTTP access record already parsed. | -| `_grokparsefail_8110-01` | `sof-elk-proxy-access` | `proxy_access` | Always, after required HTTP access fields validate | `configfiles/8110-postprocess-httpd.conf` | Optional page/not-page URL path classification after the HTTP access record already parsed. | +| `_grokparsefail_8110-01` | `sof-elk-web-access` | `web_access` | Always, after required HTTP access fields validate | `configfiles/8004-postprocess-httpd.conf` | Optional page/not-page URL path classification after the HTTP access record already parsed. | +| `_grokparsefail_8110-01` | `sof-elk-proxy-access` | `proxy_access` | Always, after required HTTP access fields validate | `configfiles/8004-postprocess-httpd.conf` | Optional page/not-page URL path classification after the HTTP access record already parsed. | | `_grokparsefail_6018-01` | `sof-elk-syslog` | `syslog` | Always for Linux syslog events, after required syslog envelope fields validate | `configfiles/6018-cisco_asa.conf` | SOF-ELK's Cisco ASA filter opportunistically runs on ordinary syslog rows; a miss does not mean the Linux syslog record failed. | +| `_grokparsefailure` | `sof-elk-syslog` | `syslog` | Only for archived Linux syslog records with a complete parsed envelope, no successful specialized parser, and no UniFi application-name shape | `configfiles/6018-cisco_asa.conf` at `d9f9bdd` | The pinned filter removed its scoped failure tag, so an expected Cisco ASA probe miss receives Logstash's generic tag. Malformed ASA, base-syslog, specialized-parser, and UniFi records remain fatal. | | `_grokparsefailure_6015-01` | `sof-elk-syslog` | `syslog` | Only when the event is an `sshd` `pam_unix(sshd:session)` open/close record that has `got_pam` and `parse_done` | `configfiles/6015-sshd.conf` and `configfiles/6016-pam.conf` | SOF-ELK's SSHD filter runs before the PAM filter on `appname=sshd`; the PAM record can parse successfully while retaining the earlier SSHD miss. | | `_grokparsefail_6016-02` | `sof-elk-syslog` | `syslog` | Only when the event is a parsed `pam_unix(...:auth)` authentication failure with `got_pam` and `parse_done` | `configfiles/6016-pam.conf` | SOF-ELK parses the PAM auth envelope, but the second-stage remainder enrichment does not cover common authentication failure detail fields. | | `_grokparsefail_6010-01` | `sof-elk-windows-security-snare` | `windows_event_security_snare` | Only when the Snare row has `snare_log`, `parse_done`, and required `winlog.*` fields | `configfiles/6010-snare.conf` | SOF-ELK's second-stage expanded-data enrichment can retain a grok miss after the Snare CSV row and required Windows fields parsed. | diff --git a/docs/reference/EVIDENCE_FORMATS.md b/docs/reference/EVIDENCE_FORMATS.md index 56b6c7e64..5b9f09cc3 100644 --- a/docs/reference/EVIDENCE_FORMATS.md +++ b/docs/reference/EVIDENCE_FORMATS.md @@ -629,3 +629,8 @@ companions appear according to normal visibility rules. - Non-intercepting tunnel-only HTTPS proxy behavior is not yet modeled - Cache hit/miss status is probabilistic, with stable web-route status generated upstream - Limited to HTTP and HTTPS traffic + +## Record validation + +See [the shared record contract](RECORD_VALIDATION.md) for typed predicates, Windows aliases, +parser failure accounting, and exact schema/correctness acceptance gates. diff --git a/docs/reference/GENERATION_CHECKPOINTS.md b/docs/reference/GENERATION_CHECKPOINTS.md index 9bc3e2c1d..30cfe5269 100644 --- a/docs/reference/GENERATION_CHECKPOINTS.md +++ b/docs/reference/GENERATION_CHECKPOINTS.md @@ -197,3 +197,18 @@ provenance when recovery occurred. Under an exact resume, deterministic evidence ground truth, artifacts, and deterministic sidecars are byte-identical to uninterrupted generation. A load-compatible resume makes no byte-equivalence promise; `generation.log` and the time-bearing generation manifest retain their established nondeterministic fields in either case. + +### Typed-validation snapshot compatibility + +The typed-validation runtime recognizes exact immutable validation documents from baseline +`787fd733` (2.1.0). It promotes recognized legacy rules/schema metadata and evaluation thresholds +in memory, preserving the stored resolved snapshot and verifying identical native rendering +templates. Other old internal rule documents receive the existing actionable contract error. +This is a bounded decoder for package-owned metadata, not a user configuration migration surface. + +`exact` still requires the original fingerprint and rejects drift without changing recovery state. +Default `compatible` performs normal isolated hydration and records the dependency/build transition +before continuing. The removed JSON Logic dependency remains visible in migration provenance. +The output-equivalence classification remains `not-guaranteed`; observed byte equality in a +regression test does not strengthen that guarantee. Corrupt, unsupported, and conflicting recovery +states retain their existing refusal behavior. diff --git a/docs/reference/RECORD_VALIDATION.md b/docs/reference/RECORD_VALIDATION.md new file mode 100644 index 000000000..fadf15730 --- /dev/null +++ b/docs/reference/RECORD_VALIDATION.md @@ -0,0 +1,129 @@ +# Input validation and evidence validation + +`validate-config` checks effective supported configuration and packaged record contracts. +`validate`, `resolve`, and `generate` preflight the required package contracts alongside their +existing scenario and configuration checks. Passing input validation does not mean that generated +evidence has been evaluated. `generate` does not automatically run dataset evaluation. + +Run `eforge eval --format json` to assess evidence. Schema compliance and objective +record correctness require 100%: a single malformed or contradictory record fails acceptance. +A completed report still exits 0 even when `acceptance_passed` is false. Engine failures exit 22 +and must never be presented as successful acceptance. Existing report keys remain; sub-scores +also expose bounded `sample_findings` with rule ID, format/variant, fields, category, severity, +outcome, and message. Counts cover all records, not just these diagnostic samples. + +Realism diagnostics are separate from objective correctness. Sparse endpoint metadata, zero-duration +observations, and unusual certificate validity intervals can be legitimate evidence. Specialized +lifecycle, collection-visibility, cryptographic, and cross-record evaluators retain their ownership; +partial observation does not excuse contradictions within a visible record. + +Rules and thresholds are package-owned developer interfaces. They cannot be overridden in scenario +YAML, `.eforge/config`, pack catalogs, or environment variables. Supported Scenario 1.0/2.0, overlay +syntax and merge precedence, pack/release schemas, and project-root resolution are unchanged. +Do not add a threshold override or weaken a rule to make a dataset pass. + +## Developer contract + +Definitions live in `src/evidenceforge/config/formats/*.yaml`. `validators` contains rules with +`id`, `message`, `severity`, optional `when` and `exclude` conjunctions, and nonempty `checks`. +Supported operations are `presence`, `compare`, `membership`, `bounds`, `length`, `pattern`, +`same_length`, `combination`, and the named `address_family` predicate. There is no expression +language, dynamic code loading, or JSON Logic fallback. Unknown keys/operators, invalid references, +regexes, duplicate identities, and inverted bounds are definition errors. + +```yaml +validators: + - id: example.counter + message: Response count must not exceed request count + when: + - {op: presence, field: requests} + - {op: presence, field: responses} + checks: + - {op: compare, field: responses, relation: le, other_field: requests} +``` + +Missing and null are absent for `presence`; empty strings, empty lists, zero, and source-native +sentinels are present. Apply explicit comparisons/exclusions for empty values and sentinels. +List schemas declare `item_type`; numeric values must be finite, and numeric bounds apply to +integers and floats. Parsers own documented source-native conversions. Windows variants declare +`event_id` and explicit `event_ids` aliases; do not add a second hand-maintained selection table. + +`validate_event` retains `valid` and `errors` compatibility views and adds `findings`. Rule outcomes +are `pass`, `fail`, `not_applicable`, and `evaluation_error`. Invalid prerequisite fields skip their +dependent rules to avoid duplicate penalties. Rule execution errors are always errors, including +for diagnostic rules. Unavailable schemas and invalid engine policy cannot yield acceptance. + +Add positive, negative, conditional, missing/null/sentinel, malformed-definition, parser-to-score, +and single-violation acceptance coverage when extending a contract. Preserve positive examples +of deliberately unusual evidence. Changes to rule YAML can affect checkpoint behavior provenance; +use the generation-behavior manifest workflow and prove raw-byte compatibility separately. + + +## Validation coverage and execution failures + +Every parser source has an explicit package-owned validation route. Native log sources require a +format schema; email artifact manifest entries use structural artifact validation and retain their +specialized email consistency checks. An unknown source or unavailable native schema is an engine +error, never an implicitly passing record. Empty email sections and optional metadata remain valid. + +A failed scoring pillar stops evaluation with exit 22 and no quality report. Successful JSON mode +writes one report object to stdout; warnings and progress go to stderr. A completed report may still +fail acceptance and exit 0. Use `--verbose` for an execution-failure traceback. Do not interpret a +partial collection of pillar scores as an overall quality result. + +Developer coverage checks reconcile all parser routes, native schemas, emitter registrations, and +rendering paths. Routine tests render, parse, and validate every native format and supported Windows +variant. The slow iteration-scenario gate checks fresh-process byte equality, bundle integrity, +complete evaluation, and exact record validation, including email artifacts and observation gaps. + +### Malformed evidence versus evaluator faults + +A returned `evaluation_error` finding stops scoring before aggregation, including diagnostic and +artifact rules. The CLI returns 22, identifies the rule/source/variant/fields on stderr, and emits no +report. The library compatibility view still returns `valid=False`, errors, and structured findings. + +Malformed records remain counted in source totals and exact schema acceptance. Once recorded as +schema/parse failures, they do not enter later pillars' typed distribution or cross-source indexes. +Those scores describe usable evidence and cannot override failed schema acceptance. Well-typed +records with cross-field contradictions still reach specialized evaluators. This prevents malformed +identities, timestamps, and collections from turning ordinary invalid evidence into engine faults. + +Splunk web/proxy JSON is parsed through its supported field aliases before shared validation. +Malformed native fields and conflicting aliases remain counted failures. + +## Windows Snare representation + +SOF-ELK® Windows output uses a Snare envelope, not XML. The parser explicitly records the +representation and validates the envelope independently; XML retains its full structure requirements. +Package-owned event-specific projections preserve canonical fields and select coherent display +aliases for downstream extraction. Scoped logon IDs use `Canonical[SubjectLogonId]` and +`Canonical[TargetLogonId]` labels (also `Canonical[TargetLinkedLogonId]`) to avoid SOF-ELK's +unanchored generic LogonId pattern. Hex process +IDs retain their original canonical values alongside decimal views where downstream parsing needs +one. Execution PID fallback is explicitly sourced from ExecutionProcessID and never fabricated. + +Current projections carry `ProjectionVersion: 1`, precise TimeCreated, Level, execution IDs and the +Windows EventRecordID. Snare criticality and counter remain distinct source-native concepts. +Private generation bookkeeping is excluded. String values retain native whitespace/delimiter +sanitization. Raw preservation does not imply SOF-ELK indexes every field. +Supplied Sysmon UtcTime is retained independently of TimeCreated; only an absent UtcTime uses the +existing system-time fallback. SOF-ELK uses UtcTime for its event timestamp. Zero-valued ports remain +in the raw record, although upstream positive-integer patterns do not extract them. +Both frozen revisions also normalize backslashes before applying backslash-dependent ParentImage +and CurrentDirectory patterns. These fields remain raw-only; field-preservation tests explicitly +check this limitation. RuleName becomes an upstream array, and domain/user patterns require a +qualified identity. Do not assume raw-only fields are searchable as structured fields. + +Historical generated Snare remains supported. Ordered repeated labels are retained without +last-value-wins identity reconstruction. Missing unrepresentable XML/scoped fields produce explicit +not-applicable findings; malformed values and contradictions still fail. Parseability reports +`unavailable_check_count` and bounded `sample_unavailable_findings`. These indicate coverage limits, +not proof that unavailable facts were correct. Current projections must provide required metadata. + +External compatibility is tested against revisions `517af9445574cc084cd5f4b80539fc244dab82b0` and +`d9f9bdd113a606c7b3fa1b2eafaa2d4400a16668`, checking extracted values as well as ingestion. The harness +uses uncompressed staged files and path identity for small fixtures; it removes upstream gzip auto +detection from this transport adapter. Upstream Logstash filters remain unchanged. Tag policy keeps +generic parser failures fatal except for the pinned Cisco ASA probe miss on a fully parsed generic +Linux syslog envelope. See the ignored-tag reference, branch worklog, and field inventory for exact +predicates, nearby fatal cases, source/version-specific limitations, and executed gate results. diff --git a/docs/worklog/2026-09-15-record-validation.md b/docs/worklog/2026-09-15-record-validation.md new file mode 100644 index 000000000..973dead75 --- /dev/null +++ b/docs/worklog/2026-09-15-record-validation.md @@ -0,0 +1,841 @@ +# Unified record validation + +## Contract and baseline + +- Branch: `codex/record-validation`, based on freshly fetched `origin/dev` at `787fd733`. +- Immutable comparison checkout: `/tmp/eforge-record-validation-baseline` (detached). +- Preserve scenario/pack schemas, overlay precedence, project-root behavior and CLI exit codes. +- Correctness checks apply to every record and gate acceptance at 100%; realism remains diagnostic. +- Validation-only changes must preserve raw generated evidence; any generator correction requires + separate evidence and a separate commit. Package version remains unchanged. + +## Execution + +Implementation and the iteration-test follow-up repairs are complete locally. The defects discovered +by the full iteration run are documented below together with their repairs and passing final gates. +External CI awaits explicit publication approval. No generator correction or version bump was made. + +## Audit inventory + +25 formats: bash_history, cisco_asa, ecar, proxy_access, snort_alert, syslog, web_access, +windows_event_security, windows_event_sysmon, zeek_conn, zeek_dhcp, zeek_dns, zeek_files, +zeek_http, zeek_ntp, zeek_ocsp, zeek_packet_filter, zeek_pe, zeek_reporter, zeek_smb_files, +zeek_smb_mapping, zeek_smtp, zeek_ssl, zeek_weird, zeek_x509. + +42 co-occurrence rules: Windows Security 14, conn 4, eCAR 12, syslog 2, Snort 2, +web 2, DNS 2, HTTP 2, bash history 2. Four malformed JSON Logic rules overlap +with these or require semantic correction. Their migration classification and final results +will be recorded below. + +## Scope decisions and compatibility + +- Format/rule YAML and evaluation thresholds remain package-owned. Supported overlays, pack catalogs, + scenario schemas, composition precedence, and CWD/explicit project-root resolution are unchanged. +- Native DNS metadata is optional when the corresponding message was not observed. Removed the + incomplete closed qtype/rcode name pools; known numeric/name pairs must agree. Missing response + metadata and empty/root query diagnostics remain warnings. Source contract: + https://docs.zeek.org/en/current/scripts/base/protocols/dns/main.zeek.html +- HTTP CONNECT is supported by existing generation and now by the web field schema as well as the + record rule. TRACE remains supported. Failed CONNECT responses may carry an error body. +- eCAR FILE/RENAME is retained; object/action pairs share one schema-owned contract. +- Windows Security selectors now come from variant metadata, including aliases, 4778/4779 and + separate task deleted/disabled/enabled variants. Sysmon address/family checks apply only when both + fields are observed. Malformed numeric Windows fields are parse failures; native absent-port + sentinels retain their documented conversion. +- Windows identity/privilege/session enrichment rules remain context-dependent diagnostics. Sparse + metadata and deliberately unusual certificate/OCSP intervals must not be mistaken for impossible + records. Cross-record lifecycle, visibility, cryptographic and causal checks remain specialized. +- Dependency removal changes runtime checkpoint fingerprints. Existing exact-resume compatibility + policy is retained; an older checkpoint cannot silently ignore a changed dependency/runtime + fingerprint. The behavior revision declares no rendered-evidence change, supported by byte checks. +- Canonical skill sources and reference mappings were updated; project skills were regenerated with + `eforge install-skills --agent chatgpt`. No installed artifact was edited by hand. + +## Format review matrix + +| Format | Record contract / retained specialized ownership | +|---|---| +| bash_history | Nonempty command and username; parser owns history timestamp syntax. | +| cisco_asa | Existing source message parsing and field schema retained; firewall correlation stays specialized. | +| ecar | One object/action relation including FILE/RENAME; conditional required identity/network fields; sparse enrichment diagnostic. | +| proxy_access | Finite, nonnegative traffic/tunnel counters; existing proxy routing and transactions stay specialized. | +| snort_alert | Priority bounds and endpoint presence; existing IDS canonical/cryptographic checks retained. | +| syslog | Nonempty message/hostname; Linux message-specific lifecycle checks retained. | +| web_access | Status range, reconciled methods, finite/nonnegative counters. | +| windows_event_security | Metadata selectors/aliases, task variants, ClientPort conversion; contextual logon enrichment diagnostic. | +| windows_event_sysmon | Variant selection, source/destination address types and IPv6 correspondence, port bounds. | +| zeek_conn | SF duration/counter presence, valid transport, finite/nonnegative counters; zero-duration warning. | +| zeek_dhcp | String message-type list, finite/nonnegative lease; DHCP lifecycle remains specialized. | +| zeek_dns | Numeric/name relationships, answers/TTLs correspondence, float TTL elements, optional partial metadata. | +| zeek_files | Finite/nonnegative counters and typed lists; avoid requiring full file observation or cross-record equality. | +| zeek_http | CONNECT body semantics, reconciled methods, nonnegative body counters; HTTP/file agreement specialized. | +| zeek_ntp | Finite time/interval fields and nonnegative extension count; no blanket synchronized-server assumption. | +| zeek_ocsp | Typed values; reversed interval diagnostic; cryptographic verification remains specialized. | +| zeek_packet_filter | Existing boolean/string source-health contract; no inferred sibling evidence. | +| zeek_pe | Typed list elements; file/process/cryptographic identity stays specialized. | +| zeek_reporter | Existing source-health scalar contract; warnings can describe legitimate unusual evidence. | +| zeek_smb_files | Rename source name; SMB action/session/storage semantics remain specialized. | +| zeek_smb_mapping | Existing tree/share schema; topology and backing storage semantics remain specialized. | +| zeek_smtp | Typed recipient/forwarding lists; conversation/envelope/lifecycle checks remain specialized. | +| zeek_ssl | Typed certificate/protocol lists; TLS chain/observation checks remain specialized. | +| zeek_weird | Existing source diagnostic contract; unusual traffic itself is not a correctness violation. | +| zeek_x509 | Typed SAN lists and finite validity fields; reversed interval diagnostic, certificate checks specialized. | + +## Baseline evidence + +- Isolated environments: `/private/tmp/eforge-rv-baseline-env` and + `/private/tmp/eforge-rv-candidate-env`, each installed from its own frozen lockfile. Dependency diff + removes only json-logic-qubit and its six dependency. Package version stays 2.1.0. +- Nine frozen generation comparisons cover typed activity in default/threaded, SOF-ELK®/serial, + Splunk/threaded, filtered Zeek, system families, SMB phases, periodic content, foreground process + ownership, and process companions. All 236 artifact comparisons match. `generation.log` is + excluded; manifest creation times are normalized and every manifest file hash is independently + verified by `scripts/compare_cleanup_output.py`. Ground truth and observation sidecars are included. +- The extra resolver fixture was rejected by the existing capture harness because it is not in that + harness's frozen input inventory. This was a harness precondition failure, not output divergence. +- All 18 scenario fixtures compile in baseline and candidate in sequential fresh processes, including + Scenario 1.0, Scenario 2.0, industry and organization packs. Full compiled payloads match after + excluding only changed package-owned format/threshold/co-occurrence/behavior documents and their + effective_config/compiled digests. Scenario entities, supported configuration, provenance and pack + locks otherwise match exactly. +- Representative authoritative bundle: 1,045 records from 17 sources. Schema and correctness both + score 100% after correcting HTTP method policy. No generator correction was needed for this bundle. +- Three relevant slow fresh-process determinism tests passed (`--no-cov`). Routine checkpoint smoke + verifies suspended/resumed output against uninterrupted output, including emitted evidence. + +## Verification status + +Earlier full runs exposed stale behavior fingerprints while source files were still being edited, +plus skill-size/packaging expectations. These were corrected. Final passing results are recorded +below; the earlier failed runs are retained here as execution history. + +## Complete rule inventory + +The 42 `legacy-N` IDs retain a traceable mapping to the old co-occurrence rule order. New semantic +checks use descriptive IDs. Error rules gate correctness; warning rules are realism/context +diagnostics. Scalar type/constraint checks additionally apply to every declared field. + +| Rule | Category | Contract | +|---|---|---| +| `bash_history.legacy-1` | objective correctness | Command is non-empty | +| `bash_history.legacy-2` | objective correctness | Has username | +| `ecar.legacy-1` | objective correctness | PROCESS records have pid | +| `ecar.legacy-2` | context-dependent / realism diagnostic | PROCESS/CREATE records have canonical primary tid | +| `ecar.legacy-3` | context-dependent / realism diagnostic | PROCESS/TERMINATE records have canonical primary tid | +| `ecar.legacy-4` | objective correctness | All records have objectID | +| `ecar.legacy-5` | objective correctness | PROCESS/CREATE has image_path | +| `ecar.legacy-6` | context-dependent / realism diagnostic | PROCESS/CREATE has ppid | +| `ecar.legacy-7` | context-dependent / realism diagnostic | PROCESS/CREATE has command_line | +| `ecar.legacy-8` | context-dependent / realism diagnostic | THREAD/REMOTE_CREATE has target info | +| `ecar.legacy-9` | context-dependent / realism diagnostic | PROCESS/OPEN has source image | +| `ecar.legacy-10` | objective correctness | FLOW events have network fields | +| `ecar.legacy-11` | objective correctness | SERVICE/CREATE has service name | +| `ecar.legacy-12` | context-dependent / realism diagnostic | USER_SESSION LOGIN has principal | +| `ecar.object-action` | objective correctness | Unsupported object/action combination | +| `snort_alert.legacy-1` | objective correctness | Alert has valid priority | +| `snort_alert.legacy-2` | objective correctness | Alert has source and destination | +| `syslog.legacy-1` | objective correctness | Syslog has non-empty message | +| `syslog.legacy-2` | objective correctness | Syslog has hostname | +| `web_access.legacy-1` | objective correctness | Request has valid status code | +| `web_access.legacy-2` | objective correctness | Request has HTTP method | +| `windows_event_security.legacy-1` | context-dependent / realism diagnostic | Network logon (type 3) requires valid IP | +| `windows_event_security.legacy-2` | context-dependent / realism diagnostic | Interactive logon (type 2) uses local workstation | +| `windows_event_security.legacy-3` | context-dependent / realism diagnostic | Process creation has process name | +| `windows_event_security.legacy-4` | context-dependent / realism diagnostic | Logoff must have a logon type | +| `windows_event_security.legacy-5` | context-dependent / realism diagnostic | Logon has valid SID | +| `windows_event_security.legacy-6` | context-dependent / realism diagnostic | Failed logon has status code | +| `windows_event_security.legacy-7` | context-dependent / realism diagnostic | Special privileges has privilege list | +| `windows_event_security.legacy-8` | context-dependent / realism diagnostic | Process termination has process name | +| `windows_event_security.legacy-9` | context-dependent / realism diagnostic | Kerberos TGT has krbtgt service | +| `windows_event_security.legacy-10` | context-dependent / realism diagnostic | Kerberos service ticket has service name | +| `windows_event_security.legacy-11` | context-dependent / realism diagnostic | NTLM validation has workstation | +| `windows_event_security.legacy-12` | context-dependent / realism diagnostic | Kerberos preauth failure has status | +| `windows_event_security.legacy-13` | context-dependent / realism diagnostic | WFP connection has direction | +| `windows_event_security.legacy-14` | context-dependent / realism diagnostic | Explicit creds has target server | +| `sysmon.source-family` | objective correctness | IP address must agree with IPv6 flag | +| `sysmon.destination-family` | objective correctness | IP address must agree with IPv6 flag | +| `zeek_conn.legacy-1` | objective correctness | Completed connection (SF) has duration | +| `zeek_conn.legacy-2` | objective correctness | Completed connection (SF) has byte counts | +| `zeek_conn.legacy-3` | objective correctness | Connection has valid protocol | +| `zeek_conn.legacy-4` | context-dependent / realism diagnostic | Completed TCP (SF) cannot have zero duration | +| `zeek_dns.legacy-1` | context-dependent / realism diagnostic | DNS query has non-empty query field | +| `zeek_dns.legacy-2` | context-dependent / realism diagnostic | DNS response has rcode | +| `dns.qtype-name` | objective correctness | qtype and its name must agree | +| `dns.rcode-name` | objective correctness | rcode and its name must agree | +| `dns.answer-ttls` | objective correctness | Answers and TTLs must correspond | +| `zeek_http.legacy-1` | objective correctness | HTTP CONNECT must not have response body | +| `zeek_http.legacy-2` | objective correctness | HTTP response has method | +| `zeek_ocsp.interval` | context-dependent / realism diagnostic | Validity interval is reversed | +| `smb.rename-source` | objective correctness | Rename requires previous name | +| `zeek_x509.interval` | context-dependent / realism diagnostic | Validity interval is reversed | + +## Additional frozen-tree evidence + +- The one-hour mixed-platform `checkpoint-all-formats.yaml` baseline and candidate captures match + across all 26 hashed artifacts. Its 1,407 parsed records pass both record/schema gates at 100%. + This caught and corrected a parser conversion regression: Security `Protocol` is numeric, Sysmon + `Protocol` is textual. The regression now has a focused test. +- Across scenario comparisons, native files cover 22 formats. The three source-health/anomaly formats + (`zeek_packet_filter`, `zeek_reporter`, `zeek_weird`) did not appear in those bounded scenarios. + Their unchanged templates render identical native bytes in both environments; committed native + parser fixtures and schema witnesses cover them. This is renderer/parser coverage, not a claim + that those scenarios emitted all 25 formats. Expanding generation of those diagnostics is a + separate source-routing/observation investigation; no generator patch was made speculatively. +- Positive schema witnesses cover all 25 formats and all 43 Windows/Sysmon variants. Each required + field is removed in turn, and every bundled record rule has explicit positive/negative witnesses. + New tests include malformed definitions, malformed native inputs, optional DNS observations, + Sysmon protocol representation, source sentinels, engine-error outcomes, exact single-violation + acceptance, cached field plans, and clean command JSON failure envelopes. +- Correctness scoring now executes once per record in the normal scoring pass, retaining only + bounded diagnostic samples. On repeated parsed DNS records with tracemalloc enabled: 1,000 records + took 0.188 s, 10,000 took 1.867 s, and 20,000 took 3.757 s (about 5,300 records/s). Incremental traced + peak allocation was 14.9/12.0/12.0 KiB respectively, excluding the already-parsed input collection. + This measures the shared schema/correctness pass, not total multi-pillar evaluation memory. +- Final focused parser/evaluator/contract run: 322 passed. Relevant slow fresh-process determinism: + 3 passed in 25.64 s, without coverage. Ruff check/format and the revision-90 generation-behavior + declaration check pass. Full macOS routine and remote Linux/Windows CI results are recorded below when complete. + +## Final parser boundary repair + +A final truncation probe found that an unterminated `` wrapper could yield zero parsed +records. Windows parsing now records unmatched/malformed wrappers as parse failures, while a +complete empty wrapper remains an empty input. Four regression cases cover this distinction; +271 parser/contract/evaluator tests pass after the repair. This changes no generated bytes. + +External CI has not run: automatic approval review rejected `git push` because external publication +was not explicitly authorized. No push occurred. The committed branch and draft-PR description are +prepared locally; user approval to push/open the draft is required to run Linux/Windows CI. + +## Local completion results + +- Full macOS routine run: **8,844 passed, 67 skipped, 2,023 deselected**, without coverage + (338.69 seconds). The wrapper repair additionally passes its 271-test focused gate. +- A final HTTP boundary check extends the migrated CONNECT guard from only 200 to every 2xx + response. This is required by RFC 9110 section 9.3.6, not a new scenario restriction: + https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.6 . Seven explicit status-boundary tests + distinguish successful tunnels from failed CONNECT error responses. This affects evaluation only. +- Final focused rule/parser/checkpoint/behavior gate: **261 passed** in 23.93 seconds. A fresh + candidate generation after the final rule adjustment matches all 29 baseline artifacts again. +- Local work is complete. Remote Linux/Windows CI remains blocked solely on explicit approval to + publish the local feature branch and open a draft PR. + +## Full iteration-test follow-up (supersedes the completion statement above) + +At the user's request, ran the current `scenarios/iteration-test/scenario.yaml` unchanged against +baseline `787fd733` and candidate `3c4323fb`, using their isolated locked environments. Both CLI +commands ran from the same project root, with `--seed 42 --target default`, normal threaded +rendering, and the default checkpoint cadence. The Scenario 2.0 input uses six hours of collection, +two hours of warmup, the Meridian Healthcare Solutions organization pack 1.1.0, technology industry +pack 1.0.0, and the `enterprise_standard` observation profile. Input SHA-256: +`f397d25ebb47d21ae2232bd3d1022bcedc96eb8d75a58b65fa7db5462c24e9a4`. +Validation passed; no scenario, configuration, pack, or generator changes were made for this test. + +### Generation comparison: PASS + +- Both generate commands exited 0. Outputs are retained in + `/private/tmp/eforge-rv-iteration-baseline` and `/private/tmp/eforge-rv-iteration-candidate`. +- Both contain 143 files excluding `generation.log`; no files are missing or extra. All 141 files + other than the resolved scenario and generation manifest are raw-byte identical, including native + evidence, ground truth, observation/collection/storage sidecars, and payload/email artifacts. +- Independently verified all 142 file hashes in each generation manifest and each resolved-file + hash. Both seeds, targets, selected pack identities/digests, and runtime metadata match. +- `RESOLVED_SCENARIO.yaml` differs only in package-owned format definitions, migrated co-occurrence + rules, exact schema/correctness thresholds, and the three resulting configuration/document digests. + Authored scenario, resolved entities, assets, provenance, and other effective configuration match. +- `GENERATION_MANIFEST.json` differs only in `created_at`, `compiled_sha256`, + `resolved_file_sha256`, and `files.RESOLVED_SCENARIO.yaml`. +- Native data occupies 76,175,193 bytes. Both evaluators account for 123,105 records in 22 source + categories, including 25 `email_artifacts` records. This is 21 native log formats plus the artifact + category; this run does not contain Zeek NTP, packet_filter, reporter, or weird records. +- Comparison script and full enumerated metadata differences are retained at + `/private/tmp/eforge-rv-iteration-compare.py` and + `/private/tmp/eforge-rv-iteration-comparison.json`. + +### Evaluation: candidate integration defects found + +- Baseline evaluation completes its pillars, overall 96.3267, acceptance FAIL because temporal + integrity is 83.3333 against its unchanged 85 minimum. Its legacy record validator additionally + reports one eCAR FILE/RENAME false rejection (123,104/123,105 passing). +- Candidate parseability and plausibility pillars fail with `ConfigurationError: Format definition + not found: email_artifacts`. Their new generic format loading mistakenly includes this specialized + artifact source. These pillars are unmeasured; no 100% schema/correctness claim is warranted. +- The existing engine catches those pillar exceptions, continues producing a partial report, and + exits 0. Acceptance correctly fails for the unmeasured required gates, but the execution failure + is not surfaced as exit 22. This remains a gap in the requested explicit engine-error contract. +- Both baseline and candidate write validator warnings before the JSON document on stdout; the + candidate also writes pillar tracebacks there. Raw stdout is therefore not valid JSON. The prior + narrow JSON checks did not cover this richer input. Original stdout/stderr are retained separately; + `*-report.json` files extract the report object for diagnosis without rerunning evaluation. +- Candidate causality and timing match baseline exactly, including the same eight temporal-integrity + findings (40/48 expected-visible events correctly timed). Both load the observation manifest and + apply identical filtered/dropped/delayed/out-of-window accounting. +- Do not interpret the candidate's partial overall score (93.5685) as a realism regression: two + scoring pillars did not execute. The evidence bytes are identical. + +Reports: `/private/tmp/eforge-rv-iteration-{baseline,candidate}-report.json`; original captured output: +`/private/tmp/eforge-rv-iteration-{baseline,candidate}-eval.json` and corresponding `.err` files. +Next implementation work must restore specialized email-artifact handling without silently accepting +missing native schemas, surface pillar execution failures explicitly, and keep JSON stdout clean. +The full iteration scenario should become a regression gate for these interactions. + + +## Evaluator routing repair + +Implemented explicit Pydantic-validated source routes for all 26 parser sources: 25 native schemas +and the named email-manifest artifact validator. Shared command preflight and evaluation verify +registry completeness; duplicate parser registration, duplicate/missing/stale routes, unavailable +schemas, and unknown artifact validators fail explicitly. Inventory tests also reconcile all 25 +native emitter registrations and parse all 29 embedded Jinja template strings. + +Email artifacts retain their existing open extension metadata and optional fields. Known scalar and +recipient-list types are checked; malformed top-level shapes, sections, message entries, and dates +remain counted failures. Invalid values retain raw evidence but do not reach specialized indexes +(for example, a list-valued Message-ID cannot crash a dictionary lookup). Complete empty sections +remain empty inputs. Existing email/SMTP/file consistency checks remain active. + +Pillar execution failures now abort evaluation through the existing CLI exit-22 boundary, without +an incomplete quality report. Completed evaluations with failed acceptance retain exit 0. Logging +is configured on stderr for each CLI invocation, preserving clean JSON stdout across repeated +in-process invocations. Normal execution failures have concise diagnostics; verbose mode retains +explicit traceback access. CLI help, canonical evaluate skill, and shared validation references are +updated; installed skills were regenerated through `install-skills` (sandbox-authorized write). + +Coverage now includes 66 native render/parse/validate cases spanning all native formats and every +supported Windows/Sysmon variant, with explicit Bash and Snort source-native rendering paths. A +committed compact email/SMTP/connection fixture verifies normal scoring and cross-source subject +agreement; corrupt manifest cases verify completed failed acceptance rather than pillar crashes. +The slow iteration test generates twice in fresh processes, verifies manifest hashes, compares all +manifest-owned bytes including the resolved scenario, and requires all four pillars to complete +with exact schema/correctness scores. + +Generation behavior revision 91 declares `impact: none` for the expanded preflight/error surface; +package version remains 2.1.0. Two repaired fresh-process captures match all 141 baseline evidence +files and the pre-repair candidate, with manifest hashes independently verified. The first final +revision-91 slow-test capture also matches those 141 frozen-baseline files; metadata changes are +restricted to the packaged validation/behavior contracts and derived provenance hashes. + +The repaired full iteration evaluation parses all 123,105 records and completes every pillar: +schema and record correctness 100%; plausibility 96.88451591546246; causality 93.9846681096681; +timing 93.04839206783377. Overall is 96.32697441984939, acceptance FAIL solely for the unchanged +83.3333 temporal-integrity score against 85. No new evidence violation was found after repairing +routing. Original output remains unchanged; reports are in `/private/tmp/eforge-routing-final-report.json` +and corresponding `.err`, with comparison evidence in `/private/tmp/eforge-routing-byte-comparison.json`. + +Initial full routine run: 8,940 passed, one skill-word-limit failure, 67 skipped, 2,024 deselected. +The skill text was shortened and its focused gate passed. Final focused routing/parser cases: +143 passed; skill/routing gate: 96 passed. Checkpoint resume and behavior gates: 24 passed. +Final full routine and slow results follow below when complete. Linux/Windows CI remains unrun; +no branch publication is authorized by this repair request. + + +### Final repair gates + +- Full routine suite: **8,946 passed, 67 skipped, 2,024 deselected**, `--no-cov`, 352.20 seconds. +- Final routing/parser/engine/skill focused gate: **159 passed**, 4.25 seconds. +- Slow iteration plus determinism gate: **4 passed, 7 deselected**, `--no-cov`, 474.27 seconds. + This includes two complete fresh-process iteration generations and a full successful evaluation + execution; schema/correctness gates are 100%, while the known temporal gate still fails acceptance. +- Checkpoint suspension/resume and behavior manifest gate: **24 passed**, 24.80 seconds. +- Ruff check and format check pass (883 files); `git diff --check` is clean. Behavior revision 91 + digest: `01d8e495c09bb88c163a1142a30bf272eaf4fba201c29ccb26b3173c61eccbed`. +- Final revision-91 captures have identical file sets and all 142 manifest-owned files are identical + between fresh processes, including `RESOLVED_SCENARIO.yaml`. Against frozen baseline, all 141 + non-metadata evidence/sidecar/artifact files match. The only changed files are the resolved scenario + and generation manifest; resolved changes are exclusively the enumerated package-owned validation + documents and derived digests. Comparison details and hashes are retained in + `/private/tmp/eforge-routing-final-comparison.json`. +- Logs: `/private/tmp/eforge-routing-routine-final.log`, `/private/tmp/eforge-routing-final-focused.log`, + `/private/tmp/eforge-routing-slow.log`, `/private/tmp/eforge-routing-checkpoint.log`. +- Immutable baseline checkout remains clean. No generator correction, scenario/pack/overlay edit, + package-version bump, push, or PR publication occurred. Linux/Windows CI remains outstanding. + +## Pre-PR gap closure (2026-09-15) + +### Requirement matrix + +| Requirement | Status | Evidence / boundary | +|---|---|---| +| 1. Returned correctness/diagnostic/artifact execution errors | Passed | Scoring calls `require_evaluated` before aggregation; CLI fault injection checks exit 22, empty stdout, rule/source/variant/fields. Library compatibility remains `valid=False` plus errors/findings. | +| 2. Native malformed-record matrix | Passed | All 66 format/Windows variant witnesses; 2,044 required JSON/XML mutations; six malformed text timestamps; 51 rules through native parsing (101 pass/fail cases, one explicitly inapplicable native case); 310 JSON fields with null/empty/dash/object/bounds/nonfinite/list cases. | +| 2. Malformed values through all pillars | Passed | One combined CLI batch covers all 25 native formats, every required-field mutation and every JSON field with an invalid object. Exact source counts remain; completed FAIL exits 0. | +| 3. Historical checkpoint | Passed | Baseline suspension, untouched copy, exact refusal/no mutation, read-only status/verify, compatible hydration/resume, one migration, dependency diagnostics and 24 byte-identical evidence files against both uninterrupted controls. | +| 4. Scenario/config/pack compatibility | Passed | 55 comparison entries across two projects and Scenario 1.0/2.0; all command exits match. Supported effective values, entities, provenance, pack locks/build/import/hydration match. Detailed differences retained. | +| 4. Target generation bytes | Passed | Full iteration SOF-ELK serial and Splunk threaded captures: 141 evidence files each match baseline, with manifest hashes independently verified. | +| 4. Target evaluation | **Failed / merge blocker** | SOF-ELK Snare lacks the full XML contract and has ambiguous flattened field labels. No schema waiver or generation change made. Splunk JSON parser repaired; exact record gates now pass, but indicator accuracy is 71.9215%. | +| 4. Five-run full-evaluation performance | Passed | Isolated full parsing/all-pillar runs on the same 123,105-record baseline evidence; final median candidate 12.1033s versus 12.3028s baseline, with slightly lower peak RSS. | +| 4. Routine/slow/Ruff/behavior gates | Results below | First routine run found missing navigation in the expanded checkpoint reference; fixed and installer rerun. | +| 4. Linux/Windows CI | Externally pending | No publication authorized. Local macOS tests do not substitute for CI. | +| 5. Independent review / merge readiness | Externally pending | No independent review or PR publication. The target findings above remain explicit blockers. | + +### Repairs and demonstrated defects + +- Shared scoring now converts **returned** `evaluation_error` findings into `EvaluationError` + before aggregate totals, including diagnostics and artifact validators. Ordinary malformed evidence + is not an execution fault. The diagnostic boundary includes the rule, source, variant and fields. +- Bash epochs outside platform time range, or beyond Python's integer-string conversion limit, + previously raised before producing a record. Both now remain counted parse failures. +- The combined native mutation batch exposed an OCSP diagnostic comparing malformed operands, then + a distribution index using a dictionary-valued field as a key. Diagnostics now check operand + schema validity; parseability records schema failures in a run-local set. Later pillars consume + the usable-record view, while source totals and exact acceptance retain every malformed record. + Well-typed cross-field contradictions still reach specialized evaluators. No catch-and-continue + or acceptance relaxation was added. +- Baseline checkpoint hydration initially rejected frozen JSON Logic format documents. A narrowly + recognized immutable-snapshot decoder now promotes the two known legacy format documents and + threshold policy in memory. Full-document hashes must match, and native rendering templates must + remain identical. Stored snapshots are untouched; arbitrary old disk/internal syntax is still + rejected. Promoting only rule lists was insufficient: Windows renderer identity also depends on + canonical field metadata, which the final decoder preserves coherently. +- Full Splunk target evaluation exposed text-only web/proxy parsers. The new Apache JSON adapter + maps the existing target fields, preserves source-native values, rejects conflicting aliases and + malformed shapes/types/timestamps, and retains CONNECT authority versus ordinary request-path + semantics without inventing URL schemes. Compact native fixtures cover positive and corrupted + records through parsing, scoring and CLI acceptance. No emitter was changed. + +### Historical checkpoint evidence + +`tests/integration/test_validation_checkpoint_upgrade.py` is the reproducible slow gate. Set +`EFORGE_VALIDATION_BASELINE_PYTHON=/private/tmp/eforge-rv-baseline-env/bin/python` and run it with +`-m slow --no-cov`. Routine decoder tests use committed immutable baseline YAML fixtures, so they +need no external checkout. The mixed Windows/Linux fixture has one hour warmup, three hours of +collection, seed 42, hourly checkpoints, and the existing synchronization harness. + +The verified run preserved the suspended checkpoint byte-for-byte. Exact policy exited 1 and +left every checkpoint/bundle file hash unchanged; status and full scratch verification also left +it unchanged. Compatible resume exited 0, recorded `accepted_policy=compatible`, migration count 1, +and removal of `json-logic-qubit`. It retained `output_equivalence=not-guaranteed` for runtime drift. +All 24 evidence/ground-truth/observation files matched both controls. Resolved scenario and generation +manifest differences are validation snapshots, derived fingerprints, generation/resume timestamps, +and migration lineage. Byte equality is evidence for this run, not a compatibility guarantee. + +The first scratch verifier attempt hit macOS's `/var` symlink ancestry guard. The harness now uses +its resolved private temporary directory for scratch storage; the safety guard was not bypassed. +An existing classifier initializes any nonempty behavior history as `localized`, including a history +containing only `impact: none` entries. That conservative diagnostic remains unchanged; it does not +prevent compatible hydration or strengthen the output-equivalence guarantee. + +### CLI/configuration comparison + +Scratch harness `/private/tmp/eforge-gap-compat.py` runs baseline and candidate in isolated processes, +with multiple project scopes sequentially inside each process. Both have 55 result entries and no +nonzero command exits. Coverage includes input/resolved validation, resolve JSON, configuration JSON, +CWD/explicit/no-ancestor resolution, two DNS overlays, Scenario 1.0/2.0, organization/industry closure, +pack validation/build/inspect/import/hydration, exact locks, and legacy text/JSON eval. A repeated +project-A check after project B matches A's initial configuration. + +Compiled-document differences are limited to the already enumerated 20 format documents, packaged +co-occurrence/threshold documents, and effective/compiled digests. Scenario, supported overlays, +field provenance and locks do not differ. Resolve JSON differs only in `compiled_sha256`. +Validation text additionally reports changing available memory/disk. Eval retains existing keys; +expected differences are exact thresholds, structured findings, current validation counts/details, +execution timing and evaluated timestamp. Pack JSON and immutable release locks match exactly. +Full outputs: `/private/tmp/eforge-gap-compat-{baseline,candidate}/results.json`; comparison: +`/private/tmp/eforge-gap-compat-comparison.json`. + +### Newly exposed target boundaries + +Both targets contain 123,105 records from 22 sources; baseline/candidate bytes match in all 141 +non-metadata files per target. SOF-ELK serial and Splunk threaded captures are retained under +`/private/tmp/eforge-gap-{sof-elk,splunk}-{baseline,candidate}`. Hash comparison: +`/private/tmp/eforge-gap-target-comparisons.json`. + +SOF-ELK evaluation completes but schema compliance is 75.4397%: all 18,718 Windows Security and +11,517 Sysmon records lack XML-only `Level`, `ExecutionProcessID`, and `ExecutionThreadID` metadata. +Security labels also map `SourceAddress`/`DestAddress` to `SourceIp`/`DestinationIp` and flatten +subject/target identities into repeated labels that the current parser cannot scope reliably. +This is a projection-contract and information-preservation issue, not a missing Jinja template. +The full inventory is retained in `/private/tmp/eforge-gap-snare-audit.log`. A compact Snare fixture +keeps the failure visible. Defining a native projection contract and repairing lost identity scope +requires separate work; silently making XML fields optional would conceal it. + +Splunk initially rejected all 2,236 proxy and 822 web records. After its parser repair, schema and +correctness are 100%; overall score is 95.3330. Its indicator accuracy of 71.9215% is now exposed by +complete parsing (1,063/1,478 checks), including proxy and Windows username mismatches. It needs a +separate trace-matching/identity investigation; the evaluator must not invent missing identities or +weaken the gate. Temporal integrity remains 83.3333% versus 85, as before. These findings, and the +packet-filter/reporter/weird generation investigation, remain separate from validation-rule fixes. + +### Final evidence and repository gates + +- Fix commits: `9c89e83d` (returned execution errors and malformed evidence), `cd6463f7` + (historical snapshot recovery), `68cd5dd8` (Splunk web/proxy parsing). Generator code and package + version are unchanged. Behavior revision 92 declares validation snapshot decoding with no + generation impact; behavior manifest checks pass. +- **Routine:** 11,439 passed, 68 skipped, 2,025 deselected, `--no-cov`, 368.81s. + The additional deliberate native skip is the unrepresentable empty Bash filename-derived username. +- **Slow:** 5 passed, 7 deselected, `--no-cov`, 482.28s: complete iteration fresh-process pair, + authoritative observation-overlay evaluation, public seed determinism, hash-seed storage identity, + and historical baseline checkpoint upgrade. The final default capture matches all **141** baseline + evidence files; both fresh candidate captures match all **142** manifest-owned files including + resolved input. Manifest-owned hashes are independently verified. +- **Final focused:** 152 passed, 2,456 deselected, 8.11s: error routing, snapshot decoder, target JSON, + behavior provenance, combined 25-format malformed-record evaluation, and oversized Bash epochs. +- Existing routine cutoff/partial-observation guards remain active, including + `test_firewall_teardown_after_export_window_is_marked_unobserved` and + `test_pre_window_or_observation_gap_is_not_scored`. The dedicated slow observation-profile test + verifies authoritative bundle configuration and intentional missingness through causality scoring. +- **Performance:** five isolated full evaluations per revision, alternating interpreters, identical + 123,105-record heterogeneous baseline bundle, all four pillars complete, all exits 0. Median wall + time baseline **12.3028s**, candidate **12.1033s** (1.62% faster). Median peak process RSS baseline + **777,846,784 bytes**, candidate **774,471,680 bytes** (0.43% lower). Includes imports, parsing and + all pillars. No >20% regression to investigate; these measurements are not CI timing assertions. +- **Ruff:** check and format check pass (892 Python files). `git diff --check` is clean. Canonical + references were regenerated through `install-skills`; installer/reference contracts pass. +- Immutable baseline checkout remains clean. No push, PR, version bump, generator modification, + `attempt` policy, or relaxed threshold was used. Linux/Windows CI and independent review remain + pending; **merge readiness is not established**, including the target-specific findings above. + +Machine-readable results and comparison hashes are committed in +[validation-gap evidence](2026-09-15-validation-gap-evidence.json). Full logs are retained at +`/private/tmp/eforge-gap-routine-final.log`, `/private/tmp/eforge-gap-slow.log`, +`/private/tmp/eforge-gap-final-focused.log`, and `/private/tmp/eforge-gap-performance-final/`. +Historical preserved checkpoint and controls are in +`/private/tmp/eforge-gap-slow-final/test_baseline_checkpoint_upgra0/`. + +Reproducible verification tools (run from the repository, with new output directories): + +```bash +# Repeat for the candidate interpreter into a separate directory. +/private/tmp/eforge-rv-baseline-env/bin/python scripts/capture_validation_compatibility.py \ + --output /private/tmp/validation-compat-baseline-new + +/private/tmp/eforge-rv-candidate-env/bin/python scripts/benchmark_validation.py \ + --baseline-python /private/tmp/eforge-rv-baseline-env/bin/python \ + --candidate-python /private/tmp/eforge-rv-candidate-env/bin/python \ + --bundle /private/tmp/eforge-rv-iteration-baseline \ + --output /private/tmp/validation-performance-new + +EFORGE_VALIDATION_BASELINE_PYTHON=/private/tmp/eforge-rv-baseline-env/bin/python \ + uv run --no-sync pytest tests/integration/test_validation_checkpoint_upgrade.py -m slow --no-cov +``` + +The committed CLI capture tool was exercised against both isolated environments after its extraction +from the scratch harness: 55 results per revision, all exits 0, equal supported configuration and +pack operations. CWD/explicit effective configuration matches; no-ancestor mode excludes the parent +overlay; project A retains its values after project B. The `.efpack` archives are byte-identical: +`43433bfe3c0769748320318ab41261fd626e1471fa464c5420b0dfe3acf0757d`. + +Baseline target evaluations independently confirm these parser/projection gaps predate this branch: +SOF-ELK baseline schema/correctness are both 75.4389%; Splunk baseline schema is 97.5151%. +Both baseline runs complete with failed acceptance. Candidate native Splunk parsing repairs its +3,058 rejected HTTP records; the small remaining baseline/candidate schema difference is the +previously documented eCAR rename validation defect. Original baseline target reports are retained +as `/private/tmp/eforge-gap-{sof-elk,splunk}-baseline-report.json` and included in the evidence summary. + +## SOF-ELK parser investigation and Splunk anonymous-user repair + +This section supersedes the earlier Splunk indicator investigation and narrows the SOF-ELK +assessment: missing XML system metadata does **not** establish incorrect Snare rendering. + +### Upstream SOF-ELK findings + +Inspected the actual preprocessing and extraction configuration at our harness pin +`517af9445574cc084cd5f4b80539fc244dab82b0` and current upstream main +`a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b`: + +- [1010 preprocessing](https://github.com/philhagen/sof-elk/blob/517af9445574cc084cd5f4b80539fc244dab82b0/configfiles/1010-preprocess-snare.conf) + removes MSWinEventLog and converts tabs into CSV separators. Our envelope uses this contract. +- [6010 extraction at the pin](https://github.com/philhagen/sof-elk/blob/517af9445574cc084cd5f4b80539fc244dab82b0/configfiles/6010-snare.conf) + reads Snare criticality, counter, channel, provider, computer, log type and expanded message. + It does not require XML Level/ExecutionProcessID/ExecutionThreadID. Criticality and Snare counter + are their own fields, not interchangeable XML metadata. Our XML-schema requirement is wrong for + this representation; adding invented XML values would also be wrong. +- SourceIp/DestinationIp map to ECS source.ip/destination.ip. These labels are intentional. + SourcePort/DestinationPort have explicit patterns, but the retained 5156 fixture's DestPort does + not match DestinationPort. Successful ingestion is therefore weaker than complete extraction. +- Repeated Security ID, Account Name, Account Domain and Logon ID labels feed generic fields. + There is no event-specific subject/target reconstruction in these patterns. Our parser additionally + overwrites repeated labels. Preserve the raw ordered occurrences; do not assign scope by guessing. +- Sysmon UtcTime overrides the syslog timestamp; the local-system timestamp is retained separately. + Hex process/logon IDs are converted, hashes are split, and backslashes are normalized to slashes. + These are explicit projection semantics to account for in comparison tests. +- [Current main](https://github.com/philhagen/sof-elk/blob/a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b/configfiles/6010-snare.conf) + now distinguishes New Process ID/Creator Process ID and New Process Name/Creator Process Name. + Our renderer's generic Process ID/Process Name matches the older pin, so parser-version coverage + matters. Both inspected versions retain notes about unhandled Security messages. +- Our external Snare harness currently checks event ID/provider/channel/computer and ingestion tags; + it does not assert full account/process/network extraction. This explains why that gate could pass + while internal XML-based evaluation fails. This investigation was source inspection, not a fresh + Logstash execution; the sandbox could not access the Docker socket. + +Recommended implementation: explicit Snare representation metadata and a typed native-envelope +contract, event-specific unambiguous alias normalization, ordered repeated-label retention, and +field-level external-parser assertions against a declared upstream revision. Apply shared rules to +facts the representation actually carries; report unavailable scope explicitly. Retain full XML +requirements for XML. Separately demonstrate any rendering incompatibility before authorizing a +renderer change. No Snare parser/schema/renderer changes were made in this follow-up. + +### Splunk fix and evidence + +Apache JSON `user: "-"` now means absent authenticated identity, matching the text parsers. +Normalization happens after alias conflict detection, preserving errors for contradictory +`user`/`username` values in either order. Real usernames, domain-qualified users, and machine accounts +are retained; actual wrong usernames still fail indicator checks. Regression coverage includes +parsing, schema scoring, indicator checks, and CLI accounting/acceptance for conflicting aliases. + +Full retained Splunk iteration evaluation completed with exit 0 and one JSON report: +`/private/tmp/eforge-gap-splunk-normalized-report.json` (stderr in the adjacent `.err` file). +All 123,105 records remain counted. Schema/correctness remain 100%; indicator accuracy improves +from 1,063/1,478 (71.9215%) to 1,063/1,080 (98.4259%), matching the default target. The 398 removed +checks were comparisons against the no-user sentinel. The sole failing acceptance gate is unchanged +83.3333% temporal integrity versus 85%. No evidence regeneration or generator modification occurred. + +### Deferred temporal work + +At the user's direction, TODO now tracks temporal integrity as a separate **P1, deferred** item. +The eight findings are event indices 0 (-152s), 11 (-172s), 24 (-188s), 28 (+198s), 29 (+313s default, ++314s Splunk), 33 (ordering), 42 and 44 (missing traces). Timing tolerance is 120s. These require +separating matcher expectations from canonical/source-observation timing before prescribing fixes. +Thresholds and generated evidence remain unchanged. The obsolete Splunk investigation was removed; +the diagnostic Zeek generation-coverage follow-up remains separately tracked. + +Verification for this follow-up: **89 passed** (Apache JSON and native evaluator parsers), 4.46s, +`--no-cov`; Ruff check/format (892 files), behavior-manifest check, and diff whitespace check pass. +The earlier full routine/slow results above precede this narrow normalization fix; those suites were +not rerun. No branch publication or PR was performed. + +## Snare data preservation and representation-aware validation + +This implementation supersedes the Snare investigation and pending recommendation above. Work +continues locally on `codex/record-validation`; the pre-Snare comparison commit is `2c899b06`. +Original baseline `787fd733` and its isolated environment remain untouched. Package version remains +2.1.0. No branch publication or PR is authorized or performed. + +### Contracts and field dispositions + +The companion `2026-09-15-snare-field-inventory.json` inventories all **43 variants / 826 declared +field slots**, including optional fields. Each slot names its canonical field, previous disposition, +current labels, upstream extraction destinations and committed fixture witness. Optional fixture +values are synthetic contract witnesses, not facts added to generated events. The 43 minimal native +fixtures remain covered alongside the expanded optional-field fixtures. + +- Typed, exhaustive, package-owned YAML projections replace the global Security label mapping. + Generic account labels consistently select one event-appropriate identity; scoped subject and + target values remain independently available. New/creator process aliases use their actual owners. +- `DestPort` now supplies the supported `DestinationPort` alias. Hex ProcessId values retain their + canonical spelling and provide a decimal view where required by upstream patterns. +- Level, execution IDs, precise TimeCreated, Windows EventRecordID, zero and empty string values are + retained when supplied. Private bookkeeping and absent values are not emitted. Envelope position, + timestamp convention, and existing whitespace/tab/newline/double-pipe sanitization remain stable. +- Subject/target/linked logon IDs use protected `Canonical[...]` labels: the upstream `LogonId:` + pattern is unanchored and otherwise captures scoped names. The selected `Logon ID` display alias + remains available for generic Security extraction. These are distinct downstream field names. +- Current upstream requires an execution-PID fallback for events without an actor/new-process PID. + It comes only from supplied ExecutionProcessID, and internal normalization preserves that owner. + A trailing projection marker prevents whitespace trimming from hiding the final real field from + upstream patterns requiring two spaces after a value. +- Supplied Sysmon UtcTime is no longer overwritten with TimeCreated. XML truth comparison exposed + **9,011 affected Sysmon rows** in the iteration scenario. Missing UtcTime retains the existing + fallback; no canonical event time is generated or moved by this renderer repair. + +The parser distinguishes XML and Snare explicitly. Snare validates its own typed envelope and +projection; criticality/counter do not masquerade as Windows Level/EventRecordID. Ordered repeated +labels survive parsing. Historical unscoped identities are not guessed; missing unavailable facts +produce structured not-applicable findings with counts and bounded examples. Current projections +must supply their required facts. Conflicting aliases, malformed numeric fields, invalid timestamps, +and missing required fields remain counted failures through CLI acceptance. Engine-error versus +ordinary FAIL exit semantics are unchanged. + +### External compatibility + +Actual Docker/Filebeat/Logstash pipelines are exercised at both frozen revisions: + +- `517af9445574cc084cd5f4b80539fc244dab82b0` (existing harness pin). +- `a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b` (frozen current upstream). + +The harness's existing small-file path-identity adapter removes upstream compression auto-detection +for uncompressed staged fixtures; Filebeat otherwise refuses that combination. Upstream Logstash +filters are unmodified. The existing optional-enrichment `_grokparsefail_6010-01` policy remains; +no new tag exemption was added. Current upstream `_grokparsefail_6010-02` was repaired by the truthful +execution-PID fallback, not waived. + +Fixtures include distinct subject/target users, child/creator processes, hexadecimal IDs, all optional +fields, IPv6, zero ports, Unicode paths, and command-line punctuation. Assertions cover record counts, +existing tag policy, values and types, identity/process/network ownership, Sysmon event time and +optional metadata. Raw preservation does not imply indexed fields: both revisions omit zero ports +under POSINT patterns and do not extract many canonical system/scoped fields. Those values remain +in the raw record. Native whitespace sanitization is not byte-for-byte preservation of pre-render +strings. No upstream parser modification is required for these dispositions. + +### Verification and reproducibility + +Final execution results and generation evidence are recorded below for the frozen-source runs. +The external suite is opt-in; a skipped run is not a passing external gate: + +```sh +uv run --no-sync pytest tests/external_parser/test_snare_projection_matrix.py \ + -m external_parser --include-external-parsers --no-cov +uv run --no-sync pytest tests/unit/test_snare_projection.py --no-cov +uv run --no-sync pytest tests/integration/test_iteration_validation.py -m slow -k sof-elk --no-cov +uv run --no-sync pytest tests/integration/test_checkpoint_smoke.py --no-cov +uv run --no-sync pytest --no-cov +uv run --no-sync python scripts/check_generation_behavior.py --base-ref 2c899b06 +uv run --no-sync ruff check . +uv run --no-sync ruff format --check . +``` + +The Snare projection loader is registered with the existing trusted derived-cache contract; otherwise +checkpoint generation correctly rejected the unknown cached loader. The macOS mixed-format +checkpoint test also exposed a tool-owned `/var` versus `/private/var` temporary-path alias: checkpoint +verification now resolves that scratch root before Snort hydration, preserving ancestry enforcement. +Generation behavior revision **93** declares localized Windows source-native projection changes. + +Canonical evaluation references and documentation describe historical ambiguity, unavailable checks, +raw versus indexed fields, and source-specific metadata. Installed Codex skills are regenerated only +through `eforge install-skills --agent codex`. Temporal-integrity repair remains separately deferred +P1; diagnostic Zeek generation coverage remains a separate P2 investigation. Linux/Windows CI and +independent review remain publication-dependent merge gates. + +### Final local evidence + +- **Routine:** 11,608 passed, 70 skipped, 2,026 deselected, 437.95s, `--no-cov`. + Log: `/private/tmp/eforge-snare-routine-delivery.log`. The later fixture-only refinements are also + covered by 226 focused native/installer/behavior checks (4.40s). +- **Iteration slow:** 1 passed (SOF-ELK target), 386.44s; generates twice in fresh processes, verifies + every manifest hash, compares all covered bytes, and completes all four evaluation pillars. + Log: `/private/tmp/eforge-snare-complete.log`; outputs are under + `/private/tmp/eforge-snare-complete/test_iteration_fresh_process_b0/{first,second}`. +- **Checkpoint:** default and mixed Windows/Linux SOF-ELK suspend/verify/resume match uninterrupted + controls; 25 checkpoint/behavior tests passed in 60.18s. The original-baseline compatibility slow + test also passed (1 test, 51.37s). Snare's localized behavior change is declared, not misrepresented + as guaranteed equivalence with old rendering. +- **Candidate evaluation:** `/private/tmp/eforge-snare-delivery-report.json` is one complete JSON + object, exit 0; stderr is separate. All 123,105 records are counted. Spec Conformance and Format + Constraints are 100%. Temporal integrity remains 83.3333% versus 85%, the sole failed gate. +- **Byte comparison:** `2026-09-15-snare-generation-evidence.json` records hashes and per-variant label + differences. Both runs contain 142 covered files. Twenty Snare files and RESOLVED_SCENARIO.yaml + differ from the retained pre-change target bundle; the other 121 are byte-identical. Resolved + differences are the added packaged projection YAML and associated configuration digests. +- **XML truth comparison:** `2026-09-15-snare-xml-truth-evidence.json` matches all 18,718 Security and + 11,517 Sysmon records by host/EventID/EventRecordID. UtcTime now agrees for every Sysmon row. + Remaining differences are timestamp spelling, XML template defaults absent from canonical event + input, preserved native whitespace sanitation, and RestrictedSidCount string-to-integer typing. + No generated facts were invented to imitate XML template placeholders. +- **External optional-field results:** both frozen revisions pass 45-record pipelines, including all + optional field witnesses (97.23s). The stronger assertions exposed upstream RuleName array typing, + qualified-name requirements, and raw-only ParentImage/CurrentDirectory. Both revisions replace + backslashes before the latter fields' backslash-dependent patterns; actual rows confirm absent + destinations with intact raw fields and unchanged unrelated extraction. These are documented + unsupported extraction paths, not claimed successful indexing. No unsafe alternative labels or + upstream filter edits are introduced. +- Ruff check, Ruff format (895 files), behavior revision/digest against `2c899b06`, and diff whitespace + checks pass. Canonical references were regenerated with the installer; the reference/link tests + pass. External skipped runs are excluded from pass evidence. + +| Requirement | Status | Evidence | +|---|---|---| +| Every variant/field disposition | Passed | 43 variants, 826 slots, full/minimal committed fixtures and inventory | +| Typed projections and native/legacy normalization | Passed | Native tests, CLI corruption accounting, unavailable findings | +| Both actual external parsers | Passed | Opt-in 45-record pipelines at both frozen revisions | +| Optional-field interference / extraction | Passed with explicit raw-only limitations | Assertions and upstream pattern dispositions above | +| Full iteration byte equality and hashes | Passed | Generation evidence JSON; 121 unaffected files identical | +| Fresh-process and checkpoint determinism | Passed | Slow iteration and mixed-target checkpoint controls | +| Full evaluation | Completed FAIL | Schema/correctness 100%; unchanged temporal P1 failure | +| Routine / Ruff / behavior / skills | Passed | Logs and commands above | +| Linux/Windows CI and independent review | Externally pending | No publication authorized | +| Temporal repair and diagnostic Zeek generation coverage | Deferred | Existing separate P1/P2 roadmap items | + +The final external gate adds actual tab/newline/double-pipe command-line input to the Unicode +witness: **2 passed, 96.64s**, 45 records per frozen revision. Log: +`/private/tmp/eforge-snare-external-accepted.log`; extracted JSON and staged inputs are retained under +`/private/tmp/eforge-snare-external-accepted/test_all_snare_variants_extrac{0,1}/runtime/`. +This supersedes the earlier external runs. The only remaining upstream extraction limitations are +explicit raw-only dispositions, not missing event facts or waived ingestion failures. TODO records +the upstream pattern follow-up separately; the Snare preservation/evaluation task is locally complete. +Rendering/projection and evaluator integration share one implementation commit because the shared +contract is required by both; expanded external verification and documentation are committed separately. + +Local implementation commits: `1e91cf1b` (projection/validation), `2526cda3` (checkpoint scratch path), +`7b2ea369` (external and generation gates). Final native/installer/documentation checks: **205 passed, +3.97s**. Installed skills were regenerated after the final canonical-reference update. + +## Failed-logon requester, target, and DC correction + +Corrected `evt-011` to target `WS-AJOHNSON-01` while retaining `root` as the actor and +`10.10.1.99` as the authored requester. Failed-logon generation now classifies locality from logon +type instead of source/target address equality, preserves requester identity independently from the +authentication target, renders 4776 `Workstation` from the requester system, and canonicalizes a +genuinely DC-local 4771 to `::1` with port `0`. Weighted Kerberos/NTLM selection is unchanged. +Generation behavior revision **94** declares the localized authentication/source-native change. + +The deterministic evaluator now matches failed-logon evidence by authored `target_username`, treats +missing or `-` source values as mismatches when a source was authored, validates supporting 4771/4776 +records on modeled DCs, and compares their client IP/workstation to the requester. DC traces remain +optional. The 4771 format contract now requires a valid IP address; positive native fixtures were +updated accordingly. + +Verification: + +- Scenario validation: valid, 0 errors, 0 warnings, 24 pre-existing informational pivot suggestions. +- Focused auth/evaluator coverage: 135 passed; the five affected cross-contract regressions also pass. +- Routine suite: **11,635 passed, 48 skipped, 2,026 deselected**, 371.22s, `--no-cov`. +- Ruff check and format pass; generation behavior revision/digest and diff whitespace checks pass. +- Fresh bundles are retained under `/private/tmp/eforge-record-validation-fixed-20260915/{sof-elk,splunk}`. + Both authoritative evaluations count 119,982 records, pass acceptance, and score 100% for schema + and format constraints. Both report 98.3021% indicator accuracy and 89.7959% temporal integrity. +- The corrected trace renders target-side 4625 and eCAR failure evidence on `WS-AJOHNSON-01` with + `aisha.johnson`, requester `LT-MRIVERA-02` / `10.10.1.99`, and destination `10.10.1.35`. + This seed selected NTLM, so DC-01 emits 4776 with `Workstation: LT-MRIVERA-02`; no 4771 is required. + +External ingest reruns: + +- **Splunk PASS:** all 119,532 supported records were indexed with exact expected/observed counts. + CIM-required validation used `Splunk_SA_CIM` 8.5.0 plus Microsoft Windows 10.0.1, Sysmon 5.0.0, + Cisco ASA 6.0.1, Zeek 1.0.11, and Apache 3.0.0 TAs from `~/TEMP/SplunkTA`. Authentication, + Change, Endpoint, Intrusion Detection, Network Traffic, and Web models were visible. Artifacts are + under `/private/tmp/eforge-record-validation-fixed-20260915/splunk-ingest/splunk/`. +- **SOF-ELK FAIL, upstream parser only:** all expected/observed counts match, and Windows Snare, + Zeek, ASA, web, and proxy validators pass. Thirteen valid OpenSSH close records receive + `_grokparsefailure_6015-01`, including `Connection closed by authenticating user svc_mgmt + 10.10.2.27 port 59644 [preauth]` and `Connection closed by invalid user unknown 10.10.2.25 port + 37379 [preauth]`. The failure report is + `/private/tmp/eforge-record-validation-fixed-20260915/sof-elk-ingest/sof-elk/parsed/sof_elk_parser_failures.json`. + No SOF-ELK parser or generated-log workaround was added. + +Remaining evaluator findings (for example the missing cleanup trace and pre-existing timing/pivot +findings) are unrelated to this correction and were not repaired here. `TODO.md` is unchanged. + +## Windows CI checkpoint newline correction + +PR #421's first CI run passed lint, Linux routine tests, and Windows checkpoint durability, but the +Windows routine suite exposed one byte-equivalence failure in the SOF-ELK checkpoint smoke test. +Uninterrupted `web_access.log` and `proxy_access.log` files used platform-translated CRLF framing, +while checkpoint external sorting used canonical LF framing. The ordinary per-host text writer now +opens append output with `newline="\n"`, matching the existing external-sort contract on every +platform. A unit regression verifies both the explicit newline argument and final sorted bytes. +Generation behavior revision **95** declares the Windows-only output normalization. Local +verification passes the focused regression and the SOF-ELK checkpoint suspend/resume smoke test; +Ruff, behavior-manifest, and whitespace checks also pass. Windows CI remains the authoritative +cross-platform confirmation before merge. + +## SOF-ELK upstream pin refresh + +Updated the default SOF-ELK revision from `517af9445574cc084cd5f4b80539fc244dab82b0` to +`d9f9bdd113a606c7b3fa1b2eafaa2d4400a16668`, which contains the upstream OpenSSH pre-auth close +parser repair. The web/proxy harness now follows the upstream content-preserving postprocessor +renames from `8060` to `8054` for user-agent enrichment and from `8110` to `8004` for HTTP +postprocessing. The emitted optional page-classification tag remains `_grokparsefail_8110-01`. + +The pinned upstream Cisco ASA filter also removed its scoped `tag_on_failure` value, so an expected +ASA classifier miss on an otherwise-valid generic Linux syslog record now receives Logstash's +generic `_grokparsefailure`. Record-for-record comparison showed that the 2,562 generic misses at +the new pin are an exact subset of the old revision's 2,575 `_grokparsefail_6018-01` misses; the 13 +removed records are exactly the OpenSSH rows repaired upstream. The harness accepts the generic tag +only for archived Linux syslog rows with complete parsed envelope fields, no successful specialized +parser, and no UniFi application-name shape. Generic failures remain fatal for malformed base +syslog, UniFi parsing, and Cisco ASA source records; ASA records still require `got_cisco` and +`parse_done`. The historical scoped rule remains supported for explicit older-revision tests. + +Verification: + +- Focused combined/source/Zeek/runtime harness tests: **56 passed**. +- Full retained iteration SOF-ELK pipeline: **PASS**, with exact expected/observed counts for all + **119,532 supported records** across 18 source families. The run used the repository default pin + without an override. Artifacts are under + `/private/tmp/eforge-record-validation-fixed-20260915/sof-elk-ingest-d9f9bdd-harness/sof-elk/`. +- External Docker compatibility suite: **5 passed in 277.88s**. This includes the 45-record Snare + field-extraction matrix at both the historical and new revisions, the default-pin Windows Snare + smoke test, every generated Zeek type, and intentional corrupt-Zeek rejection. +- Routine suite: **11,640 passed, 48 skipped, 2,026 deselected in 361.89s**, without coverage. +- Repository-wide Ruff check and format check pass. Generated records, scenario files, package + version, and `TODO.md` are unchanged. diff --git a/docs/worklog/2026-09-15-snare-field-inventory.json b/docs/worklog/2026-09-15-snare-field-inventory.json new file mode 100644 index 000000000..a7a7ff3af --- /dev/null +++ b/docs/worklog/2026-09-15-snare-field-inventory.json @@ -0,0 +1,16881 @@ +{ + "pre_snare_commit": "2c899b06", + "revisions": [ + "517af9445574cc084cd5f4b80539fc244dab82b0", + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b" + ], + "upstream_patterns": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + { + "label": "Security ID", + "destination": "[winlog][user][identifier]" + }, + { + "label": "Account Name", + "destination": "[winlog][user][name]" + }, + { + "label": "Account Domain", + "destination": "[user][domain]" + }, + { + "label": "Logon ID", + "destination": "[winlog][event_data][LogonID]" + }, + { + "label": "Process ID", + "destination": "[winlog][process][pid]" + }, + { + "label": "Process Name", + "destination": "[process][executable]" + }, + { + "label": "Exit Status", + "destination": "[process][exit_code]" + }, + { + "label": "CommandLine", + "destination": "[process][command_line]" + }, + { + "label": "Company", + "destination": "[winlog][event_data][Company]" + }, + { + "label": "Contents", + "destination": "[winlog][event_data][Contents]" + }, + { + "label": "CreationUtcTime", + "destination": "[winlog][event_data][CreationUtcTime]" + }, + { + "label": "CurrentDirectory", + "destination": "[process][working_directory]" + }, + { + "label": "Description", + "destination": "[winlog][event_data][Description]" + }, + { + "label": "DestinationHostname", + "destination": "[destination][domain]" + }, + { + "label": "DestinationIp", + "destination": "[destination][ip]" + }, + { + "label": "DestinationPort", + "destination": "[destination][port]" + }, + { + "label": "Details", + "destination": "[winlog][event_data][Detail]" + }, + { + "label": "EventType", + "destination": "[winlog][event_data][EventType]" + }, + { + "label": "FileVersion", + "destination": "[process][pe][file_version]" + }, + { + "label": "Hashes", + "destination": "[@metadata][Hashes]" + }, + { + "label": "IntegrityLevel", + "destination": "[winlog][event_data][IntegrityLevel]" + }, + { + "label": "Image", + "destination": "[process][executable]" + }, + { + "label": "Initiated", + "destination": "[@metadata][Initiated]" + }, + { + "label": "LogonGuid", + "destination": "[winlog][event_data][LogonGuid]" + }, + { + "label": "LogonId", + "destination": "[winlog][event_data][LogonId]" + }, + { + "label": "OriginalFileName", + "destination": "[process][pe][original_file_name]" + }, + { + "label": "ParentCommandLine", + "destination": "[process][parent][command_line]" + }, + { + "label": "ParentImage", + "destination": "[process][parent][executable]" + }, + { + "label": "ParentProcessGuid", + "destination": "[process][parent][entity_id]" + }, + { + "label": "ParentProcessId", + "destination": "[process][parent][pid]" + }, + { + "label": "ParentUser", + "destination": "[winlog][event_data][ParentUser]" + }, + { + "label": "PreviousCreationUtcTime", + "destination": "[winlog][event_data][PreviousCreationUtcTime]" + }, + { + "label": "ProcessGuid", + "destination": "[process][entity_id]" + }, + { + "label": "ProcessId", + "destination": "[process][pid]" + }, + { + "label": "Product", + "destination": "[winlog][event_data][Product]" + }, + { + "label": "Protocol", + "destination": "[network][transport]" + }, + { + "label": "QueryName", + "destination": "[dns][question][name]" + }, + { + "label": "QueryResults", + "destination": "[@metadata][QueryResults]" + }, + { + "label": "RuleName", + "destination": "[rule][name]" + }, + { + "label": "SchemaVersion", + "destination": "[winlog][event_data][SchemaVersion]" + }, + { + "label": "Signature", + "destination": "[winlog][event_data][Signature]" + }, + { + "label": "SignatureStatus", + "destination": "[winlog][event_data][SignatureStatus]" + }, + { + "label": "Signed", + "destination": "[winlog][event_data][Signed]" + }, + { + "label": "SourceHostname", + "destination": "[source][domain]" + }, + { + "label": "SourceImage", + "destination": "[winlog][event_data][SourceImage]" + }, + { + "label": "SourceIp", + "destination": "[source][ip]" + }, + { + "label": "SourcePort", + "destination": "[source][port]" + }, + { + "label": "SourceProcessGuid", + "destination": "[process][source][entity_id]" + }, + { + "label": "SourceProcessId", + "destination": "[process][source][pid]" + }, + { + "label": "SourceUser", + "destination": "[winlog][event_data][SourceUser]" + }, + { + "label": "StartAddress", + "destination": "[winlog][event_data][StartAddress]" + }, + { + "label": "StartFunction", + "destination": "[winlog][event_data][StartFunction]" + }, + { + "label": "StartModule", + "destination": "[winlog][event_data][StartModule]" + }, + { + "label": "State", + "destination": "[winlog][event_data][State]" + }, + { + "label": "TargetFilename", + "destination": "[winlog][event_data][TargetFilename]" + }, + { + "label": "TargetImage", + "destination": "[winlog][event_data][TargetImage]" + }, + { + "label": "TargetObject", + "destination": "[winlog][event_data][TargetObject]" + }, + { + "label": "TargetProcessGuid", + "destination": "[winlog][event_data][TargetProcessGuid]" + }, + { + "label": "TargetProcessId", + "destination": "[winlog][event_data][TargetProcessId]" + }, + { + "label": "TargetUser", + "destination": "[winlog][event_data][TargetUserName]" + }, + { + "label": "TerminalSessionId", + "destination": "[winlog][event_data][TerminalSessionId]" + }, + { + "label": "User", + "destination": "[@metadata][User]" + }, + { + "label": "UtcTime", + "destination": "[@metadata][UtcTime]" + }, + { + "label": "Version", + "destination": "[winlog][event_data][Version]" + } + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + { + "label": "Security ID", + "destination": "[winlog][user][identifier]" + }, + { + "label": "Account Name", + "destination": "[winlog][user][name]" + }, + { + "label": "Account Domain", + "destination": "[user][domain]" + }, + { + "label": "Logon ID", + "destination": "[winlog][event_data][LogonID]" + }, + { + "label": "New Process ID", + "destination": "[winlog][process][pid]" + }, + { + "label": "Creator Process ID", + "destination": "[winlog][process][parent][pid]" + }, + { + "label": "New Process Name", + "destination": "[process][executable]" + }, + { + "label": "Creator Process Name", + "destination": "[process][parent][executable]" + }, + { + "label": "Exit Status", + "destination": "[process][exit_code]" + }, + { + "label": "CommandLine", + "destination": "[process][command_line]" + }, + { + "label": "Company", + "destination": "[winlog][event_data][Company]" + }, + { + "label": "Contents", + "destination": "[winlog][event_data][Contents]" + }, + { + "label": "CreationUtcTime", + "destination": "[winlog][event_data][CreationUtcTime]" + }, + { + "label": "CurrentDirectory", + "destination": "[process][working_directory]" + }, + { + "label": "Description", + "destination": "[winlog][event_data][Description]" + }, + { + "label": "DestinationHostname", + "destination": "[destination][domain]" + }, + { + "label": "DestinationIp", + "destination": "[destination][ip]" + }, + { + "label": "DestinationPort", + "destination": "[destination][port]" + }, + { + "label": "Details", + "destination": "[winlog][event_data][Detail]" + }, + { + "label": "EventType", + "destination": "[winlog][event_data][EventType]" + }, + { + "label": "FileVersion", + "destination": "[process][pe][file_version]" + }, + { + "label": "Hashes", + "destination": "[@metadata][Hashes]" + }, + { + "label": "IntegrityLevel", + "destination": "[winlog][event_data][IntegrityLevel]" + }, + { + "label": "Image", + "destination": "[process][executable]" + }, + { + "label": "Initiated", + "destination": "[@metadata][Initiated]" + }, + { + "label": "LogonGuid", + "destination": "[winlog][event_data][LogonGuid]" + }, + { + "label": "LogonId", + "destination": "[winlog][event_data][LogonId]" + }, + { + "label": "OriginalFileName", + "destination": "[process][pe][original_file_name]" + }, + { + "label": "ParentCommandLine", + "destination": "[process][parent][command_line]" + }, + { + "label": "ParentImage", + "destination": "[process][parent][executable]" + }, + { + "label": "ParentProcessGuid", + "destination": "[process][parent][entity_id]" + }, + { + "label": "ParentProcessId", + "destination": "[process][parent][pid]" + }, + { + "label": "ParentUser", + "destination": "[winlog][event_data][ParentUser]" + }, + { + "label": "PreviousCreationUtcTime", + "destination": "[winlog][event_data][PreviousCreationUtcTime]" + }, + { + "label": "ProcessGuid", + "destination": "[process][entity_id]" + }, + { + "label": "ProcessId", + "destination": "[process][pid]" + }, + { + "label": "Product", + "destination": "[winlog][event_data][Product]" + }, + { + "label": "Protocol", + "destination": "[network][transport]" + }, + { + "label": "QueryName", + "destination": "[dns][question][name]" + }, + { + "label": "QueryResults", + "destination": "[@metadata][QueryResults]" + }, + { + "label": "RuleName", + "destination": "[rule][name]" + }, + { + "label": "SchemaVersion", + "destination": "[winlog][event_data][SchemaVersion]" + }, + { + "label": "Signature", + "destination": "[winlog][event_data][Signature]" + }, + { + "label": "SignatureStatus", + "destination": "[winlog][event_data][SignatureStatus]" + }, + { + "label": "Signed", + "destination": "[winlog][event_data][Signed]" + }, + { + "label": "SourceHostname", + "destination": "[source][domain]" + }, + { + "label": "SourceImage", + "destination": "[winlog][event_data][SourceImage]" + }, + { + "label": "SourceIp", + "destination": "[source][ip]" + }, + { + "label": "SourcePort", + "destination": "[source][port]" + }, + { + "label": "SourceProcessGuid", + "destination": "[process][source][entity_id]" + }, + { + "label": "SourceProcessId", + "destination": "[process][source][pid]" + }, + { + "label": "SourceUser", + "destination": "[winlog][event_data][SourceUser]" + }, + { + "label": "StartAddress", + "destination": "[winlog][event_data][StartAddress]" + }, + { + "label": "StartFunction", + "destination": "[winlog][event_data][StartFunction]" + }, + { + "label": "StartModule", + "destination": "[winlog][event_data][StartModule]" + }, + { + "label": "State", + "destination": "[winlog][event_data][State]" + }, + { + "label": "TargetFilename", + "destination": "[winlog][event_data][TargetFilename]" + }, + { + "label": "TargetImage", + "destination": "[winlog][event_data][TargetImage]" + }, + { + "label": "TargetObject", + "destination": "[winlog][event_data][TargetObject]" + }, + { + "label": "TargetProcessGuid", + "destination": "[winlog][event_data][TargetProcessGuid]" + }, + { + "label": "TargetProcessId", + "destination": "[winlog][event_data][TargetProcessId]" + }, + { + "label": "TargetUser", + "destination": "[winlog][event_data][TargetUserName]" + }, + { + "label": "TerminalSessionId", + "destination": "[winlog][event_data][TerminalSessionId]" + }, + { + "label": "User", + "destination": "[@metadata][User]" + }, + { + "label": "UtcTime", + "destination": "[@metadata][UtcTime]" + }, + { + "label": "Version", + "destination": "[winlog][event_data][Version]" + }, + { + "label": "Process ID", + "destination": "[winlog][process][pid]" + }, + { + "label": "Process Name", + "destination": "[process][executable]" + } + ] + }, + "variant_count": 43, + "field_count": 826, + "fields": [ + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:Level" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "TargetUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[TargetLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "LogonType", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:LogonType" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "LogonProcessName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:LogonProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "AuthenticationPackageName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "AuthenticationPackageName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:AuthenticationPackageName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "WorkstationName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "WorkstationName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:WorkstationName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "LogonGuid", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonGuid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonGuid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:LogonGuid" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TransmittedServices", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TransmittedServices" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TransmittedServices" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "LmPackageName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LmPackageName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:LmPackageName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "KeyLength", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "KeyLength" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:KeyLength" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "ProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "IpAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "IpPort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "ImpersonationLevel", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ImpersonationLevel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:ImpersonationLevel" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "RestrictedAdminMode", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RestrictedAdminMode" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:RestrictedAdminMode" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetOutboundUserName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetOutboundUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetOutboundUserName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetOutboundDomainName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetOutboundDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetOutboundDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "VirtualAccount", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "VirtualAccount" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:VirtualAccount" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "TargetLinkedLogonId", + "type": "hex_string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Canonical[TargetLinkedLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:TargetLinkedLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "ElevatedToken", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ElevatedToken" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:ElevatedToken" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "RemoteUserID", + "type": "sid", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RemoteUserID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:RemoteUserID" + }, + { + "source": "windows_event_security", + "event_id": 4624, + "variant": "logon", + "field": "RemoteMachineID", + "type": "sid", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RemoteMachineID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logon:RemoteMachineID" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:Level" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "TargetUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "TargetUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:TargetUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "TargetLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[TargetLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:TargetLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4634, + "variant": "logoff", + "field": "LogonType", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:logoff:LogonType" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:Level" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "AccountName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccountName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:AccountName" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "AccountDomain", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccountDomain" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:AccountDomain" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "LogonID", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:LogonID" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "SessionName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SessionName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:SessionName" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "ClientName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ClientName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:ClientName" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "ClientAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "ClientAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:ClientAddress" + }, + { + "source": "windows_event_security", + "event_id": 4778, + "variant": "rdp_session_reconnect", + "field": "ClientPort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "ClientPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_reconnect:ClientPort" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:Level" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "AccountName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccountName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:AccountName" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "AccountDomain", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccountDomain" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:AccountDomain" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "LogonID", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:LogonID" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "SessionName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SessionName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:SessionName" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "ClientName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ClientName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:ClientName" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "ClientAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "ClientAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:ClientAddress" + }, + { + "source": "windows_event_security", + "event_id": 4779, + "variant": "rdp_session_disconnect", + "field": "ClientPort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "ClientPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:rdp_session_disconnect:ClientPort" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:Level" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "NewProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "New Process ID", + "NewProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:NewProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "NewProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "New Process Name", + "NewProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:NewProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "TokenElevationType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TokenElevationType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:TokenElevationType" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Creator Process ID", + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][parent][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "CommandLine", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CommandLine" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][command_line]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][command_line]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:CommandLine" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "TargetUserSid", + "type": "sid", + "required": false, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "TargetUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:TargetUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "TargetUserName", + "type": "string", + "required": false, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "TargetDomainName", + "type": "string", + "required": false, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "TargetLogonId", + "type": "hex_string", + "required": false, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[TargetLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:TargetLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "ParentProcessName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Creator Process Name", + "ParentProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]", + "[process][parent][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:ParentProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4688, + "variant": "process_creation", + "field": "MandatoryLabel", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "MandatoryLabel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_creation:MandatoryLabel" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:Level" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "TargetUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "TargetUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:TargetUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "Status", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Status" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:Status" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "SubStatus", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SubStatus" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:SubStatus" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "FailureReason", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "FailureReason" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:FailureReason" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "LogonType", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:LogonType" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "LogonProcessName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:LogonProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "AuthenticationPackageName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "AuthenticationPackageName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:AuthenticationPackageName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "WorkstationName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "WorkstationName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:WorkstationName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "IpAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "IpPort", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "TransmittedServices", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TransmittedServices" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:TransmittedServices" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "LmPackageName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LmPackageName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:LmPackageName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "KeyLength", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "KeyLength" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:KeyLength" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "ProcessId", + "type": "hex_string", + "required": false, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "ProcessName", + "type": "string", + "required": false, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "RemoteUserID", + "type": "sid", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RemoteUserID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:RemoteUserID" + }, + { + "source": "windows_event_security", + "event_id": 4625, + "variant": "failed_logon", + "field": "RemoteMachineID", + "type": "sid", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RemoteMachineID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:failed_logon:RemoteMachineID" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:Level" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4672, + "variant": "special_privileges", + "field": "PrivilegeList", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "PrivilegeList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:special_privileges:PrivilegeList" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:Level" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "TargetUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "TargetUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:TargetUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "TargetLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[TargetLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:TargetLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4800, + "variant": "workstation_locked", + "field": "SessionId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SessionId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_locked:SessionId" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:Level" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "TargetUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "TargetUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:TargetUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "TargetLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[TargetLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:TargetLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4801, + "variant": "workstation_unlocked", + "field": "SessionId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SessionId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:workstation_unlocked:SessionId" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:Level" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "Status", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Exit Status", + "Status" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][exit_code]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][exit_code]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:Status" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4689, + "variant": "process_termination", + "field": "ProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:process_termination:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:Level" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "LogonGuid", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonGuid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonGuid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:LogonGuid" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "TargetLogonGuid", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetLogonGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonGuid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonGuid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:TargetLogonGuid" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "TargetServerName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetServerName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:TargetServerName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "TargetInfo", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetInfo" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:TargetInfo" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "ProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "IpAddress", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 4648, + "variant": "explicit_credentials", + "field": "IpPort", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:explicit_credentials:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:Level" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "ServiceName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:ServiceName" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "ServiceSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:ServiceSid" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "TicketOptions", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TicketOptions" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:TicketOptions" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "Status", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Status" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:Status" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "TicketEncryptionType", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TicketEncryptionType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:TicketEncryptionType" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "PreAuthType", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PreAuthType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:PreAuthType" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "IpAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "IpPort", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "CertIssuerName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CertIssuerName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:CertIssuerName" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "CertSerialNumber", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CertSerialNumber" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:CertSerialNumber" + }, + { + "source": "windows_event_security", + "event_id": 4768, + "variant": "kerberos_tgt", + "field": "CertThumbprint", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CertThumbprint" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_tgt:CertThumbprint" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:Level" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "ServiceName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:ServiceName" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "ServiceSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:ServiceSid" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "TicketOptions", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TicketOptions" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:TicketOptions" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "TicketEncryptionType", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TicketEncryptionType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:TicketEncryptionType" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "IpAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "IpPort", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "Status", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Status" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:Status" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "LogonGuid", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonGuid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonGuid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:LogonGuid" + }, + { + "source": "windows_event_security", + "event_id": 4769, + "variant": "kerberos_service_ticket", + "field": "TransmittedServices", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TransmittedServices" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_service_ticket:TransmittedServices" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:Level" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "PackageName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "PackageName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:PackageName" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "Workstation", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Workstation" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:Workstation" + }, + { + "source": "windows_event_security", + "event_id": 4776, + "variant": "ntlm_validation", + "field": "Status", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Status" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:ntlm_validation:Status" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:EventID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:Computer" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:Channel" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:Level" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "ProcessID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessId", + "ProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:ProcessID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "Application", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image", + "Application" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:Application" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "Direction", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Direction" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:Direction" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "SourceAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "SourceAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:SourceAddress" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "SourcePort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:SourcePort" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "DestAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "DestinationIp", + "DestAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[destination][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[destination][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:DestAddress" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "DestPort", + "type": "integer", + "required": true, + "previous": "incorrect downstream label", + "emitted_labels": [ + "DestinationPort", + "DestPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[destination][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[destination][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:DestPort" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "Protocol", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Protocol" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[network][transport]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[network][transport]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:Protocol" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "FilterRTID", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "FilterRTID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:FilterRTID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "LayerName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LayerName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:LayerName" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "LayerRTID", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LayerRTID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:LayerRTID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "RemoteUserID", + "type": "sid", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RemoteUserID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:RemoteUserID" + }, + { + "source": "windows_event_security", + "event_id": 5156, + "variant": "wfp_connection", + "field": "RemoteMachineID", + "type": "sid", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RemoteMachineID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:wfp_connection:RemoteMachineID" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:Level" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "ServiceName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:ServiceName" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "TicketOptions", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TicketOptions" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:TicketOptions" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "Status", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Status" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:Status" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "PreAuthType", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PreAuthType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:PreAuthType" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "IpAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "IpPort", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "CertIssuerName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CertIssuerName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:CertIssuerName" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "CertSerialNumber", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CertSerialNumber" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:CertSerialNumber" + }, + { + "source": "windows_event_security", + "event_id": 4771, + "variant": "kerberos_preauth_failed", + "field": "CertThumbprint", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CertThumbprint" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:kerberos_preauth_failed:CertThumbprint" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:EventID" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:Computer" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:Channel" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:Level" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 1102, + "variant": "log_cleared", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:log_cleared:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:Level" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ServiceName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ServiceName" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ServiceFileName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceFileName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ServiceFileName" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ServiceType", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ServiceType" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ServiceStartType", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceStartType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ServiceStartType" + }, + { + "source": "windows_event_security", + "event_id": 4697, + "variant": "service_installed", + "field": "ServiceAccount", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ServiceAccount" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:service_installed:ServiceAccount" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:Level" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "TaskName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:TaskName" + }, + { + "source": "windows_event_security", + "event_id": 4698, + "variant": "scheduled_task", + "field": "TaskContent", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskContent" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task:TaskContent" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:Level" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "MemberName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "MemberName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:MemberName" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "MemberSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "MemberSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:MemberSid" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4728, + "variant": "group_membership_change", + "field": "PrivilegeList", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PrivilegeList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:group_membership_change:PrivilegeList" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:Level" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "SamAccountName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SamAccountName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:SamAccountName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "DisplayName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "DisplayName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:DisplayName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "UserPrincipalName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserPrincipalName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:UserPrincipalName" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "HomeDirectory", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "HomeDirectory" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:HomeDirectory" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "HomePath", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "HomePath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:HomePath" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "ScriptPath", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ScriptPath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:ScriptPath" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "ProfilePath", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ProfilePath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:ProfilePath" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "UserWorkstations", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserWorkstations" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:UserWorkstations" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "PasswordLastSet", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PasswordLastSet" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:PasswordLastSet" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "AccountExpires", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "AccountExpires" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:AccountExpires" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "PrimaryGroupId", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PrimaryGroupId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:PrimaryGroupId" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "AllowedToDelegateTo", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "AllowedToDelegateTo" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:AllowedToDelegateTo" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "OldUacValue", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "OldUacValue" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:OldUacValue" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "NewUacValue", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "NewUacValue" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:NewUacValue" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "UserAccountControl", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserAccountControl" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:UserAccountControl" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "UserParameters", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserParameters" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:UserParameters" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "SidHistory", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SidHistory" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:SidHistory" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "LogonHours", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonHours" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:LogonHours" + }, + { + "source": "windows_event_security", + "event_id": 4720, + "variant": "account_created", + "field": "PrivilegeList", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PrivilegeList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_created:PrivilegeList" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:Level" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4723, + "variant": "password_change", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_change:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:Level" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4724, + "variant": "password_reset", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:password_reset:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:Level" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4726, + "variant": "account_deleted", + "field": "PrivilegeList", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PrivilegeList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_deleted:PrivilegeList" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:Level" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "TargetUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "TargetUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:TargetUserName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "TargetDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "TargetDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:TargetDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "TargetSid", + "type": "sid", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:TargetSid" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "SamAccountName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SamAccountName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:SamAccountName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "DisplayName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "DisplayName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:DisplayName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "UserPrincipalName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserPrincipalName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:UserPrincipalName" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "HomeDirectory", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "HomeDirectory" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:HomeDirectory" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "HomePath", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "HomePath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:HomePath" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "ScriptPath", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ScriptPath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:ScriptPath" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "ProfilePath", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ProfilePath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:ProfilePath" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "UserWorkstations", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserWorkstations" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:UserWorkstations" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "PasswordLastSet", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PasswordLastSet" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:PasswordLastSet" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "AccountExpires", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "AccountExpires" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:AccountExpires" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "PrimaryGroupId", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PrimaryGroupId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:PrimaryGroupId" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "AllowedToDelegateTo", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "AllowedToDelegateTo" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:AllowedToDelegateTo" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "OldUacValue", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "OldUacValue" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:OldUacValue" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "NewUacValue", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "NewUacValue" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:NewUacValue" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "UserAccountControl", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserAccountControl" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:UserAccountControl" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "UserParameters", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "UserParameters" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:UserParameters" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "SidHistory", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SidHistory" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:SidHistory" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "LogonHours", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonHours" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:LogonHours" + }, + { + "source": "windows_event_security", + "event_id": 4738, + "variant": "account_changed", + "field": "PrivilegeList", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "PrivilegeList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:account_changed:PrivilegeList" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:Level" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ObjectServer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectServer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ObjectServer" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ObjectType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ObjectType" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ObjectName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ObjectName" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "HandleId", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "HandleId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:HandleId" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "TransactionId", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TransactionId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:TransactionId" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "AccessList", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:AccessList" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "AccessReason", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessReason" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:AccessReason" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "AccessMask", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessMask" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:AccessMask" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "PrivilegeList", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "PrivilegeList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:PrivilegeList" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "RestrictedSidCount", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "RestrictedSidCount" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:RestrictedSidCount" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4656, + "variant": "object_handle_requested", + "field": "ResourceAttributes", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ResourceAttributes" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_requested:ResourceAttributes" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:Level" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "ObjectServer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectServer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:ObjectServer" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "HandleId", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "HandleId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:HandleId" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4658, + "variant": "object_handle_closed", + "field": "ProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_handle_closed:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:Level" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ObjectServer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectServer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ObjectServer" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ObjectType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ObjectType" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ObjectName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ObjectName" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "HandleId", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "HandleId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:HandleId" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "AccessList", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:AccessList" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "AccessMask", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessMask" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:AccessMask" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ProcessId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Process ID", + "ProcessId", + "Canonical[ProcessId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ProcessId" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ProcessName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Image", + "ProcessName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ProcessName" + }, + { + "source": "windows_event_security", + "event_id": 4663, + "variant": "object_access", + "field": "ResourceAttributes", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ResourceAttributes" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:object_access:ResourceAttributes" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:EventID" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:Computer" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:Channel" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:Level" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "ObjectType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:ObjectType" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "IpAddress", + "type": "ip_address", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "IpPort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "ShareName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ShareName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:ShareName" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "ShareLocalPath", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ShareLocalPath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:ShareLocalPath" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "AccessMask", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessMask" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:AccessMask" + }, + { + "source": "windows_event_security", + "event_id": 5140, + "variant": "network_share_access", + "field": "AccessList", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access:AccessList" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:EventID" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:Computer" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:Channel" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:Level" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "ObjectType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ObjectType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:ObjectType" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "IpAddress", + "type": "ip_address", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp", + "IpAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:IpAddress" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "IpPort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort", + "IpPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:IpPort" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "ShareName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ShareName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:ShareName" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "ShareLocalPath", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ShareLocalPath" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:ShareLocalPath" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "RelativeTargetName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "RelativeTargetName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:RelativeTargetName" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "AccessMask", + "type": "hex_string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessMask" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:AccessMask" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "AccessList", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessList" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:AccessList" + }, + { + "source": "windows_event_security", + "event_id": 5145, + "variant": "network_share_access_check", + "field": "AccessReason", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "AccessReason" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:network_share_access_check:AccessReason" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:Level" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "TaskName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:TaskName" + }, + { + "source": "windows_event_security", + "event_id": 4699, + "variant": "scheduled_task_deleted", + "field": "TaskContent", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskContent" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_deleted:TaskContent" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:Level" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "TaskName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:TaskName" + }, + { + "source": "windows_event_security", + "event_id": 4700, + "variant": "scheduled_task_enabled", + "field": "TaskContent", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskContent" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_enabled:TaskContent" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:EventID" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:TimeCreated" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:Computer" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:Channel" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:Level" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:EventRecordID" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:ExecutionProcessID" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:ExecutionThreadID" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "SubjectUserSid", + "type": "sid", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Security ID", + "SubjectUserSid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][identifier]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][identifier]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:SubjectUserSid" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "SubjectUserName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Name", + "SubjectUserName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][user][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][user][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:SubjectUserName" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "SubjectDomainName", + "type": "string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Account Domain", + "SubjectDomainName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[user][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[user][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:SubjectDomainName" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "SubjectLogonId", + "type": "hex_string", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "Logon ID", + "Canonical[SubjectLogonId]" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonID]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonID]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:SubjectLogonId" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "TaskName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:TaskName" + }, + { + "source": "windows_event_security", + "event_id": 4701, + "variant": "scheduled_task_disabled", + "field": "TaskContent", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TaskContent" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_security:scheduled_task_disabled:TaskContent" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "FileVersion", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "FileVersion" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pe][file_version]", + "[winlog][event_data][Version]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pe][file_version]", + "[winlog][event_data][Version]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:FileVersion" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Description", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Description" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Description]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Description]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Description" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Product", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Product" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Product]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Product]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Product" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Company", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Company" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Company]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Company]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Company" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "OriginalFileName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "OriginalFileName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pe][original_file_name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pe][original_file_name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:OriginalFileName" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "CommandLine", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "CommandLine" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][command_line]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][command_line]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:CommandLine" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "CurrentDirectory", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CurrentDirectory" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][working_directory]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][working_directory]" + ] + }, + "disposition": "raw preserved; both upstream revisions normalize backslashes before backslash-dependent extraction, so destination remains absent", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:CurrentDirectory", + "extraction_limitation": "6010-snare.conf gsub precedes CurrentDirectory/WINPATH patterns; actual Docker fixtures confirm absence without interference" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "LogonGuid", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonGuid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonGuid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:LogonGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "LogonId", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "LogonId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][LogonId]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][LogonId]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:LogonId" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "TerminalSessionId", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "TerminalSessionId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][TerminalSessionId]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][TerminalSessionId]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:TerminalSessionId" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "IntegrityLevel", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "IntegrityLevel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][IntegrityLevel]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][IntegrityLevel]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:IntegrityLevel" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "Hashes", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Hashes" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][Hashes]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][Hashes]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:Hashes" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ParentProcessGuid", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ParentProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]", + "[process][parent][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]", + "[process][parent][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ParentProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ParentProcessId", + "type": "integer", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ParentProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][parent][pid]", + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][parent][pid]", + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ParentProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ParentImage", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ParentImage" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]", + "[process][parent][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]", + "[process][parent][executable]" + ] + }, + "disposition": "raw preserved; both upstream revisions normalize backslashes before backslash-dependent extraction, so destination remains absent", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ParentImage", + "extraction_limitation": "6010-snare.conf gsub precedes CurrentDirectory/WINPATH patterns; actual Docker fixtures confirm absence without interference" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ParentCommandLine", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ParentCommandLine" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][command_line]", + "[process][parent][command_line]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][command_line]", + "[process][parent][command_line]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ParentCommandLine" + }, + { + "source": "windows_event_sysmon", + "event_id": 1, + "variant": "sysmon_process_create", + "field": "ParentUser", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "ParentUser" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]", + "[winlog][event_data][ParentUser]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]", + "[winlog][event_data][ParentUser]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_create:ParentUser" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 5, + "variant": "sysmon_process_terminate", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_terminate:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "SourceProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]", + "[process][source][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]", + "[process][source][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:SourceProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "SourceProcessId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[process][source][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[process][source][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:SourceProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "SourceImage", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceImage" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]", + "[winlog][event_data][SourceImage]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]", + "[winlog][event_data][SourceImage]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:SourceImage" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "TargetProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]", + "[winlog][event_data][TargetProcessGuid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]", + "[winlog][event_data][TargetProcessGuid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:TargetProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "TargetProcessId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][event_data][TargetProcessId]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][event_data][TargetProcessId]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:TargetProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "TargetImage", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetImage" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]", + "[winlog][event_data][TargetImage]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]", + "[winlog][event_data][TargetImage]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:TargetImage" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "NewThreadId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "NewThreadId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:NewThreadId" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "StartAddress", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "StartAddress" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][StartAddress]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][StartAddress]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:StartAddress" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "StartModule", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "StartModule" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][StartModule]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][StartModule]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:StartModule" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "StartFunction", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "StartFunction" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][StartFunction]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][StartFunction]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:StartFunction" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "SourceUser", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceUser" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]", + "[winlog][event_data][SourceUser]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]", + "[winlog][event_data][SourceUser]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:SourceUser" + }, + { + "source": "windows_event_sysmon", + "event_id": 8, + "variant": "sysmon_create_remote_thread", + "field": "TargetUser", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetUser" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]", + "[winlog][event_data][TargetUserName]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]", + "[winlog][event_data][TargetUserName]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_create_remote_thread:TargetUser" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "SourceProcessGUID", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceProcessGUID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:SourceProcessGUID" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "SourceProcessId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[process][source][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[process][source][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:SourceProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "SourceThreadId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceThreadId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:SourceThreadId" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "SourceImage", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceImage" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]", + "[winlog][event_data][SourceImage]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]", + "[winlog][event_data][SourceImage]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:SourceImage" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "TargetProcessGUID", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetProcessGUID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:TargetProcessGUID" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "TargetProcessId", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]", + "[winlog][event_data][TargetProcessId]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]", + "[winlog][event_data][TargetProcessId]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:TargetProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "TargetImage", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetImage" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]", + "[winlog][event_data][TargetImage]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]", + "[winlog][event_data][TargetImage]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:TargetImage" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "GrantedAccess", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "GrantedAccess" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:GrantedAccess" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "CallTrace", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "CallTrace" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:CallTrace" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "SourceUser", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceUser" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]", + "[winlog][event_data][SourceUser]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]", + "[winlog][event_data][SourceUser]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:SourceUser" + }, + { + "source": "windows_event_sysmon", + "event_id": 10, + "variant": "sysmon_process_access", + "field": "TargetUser", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetUser" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]", + "[winlog][event_data][TargetUserName]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]", + "[winlog][event_data][TargetUserName]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_process_access:TargetUser" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "Protocol", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Protocol" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[network][transport]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[network][transport]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:Protocol" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "Initiated", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Initiated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][Initiated]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][Initiated]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:Initiated" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "SourceIsIpv6", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIsIpv6" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:SourceIsIpv6" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "SourceIp", + "type": "ip_address", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceIp" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:SourceIp" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "SourceHostname", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourceHostname" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:SourceHostname" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "SourcePort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[source][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[source][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:SourcePort" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "SourcePortName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "SourcePortName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:SourcePortName" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "DestinationIsIpv6", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "DestinationIsIpv6" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:DestinationIsIpv6" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "DestinationIp", + "type": "ip_address", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "DestinationIp" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[destination][ip]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[destination][ip]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:DestinationIp" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "DestinationHostname", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "DestinationHostname" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[destination][domain]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[destination][domain]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:DestinationHostname" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "DestinationPort", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "DestinationPort" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[destination][port]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[destination][port]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:DestinationPort" + }, + { + "source": "windows_event_sysmon", + "event_id": 3, + "variant": "sysmon_network_connect", + "field": "DestinationPortName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "DestinationPortName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_network_connect:DestinationPortName" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "ImageLoaded", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ImageLoaded" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:ImageLoaded" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "FileVersion", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "FileVersion" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pe][file_version]", + "[winlog][event_data][Version]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pe][file_version]", + "[winlog][event_data][Version]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:FileVersion" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Description", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Description" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Description]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Description]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Description" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Product", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Product" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Product]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Product]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Product" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Company", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Company" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Company]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Company]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Company" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "OriginalFileName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "OriginalFileName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pe][original_file_name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pe][original_file_name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:OriginalFileName" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Hashes", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Hashes" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][Hashes]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][Hashes]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Hashes" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Signed", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Signed" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Signed]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Signed]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Signed" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "Signature", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "Signature" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Signature]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Signature]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:Signature" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "SignatureStatus", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "SignatureStatus" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][SignatureStatus]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][SignatureStatus]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:SignatureStatus" + }, + { + "source": "windows_event_sysmon", + "event_id": 7, + "variant": "sysmon_image_loaded", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_image_loaded:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "TargetFilename", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetFilename" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][TargetFilename]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][TargetFilename]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:TargetFilename" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "CreationUtcTime", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "CreationUtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]", + "[winlog][event_data][CreationUtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]", + "[winlog][event_data][CreationUtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:CreationUtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 11, + "variant": "sysmon_file_create", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_file_create:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "EventType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][EventType]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][EventType]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:EventType" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "TargetObject", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetObject" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][TargetObject]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][TargetObject]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:TargetObject" + }, + { + "source": "windows_event_sysmon", + "event_id": 12, + "variant": "sysmon_registry_create_delete", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_create_delete:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "EventType", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventType" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][EventType]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][EventType]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:EventType" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "TargetObject", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TargetObject" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][TargetObject]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][TargetObject]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:TargetObject" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "Details", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Details" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][event_data][Detail]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][event_data][Detail]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:Details" + }, + { + "source": "windows_event_sysmon", + "event_id": 13, + "variant": "sysmon_registry_set_value", + "field": "User", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_registry_set_value:User" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "EventID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:EventID" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "TimeCreated", + "type": "timestamp", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "TimeCreated" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:TimeCreated" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "Computer", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Computer" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:Computer" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "Channel", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Channel" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:Channel" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "Level", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Level" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:Level" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "EventRecordID", + "type": "integer", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "EventRecordID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "envelope; canonical precision/record ID additionally retained where applicable", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:EventRecordID" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "ExecutionProcessID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "Process ID", + "ExecutionProcessID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[winlog][process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[winlog][process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:ExecutionProcessID" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "ExecutionThreadID", + "type": "integer", + "required": true, + "previous": "omitted system metadata", + "emitted_labels": [ + "ExecutionThreadID" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:ExecutionThreadID" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "RuleName", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "RuleName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[rule][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[rule][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:RuleName" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "UtcTime", + "type": "string", + "required": true, + "previous": "overwritten by system timestamp", + "emitted_labels": [ + "UtcTime" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][UtcTime]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][UtcTime]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:UtcTime" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "ProcessGuid", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "ProcessGuid" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][entity_id]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][entity_id]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:ProcessGuid" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "ProcessId", + "type": "integer", + "required": true, + "previous": "ambiguous or conflated label", + "emitted_labels": [ + "ProcessId" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][pid]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][pid]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:ProcessId" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "QueryName", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "QueryName" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[dns][question][name]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[dns][question][name]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:QueryName" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "QueryStatus", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "QueryStatus" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [] + }, + "disposition": "canonical value retained; no matching upstream label extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:QueryStatus" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "QueryResults", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "QueryResults" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][QueryResults]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][QueryResults]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:QueryResults" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "Image", + "type": "string", + "required": true, + "previous": "native field or envelope", + "emitted_labels": [ + "Image" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[process][executable]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[process][executable]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:Image" + }, + { + "source": "windows_event_sysmon", + "event_id": 22, + "variant": "sysmon_dns_query", + "field": "User", + "type": "string", + "required": false, + "previous": "native field or envelope", + "emitted_labels": [ + "User" + ], + "upstream_destinations": { + "517af9445574cc084cd5f4b80539fc244dab82b0": [ + "[@metadata][User]" + ], + "a85fe99b9dd296faeb39edb7b9eff0bbb87fdd4b": [ + "[@metadata][User]" + ] + }, + "disposition": "canonical value retained; declared downstream extraction", + "witness": "tests/fixtures/record_validation/snare_full_variants.json#windows_event_sysmon:sysmon_dns_query:User" + } + ], + "limitations": [ + "Pattern suffix mappings include upstream unanchored matches; runtime regression assertions verify owners and intended values. All declared optional field slots have committed synthetic witnesses; witnesses do not create generator defaults.", + "Canonical strings retain the existing Snare whitespace and double-pipe sanitization contract.", + "Zero-valued ports remain raw facts; upstream POSINT patterns do not extract zero.", + "Historical records retain ordered unscoped fields; unavailable checks are reported, not reconstructed.", + "Existing optional-enrichment tag _grokparsefail_6010-01 remains classified by the established tag policy; no new tag exemptions were added.", + "Both frozen revisions normalize backslashes before backslash-dependent ParentImage and CurrentDirectory patterns; fields are raw-only despite declared upstream patterns.", + "RuleName is split into an array by upstream; bare unqualified names do not satisfy WINDOMAINUSER for ParentUser/SourceUser/TargetUser." + ] +} diff --git a/docs/worklog/2026-09-15-snare-generation-evidence.json b/docs/worklog/2026-09-15-snare-generation-evidence.json new file mode 100644 index 000000000..4945767ac --- /dev/null +++ b/docs/worklog/2026-09-15-snare-generation-evidence.json @@ -0,0 +1,952 @@ +{ + "pre_snare_commit": "2c899b06", + "baseline_root": "/private/tmp/eforge-gap-sof-elk-candidate", + "candidate_roots": [ + "/private/tmp/eforge-snare-complete/test_iteration_fresh_process_b0/first", + "/private/tmp/eforge-snare-complete/test_iteration_fresh_process_b0/second" + ], + "baseline_files": 142, + "candidate_files": 142, + "fresh_process_bytes_equal": true, + "manifest_hashes_verified": true, + "changed_files": [ + "RESOLVED_SCENARIO.yaml", + "data/DC-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/DC-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/DC-02.meridianhcs.local/2024/windows_event_security_snare.log", + "data/DC-02.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/FILE-SRV-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/FILE-SRV-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/MAIL-FIN-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/MAIL-FIN-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/WS-AJOHNSON-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/WS-AJOHNSON-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/WS-DRAMIREZ-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/WS-DRAMIREZ-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/WS-EBROOKS-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/WS-EBROOKS-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/WS-MCHEN-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/WS-MCHEN-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/WS-PPATEL-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/WS-PPATEL-01.meridianhcs.local/2024/windows_event_sysmon_snare.log", + "data/WS-SMARTINEZ-01.meridianhcs.local/2024/windows_event_security_snare.log", + "data/WS-SMARTINEZ-01.meridianhcs.local/2024/windows_event_sysmon_snare.log" + ], + "unchanged_files": 121, + "hashes": { + "RESOLVED_SCENARIO.yaml": { + "before": "811147ecedf978c2334c110fd3e98e9dcea21c9a866106b8fb52ed892c56aeb0", + "after": "c48421d0155199b6e608dda65e127d1244ae7c98f6e86215ea39e8aeeba94f2e" + }, + "data/DC-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "f05c7e12d513617a4011a47dac5793ec16c888e7ec692238039d361eef2e8594", + "after": "cbe781f5cf8a402de3a68019173654f15151d94981438f3d0dc624e34ab3db92" + }, + "data/DC-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "f18d6452f80b44b9371985451ec765806ae02fc7afb72e612663b78e9646a689", + "after": "d4dcc5d7da345f10c70eb816831fe93479c87298499e5d35fe9afbe2ce7acad7" + }, + "data/DC-02.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "44ecc608434196a25268d55dc519f9584350542bf9ce37e6b72d731794675194", + "after": "082c5fe4786ac0084e548675ecb109179ff5f88ac8326d9a0e6c710fc515e8aa" + }, + "data/DC-02.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "6c08e6fc862710901fad5adf5bd822b830d096404ff14cba617e277654c5bbcb", + "after": "36d2b7b2c60e313e523a0b6014bea8432c9e01e60dd8b67b9564d6a7cdc530db" + }, + "data/FILE-SRV-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "53faaa37cb38dc8ed953737e076e652ce185dcaee9ff5c08b35e2f38f64d502b", + "after": "6f4894d0d8320d1ada88f7824d31eb649ee63b6341c5a407ba5a0c6b7306dfb2" + }, + "data/FILE-SRV-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "c936c74efc84ccf62fb0d27b51c85f99ef984452176192e5828a81437942b9e8", + "after": "0bc4f1fbd2add2a6c13b1f14be3d64c7542a78816650436a8bfac4e6a2526ed0" + }, + "data/MAIL-FIN-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "524488bfcf21e85e465a4a2bce701ecd3767ddb8758088c7d8f0143458204e4b", + "after": "71a6f81d377c0e910b9508c5d16dae24b6dccbc226028299f71accb21dc39971" + }, + "data/MAIL-FIN-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "5c6b80fab7747111b84ccb14c32b8c807787dd7dd2515822ba3457d30dca5c47", + "after": "4435367ec7c58e2c5a3f96fa637a8b4e4c42c928b504fa73f9c1045c90115ce9" + }, + "data/WS-AJOHNSON-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "fee56aa5e8da65648beb8c7d1f088b10dae5663011b850365a6d5ff6cb560d39", + "after": "73d0fab1237f908d418062e380be626cacd800c014fe22b3dc3584eb73e0e658" + }, + "data/WS-AJOHNSON-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "45f1fded6b9e53a68e994362aadb6b368e861738b4ac47037103c69347ac624b", + "after": "8d8d568a4123147531055a0ae6f4c3a301100487cd741a150df4e7539d0a9e43" + }, + "data/WS-DRAMIREZ-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "aa3b47d90ab3aec8d5f0ac7b064c97255aa97e75a977daae9340fec0dd9dcdd8", + "after": "fce645310e30290747be6ad8207eebe0900d584289a33da932d2830863da5c52" + }, + "data/WS-DRAMIREZ-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "1d8d768328b6c3ee8cc5d6493c3a3f6f68f04b037ab41ce540465bf332532ea4", + "after": "628c9414d81057677f4d414686cdddd62bcd86fa17a7f3148c9db764e2743056" + }, + "data/WS-EBROOKS-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "b18a609a6787f51d22494bdd20d1424addbfefc27a4b6c35663bd6125f2cb66a", + "after": "a6fbe1bf2b99d1a7b1edca628bc4dee54a7ab631f6a23b6e2f6ef0eabc998946" + }, + "data/WS-EBROOKS-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "b5c15fc4063e353b80303219dd2b75123f19b9e1d8f339c89db88e4d0d1397f0", + "after": "a55c4fa22ce6e80c0ba873f572f822a8f1e7bf1b9985a362c611a2ba2399ef6e" + }, + "data/WS-MCHEN-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "9cb9736b07e7f4ad4558c07220a7140def5883199937f1d93c4f4f36eb5d3a1d", + "after": "e432d59dcf54649811393311c579617c543861ec115f1edd3d8d113aa2605c80" + }, + "data/WS-MCHEN-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "c399e8d0b05254c45eb778af538d950c68dae22b8d903685da63ffff33f89df2", + "after": "21ea645d761c1538075d6a87f8d5c18e066eddc527c02679aac135404ba442a5" + }, + "data/WS-PPATEL-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "e3bf896fa53297c6c2c0e0b3f7b56fc923349a70a2fead28ea95e81d1d1f8fdd", + "after": "1746660c283dcd7282354ddb200c9fd1a7289a616b332b8c3d7e9754ee4b7d56" + }, + "data/WS-PPATEL-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "3fe36cedad8d86eb1cb104b7c363246b05eb3368ed63503a9588402cd8f98fe2", + "after": "bda07dcf6f421291137ea155f531ab9a3b26826a5d19313bb092d20fedc9e5a4" + }, + "data/WS-SMARTINEZ-01.meridianhcs.local/2024/windows_event_security_snare.log": { + "before": "8e3d57599fba2215226a5dc6778d6f714645dde1b336de6c2d1d0bd4856c1385", + "after": "f1dc504b6f5a4354f20db576c85d009d8ccb1d646f5e2510326bdf6bd0fdb6b0" + }, + "data/WS-SMARTINEZ-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": { + "before": "d6fbff5c3b73079028caad07e6bccfd636c633475875c6ab96301a2b3b55481f", + "after": "6f8e0802b5fba3b9a5ae1bdc373b1cc45ae1d22f9c50d762c7f72f19d8bebb11" + } + }, + "variant_differences": { + "windows_event_security:5156": { + "records": 12026, + "changed_records": 12026, + "added_labels": [ + "DestAddress", + "DestinationPort", + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceAddress", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4769": { + "records": 2103, + "changed_records": 2103, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "Status", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Exit_Status", + "_host_type" + ] + }, + "windows_event_security:4689": { + "records": 826, + "changed_records": 826, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "Status", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Process_Name", + "_host_type" + ] + }, + "windows_event_security:4624": { + "records": 810, + "changed_records": 810, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetLogonId", + "TargetUserName", + "TargetUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Process_Name", + "_auth_occurrence_id", + "_host_type" + ] + }, + "windows_event_security:4672": { + "records": 415, + "changed_records": 415, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_auth_occurrence_id", + "_host_type" + ] + }, + "windows_event_security:4688": { + "records": 957, + "changed_records": 957, + "added_labels": [ + "Creator_Process_ID", + "Creator_Process_Name", + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "NewProcessId", + "NewProcessName", + "New_Process_ID", + "New_Process_Name", + "ProcessId", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetLogonId", + "TargetUserName", + "TargetUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Process_ID", + "Process_Name", + "_host_type" + ] + }, + "windows_event_security:5140": { + "records": 92, + "changed_records": 92, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4634": { + "records": 392, + "changed_records": 392, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TargetDomainName", + "TargetLogonId", + "TargetUserName", + "TargetUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4768": { + "records": 798, + "changed_records": 798, + "added_labels": [ + "CertIssuerName", + "CertSerialNumber", + "CertThumbprint", + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "Status", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Exit_Status", + "_host_type" + ] + }, + "windows_event_security:4776": { + "records": 59, + "changed_records": 59, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "Status", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Exit_Status", + "_host_type" + ] + }, + "windows_event_security:4648": { + "records": 16, + "changed_records": 16, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Logon_ID", + "Process_Name", + "Security_ID", + "_host_type" + ] + }, + "windows_event_security:4779": { + "records": 21, + "changed_records": 21, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4771": { + "records": 4, + "changed_records": 4, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "Status", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Exit_Status", + "_host_type" + ] + }, + "windows_event_security:4697": { + "records": 3, + "changed_records": 3, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4720": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Logon_ID", + "Security_ID", + "_host_type" + ] + }, + "windows_event_security:4724": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Logon_ID", + "Security_ID", + "_host_type" + ] + }, + "windows_event_security:4738": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Logon_ID", + "Security_ID", + "_host_type" + ] + }, + "windows_event_security:4728": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Logon_ID", + "Security_ID", + "_host_type" + ] + }, + "windows_event_security:4698": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:1102": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4726": { + "records": 1, + "changed_records": 1, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TimeCreated" + ], + "removed_labels": [ + "Logon_ID", + "Security_ID", + "_host_type" + ] + }, + "windows_event_sysmon:3": { + "records": 7567, + "changed_records": 7567, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:5": { + "records": 834, + "changed_records": 834, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:10": { + "records": 725, + "changed_records": 725, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:1": { + "records": 952, + "changed_records": 952, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:22": { + "records": 1134, + "changed_records": 1134, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:7": { + "records": 122, + "changed_records": 122, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:8": { + "records": 12, + "changed_records": 12, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:11": { + "records": 29, + "changed_records": 29, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_sysmon:13": { + "records": 142, + "changed_records": 142, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:5145": { + "records": 55, + "changed_records": 55, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4656": { + "records": 36, + "changed_records": 36, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Process_Name", + "_host_type" + ] + }, + "windows_event_security:4663": { + "records": 31, + "changed_records": 31, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Process_Name", + "_host_type" + ] + }, + "windows_event_security:4658": { + "records": 36, + "changed_records": 36, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Process_Name", + "_host_type" + ] + }, + "windows_event_security:4625": { + "records": 23, + "changed_records": 23, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Image", + "Level", + "ProcessId", + "ProcessName", + "ProjectionEnd", + "ProjectionVersion", + "SourceIp", + "SourcePort", + "Status", + "SubjectDomainName", + "SubjectLogonId", + "SubjectUserName", + "SubjectUserSid", + "TargetDomainName", + "TargetUserName", + "TargetUserSid", + "TimeCreated" + ], + "removed_labels": [ + "Exit_Status", + "Logon_ID", + "Process_Name", + "_host_type" + ] + }, + "windows_event_security:4801": { + "records": 4, + "changed_records": 4, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TargetDomainName", + "TargetLogonId", + "TargetUserName", + "TargetUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + }, + "windows_event_security:4800": { + "records": 4, + "changed_records": 4, + "added_labels": [ + "EventRecordID", + "ExecutionProcessID", + "ExecutionThreadID", + "Level", + "Process_ID", + "ProjectionEnd", + "ProjectionVersion", + "TargetDomainName", + "TargetLogonId", + "TargetUserName", + "TargetUserSid", + "TimeCreated" + ], + "removed_labels": [ + "_host_type" + ] + } + }, + "resolved_difference": "Added package-owned Snare projection YAML and corresponding compiled/effective configuration digests; scenario intent unchanged." +} diff --git a/docs/worklog/2026-09-15-snare-xml-truth-evidence.json b/docs/worklog/2026-09-15-snare-xml-truth-evidence.json new file mode 100644 index 000000000..adf96408c --- /dev/null +++ b/docs/worklog/2026-09-15-snare-xml-truth-evidence.json @@ -0,0 +1,55 @@ +{ + "baseline_root": "/private/tmp/eforge-rv-iteration-baseline", + "candidate_root": "/private/tmp/eforge-snare-complete/test_iteration_fresh_process_b0/first", + "comparison": { + "windows_event_security": { + "original_records": 18718, + "matched": 18718, + "missing": 0, + "field_differences": { + "TimeCreated": 18718, + "TransmittedServices": 2713, + "ImpersonationLevel": 587, + "RestrictedAdminMode": 587, + "TargetLinkedLogonId": 587, + "PrivilegeList": 417, + "LogonGuid": 2103, + "CertIssuerName": 4, + "CertSerialNumber": 4, + "CertThumbprint": 4, + "DisplayName": 2, + "UserPrincipalName": 2, + "HomeDirectory": 2, + "HomePath": 2, + "ScriptPath": 2, + "ProfilePath": 2, + "UserWorkstations": 2, + "AccountExpires": 2, + "AllowedToDelegateTo": 2, + "UserAccountControl": 2, + "UserParameters": 2, + "SidHistory": 2, + "LogonHours": 2, + "TaskContent": 1, + "AccessList": 91, + "RestrictedSidCount": 36 + } + }, + "windows_event_sysmon": { + "original_records": 11517, + "matched": 11517, + "missing": 0, + "field_differences": { + "TimeCreated": 11517, + "RuleName": 11517 + } + } + }, + "dispositions": { + "TimeCreated": "Same instant; XML has seven fractional digits with Z versus parsed ISO precision/offset spelling", + "missing_optional_fields": "XML templates supply defaults/empty placeholders not present in canonical event data; do not invent those facts in Snare", + "PrivilegeList_UserAccountControl_AccessList_TaskContent": "Existing Snare whitespace sanitation", + "RestrictedSidCount": "XML string versus typed Snare integer", + "UtcTime": "9011 old Snare overwrites repaired; no remaining XML/Snare UtcTime differences" + } +} diff --git a/docs/worklog/2026-09-15-validation-gap-evidence.json b/docs/worklog/2026-09-15-validation-gap-evidence.json new file mode 100644 index 000000000..c358cc812 --- /dev/null +++ b/docs/worklog/2026-09-15-validation-gap-evidence.json @@ -0,0 +1,1339 @@ +{ + "baseline": "787fd733", + "fix_commits": [ + "9c89e83d", + "cd6463f7", + "68cd5dd8" + ], + "platform": "macOS arm64 Python 3.12.9", + "package_version": "2.1.0", + "generator_changes": false, + "scenario_sha256": "f397d25ebb47d21ae2232bd3d1022bcedc96eb8d75a58b65fa7db5462c24e9a4", + "cli": { + "entries": { + "a-v1-cwd-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v1-cwd-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "a-v1-cwd-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "a-v1-explicit-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v1-explicit-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "a-v1-explicit-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "a-v1-no_ancestor-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v1-no_ancestor-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "a-v1-no_ancestor-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "a-v1-resolved-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v2-cwd-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v2-cwd-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "a-v2-cwd-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "a-v2-explicit-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v2-explicit-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "a-v2-explicit-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "a-v2-no_ancestor-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-v2-no_ancestor-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "a-v2-no_ancestor-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "a-v2-resolved-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "a-config": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "a-config-explicit": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "a-config-no-ancestor": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "b-v1-cwd-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "b-v1-cwd-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "b-v1-cwd-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "b-v1-explicit-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "b-v1-explicit-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "b-v1-explicit-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "b-v1-no_ancestor-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [ + "" + ] + }, + "b-v1-no_ancestor-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "b-v1-no_ancestor-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "b-v1-resolved-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "b-v2-cwd-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "b-v2-cwd-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "b-v2-cwd-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "b-v2-explicit-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [ + "" + ] + }, + "b-v2-explicit-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "b-v2-explicit-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "b-v2-no_ancestor-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "b-v2-no_ancestor-resolve": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/compiled_sha256" + ] + }, + "b-v2-no_ancestor-compiled": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": "same enumerated package contract differences" + }, + "b-v2-resolved-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [] + }, + "b-config": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "b-config-explicit": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "b-config-no-ancestor": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "a-config-repeat": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "pack-validate": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "pack-build": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "pack-inspect": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "pack-import": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "pack-hydrate": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [] + }, + "legacy-eval-text": { + "exit": 0, + "exit_equal": true, + "comparison": "stdout", + "differences": [ + "" + ] + }, + "legacy-eval-json": { + "exit": 0, + "exit_equal": true, + "comparison": "payload", + "differences": [ + "/acceptance_criteria/0/aspirational", + "/acceptance_criteria/0/threshold", + "/acceptance_criteria/1/aspirational", + "/acceptance_criteria/1/threshold", + "/evaluated_at", + "/pillars/0/sub_scores/0/details", + "/pillars/0/sub_scores/0/sample_findings", + "/pillars/0/sub_scores/1/details", + "/pillars/0/sub_scores/1/sample_findings", + "/pillars/1/sub_scores/0/sample_findings", + "/pillars/1/sub_scores/1/details", + "/pillars/1/sub_scores/1/sample_findings", + "/pillars/1/sub_scores/2/sample_findings", + "/pillars/1/sub_scores/3/sample_findings", + "/pillars/1/sub_scores/4/sample_findings", + "/pillars/1/sub_scores/5/sample_findings", + "/pillars/1/sub_scores/6/sample_findings", + "/pillars/2/sub_scores/0/sample_findings", + "/pillars/2/sub_scores/1/sample_findings", + "/pillars/2/sub_scores/2/sample_findings", + "/pillars/2/sub_scores/3/sample_findings", + "/pillars/2/sub_scores/4/sample_findings", + "/pillars/2/sub_scores/5/sample_findings", + "/pillars/2/sub_scores/6/sample_findings", + "/pillars/2/sub_scores/7/sample_findings", + "/pillars/3/sub_scores/0/sample_findings", + "/pillars/3/sub_scores/1/sample_findings", + "/pillars/3/sub_scores/2/sample_findings", + "/pillars/3/sub_scores/3/sample_findings", + "/pillars/3/sub_scores/4/sample_findings", + "/pillars/3/sub_scores/5/sample_findings" + ] + }, + "installed-locks": { + "exit": null, + "exit_equal": true, + "comparison": "payload", + "differences": [] + } + }, + "compiled_difference_paths": [ + "/digests/compiled_sha256", + "/digests/effective_config_sha256", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/bash_history", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/ecar", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/snort_alert", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/syslog", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/web_access", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/windows_event_security", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/zeek_conn", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/zeek_dns", + "/effective_config/packaged_defaults/evaluation/co_occurrence.yaml/zeek_http", + "/effective_config/packaged_defaults/evaluation/thresholds.yaml/pillars/parseability/sub_scores/format_constraints/aspirational", + "/effective_config/packaged_defaults/evaluation/thresholds.yaml/pillars/parseability/sub_scores/format_constraints/minimum", + "/effective_config/packaged_defaults/evaluation/thresholds.yaml/pillars/parseability/sub_scores/spec_conformance/aspirational", + "/effective_config/packaged_defaults/evaluation/thresholds.yaml/pillars/parseability/sub_scores/spec_conformance/minimum", + "/effective_config/packaged_defaults/formats/bash_history.yaml/validators", + "/effective_config/packaged_defaults/formats/ecar.yaml/fields/17/constraints", + "/effective_config/packaged_defaults/formats/ecar.yaml/validators", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/10/constraints", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/11/constraints", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/12/constraints", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/14/constraints", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/15/constraints", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/7/constraints", + "/effective_config/packaged_defaults/formats/proxy_access.yaml/fields/8/constraints", + "/effective_config/packaged_defaults/formats/snort_alert.yaml/validators", + "/effective_config/packaged_defaults/formats/syslog.yaml/validators", + "/effective_config/packaged_defaults/formats/web_access.yaml/fields/3/constraints/allowed_values", + "/effective_config/packaged_defaults/formats/web_access.yaml/fields/7/constraints", + "/effective_config/packaged_defaults/formats/web_access.yaml/validators", + "/effective_config/packaged_defaults/formats/windows_event_security.yaml/validators", + "/effective_config/packaged_defaults/formats/windows_event_security.yaml/variants", + "/effective_config/packaged_defaults/formats/windows_event_sysmon.yaml/validators", + "/effective_config/packaged_defaults/formats/windows_event_sysmon.yaml/variants/4/fields/11/constraints", + "/effective_config/packaged_defaults/formats/windows_event_sysmon.yaml/variants/4/fields/14/type", + "/effective_config/packaged_defaults/formats/windows_event_sysmon.yaml/variants/4/fields/16/constraints", + "/effective_config/packaged_defaults/formats/windows_event_sysmon.yaml/variants/4/fields/9/type", + "/effective_config/packaged_defaults/formats/zeek_conn.yaml/fields/8/constraints", + "/effective_config/packaged_defaults/formats/zeek_conn.yaml/validators", + "/effective_config/packaged_defaults/formats/zeek_dhcp.yaml/fields/1/item_type", + "/effective_config/packaged_defaults/formats/zeek_dhcp.yaml/fields/10/constraints", + "/effective_config/packaged_defaults/formats/zeek_dhcp.yaml/fields/8/item_type", + "/effective_config/packaged_defaults/formats/zeek_dhcp.yaml/fields/9/constraints", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/13/constraints", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/13/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/15/constraints", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/15/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/16/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/17/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/18/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/19/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/20/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/21/item_type", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/22/item_type", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/23/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/7/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/8/constraints", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/fields/9/required", + "/effective_config/packaged_defaults/formats/zeek_dns.yaml/validators", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/10/constraints", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/13/constraints", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/14/constraints", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/15/constraints", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/16/constraints", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/2/item_type", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/3/item_type", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/4/item_type", + "/effective_config/packaged_defaults/formats/zeek_files.yaml/fields/8/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/12/constraints", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/13/constraints", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/16/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/18/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/19/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/20/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/21/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/22/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/fields/23/item_type", + "/effective_config/packaged_defaults/formats/zeek_http.yaml/validators", + "/effective_config/packaged_defaults/formats/zeek_ntp.yaml/fields/18/constraints", + "/effective_config/packaged_defaults/formats/zeek_ocsp.yaml/validators", + "/effective_config/packaged_defaults/formats/zeek_pe.yaml/fields/16/item_type", + "/effective_config/packaged_defaults/formats/zeek_smb_files.yaml/fields/9/constraints", + "/effective_config/packaged_defaults/formats/zeek_smb_files.yaml/validators", + "/effective_config/packaged_defaults/formats/zeek_smtp.yaml/fields/11/item_type", + "/effective_config/packaged_defaults/formats/zeek_smtp.yaml/fields/15/item_type", + "/effective_config/packaged_defaults/formats/zeek_smtp.yaml/fields/16/item_type", + "/effective_config/packaged_defaults/formats/zeek_smtp.yaml/fields/20/item_type", + "/effective_config/packaged_defaults/formats/zeek_smtp.yaml/fields/9/item_type", + "/effective_config/packaged_defaults/formats/zeek_ssl.yaml/fields/12/item_type", + "/effective_config/packaged_defaults/formats/zeek_x509.yaml/fields/14/item_type", + "/effective_config/packaged_defaults/formats/zeek_x509.yaml/validators" + ], + "sequential_project_isolation": true, + "explicit_cwd_equivalence": true, + "no_ancestor_overlay_exclusion": true, + "pack_archive_sha256": "43433bfe3c0769748320318ab41261fd626e1471fa464c5420b0dfe3acf0757d" + }, + "generation": { + "default": { + "files": 141, + "differences": [], + "manifest_hashes_verified": true + }, + "targets": [ + { + "target": "sof-elk", + "serial": true, + "files": 141, + "equal": true, + "hashes": { + "COLLECTION_PROFILE.json": "3988d91fbc2e8ed94f5ea5edfa8ec3e020d9525e2185a5a8f3cdbad3568ab221", + "ARTIFACTS_MANIFEST.json": "7291ceaac01333cf8ff7b283594d4f8d58f2787c513fe09f8ae1d91480a3e8ba", + "STORAGE_MANIFEST.json": "9ed5b8fab6895ac4ed9e9f95f4a6e00684a631b6b8e5518f80baf1237e13f49a", + "GROUND_TRUTH.md": "23a9a6d2a3e03b0422c85715e894a628ec868a913ec1e2cf32fa6d377f060990", + "OUTPUT_TARGET.txt": "7a970cb04428c1aeaa10cc8a99617b652bd625b2c1f1b14d95d9bfbd580d03ea", + "OBSERVATION_MANIFEST.json": "3ca29efb16318975acb35c79aec58a46fb177924de0a4a16d101a9f35f2581d0", + "GROUND_TRUTH.json": "e23649f3e62d136271af0dbb63639c33a59d12e3579846cc00e2a75cb6450b6b", + "artifacts/email/email-000067da1b70.eml": "c5015f17a347ba2fd6673ef9733f10cdbdd57bd40a663bb636d646059e3ae495", + "artifacts/email/vendor-interface-package-msg.eml": "d5e106545bc7f3293b8f33d6e2ba3a41b3476199a0cd3870396ad349b58a1a24", + "artifacts/email/email-0000353a8db2.eml": "8e0c7fa3299b85e7fd7ba1926ebdcf6a411455770246962ecb66127124121eec", + "artifacts/email/email-0000a19a7c67.eml": "45afb9aa8ffea371b6b54a8e1206a7424ce8bcf4a7828e78a029642a2216d57c", + "artifacts/email/email-0000ac7de856.eml": "50dc20f4e0ff5eb5b8d1371e605e041b5bcbee6311d333a3a072f5487257211d", + "artifacts/email/email-0000d86f3a5a.eml": "84ec46d89faa29cb0160f36f3f8dde769b99af22afa7d1cdde7f4c991e368980", + "artifacts/email/email-000062c1e8bc.eml": "25e794da3b85d8a7a74288fcc0fec3e24ec5b334a82ee6f15ccfdf20b9b4ac2a", + "artifacts/email/email-0000c26b996c.eml": "29163f366250394374c394e7d9f2bb265588b30d44c73a149b9a10d3a00f33b5", + "artifacts/email/email-00000d636362.eml": "5907d9ff374dfd7ab93522b4207504eab629a5033d98bfed1411ae649b2467da", + "artifacts/email/email-000017856473.eml": "413fe90452348ed236ef1878354e3fc987a4afe8e81ce45ffcc62b4cd6d4e668", + "artifacts/email/email-0000038a366c.eml": "4904ea5246bbbb0e63a702e45e6e73aa29d7734110daa2d2c0567df73a1ca4f3", + "artifacts/email/email-0000c6e10117.eml": "b8509166998e77d212bd7c0d9b1d340a62c6656405b00a030569453831f98d02", + "artifacts/email/email-00002cc7948e.eml": "f8c3053c2ead1247e66ee6a5443e68de8b3aed865de9bf9cf1721ac3f3386399", + "artifacts/email/email-00006cf8c4e9.eml": "1fa60a446fc111b4cb66257dd1d8e962da02adfa42906f4835eb477d4659a1a1", + "artifacts/email/ehr-release-note-msg.eml": "d70f3ede4146534f746a6611e2f4eab69de19e3c748592e554ee58e42b25b88f", + "artifacts/email/email-0000bd32b806.eml": "3461a56c25611c9e7f03fc9aae7913181d354f7f69cf2d593e4a629be463153f", + "artifacts/email/benefits-confirmation-msg.eml": "5fa3d66ede215ab36dbeecb22d60cd40f2c32b2fb549ad8a45567f5602afc0bd", + "artifacts/email/internal-reset-lure-msg.eml": "80c25648c41069faafd66b9c0778d4df4f01c0ae7b2699effee87c383b1e42e3", + "artifacts/email/finance-forward-to-it-msg.eml": "9f00abdc22dd7344e66073bc4108966bf5ce2165ebc724ba605f0fc776bdfb58", + "artifacts/email/executive-operating-note-msg.eml": "533f85f249fd41fd24c519f9706294d271cbdd99b319554a1efe1e645f45e22d", + "artifacts/email/email-0000ddba5b5b.eml": "2d3e1476df948add47258b0413c3a05a537ac3c859e777bc23fa776e7b56543b", + "artifacts/email/email-000020db74d5.eml": "a94fa73332a03af61fa8fa59bc6c74f3dbd52682e4e0cd232ee4625ca1a4014e", + "artifacts/email/docflow-ai-summary-msg.eml": "cfd9f88f5c78ae881a66551bbc3f4cc09e45cbc91a2c65b1e35465071b2dd68e", + "artifacts/email/email-0000ca36ebc9.eml": "8f15cfecd1127bb3e007fd64c91eb0f460fb48c510dbb0e6314b690c015d0cc6", + "data/MAIL-EDGE-01.meridianhcs.local/ecar.json": "0e5736f8503c0c9d73c981eefa667e27b608203ffcfb4a1f44ab31a208f4d3ae", + "data/DC-02.meridianhcs.local/ecar.json": "606cb6ba6324cc2d85b881bea2e17783fd1be94b471c291ce34b330e33293e14", + "data/WS-PPATEL-01.meridianhcs.local/ecar.json": "a8987267959232fc9b34df149f4a92c737d732c4edb39a5d6447a5ad4f1ea2a3", + "data/DB-PROD-01.meridianhcs.local/ecar.json": "0f1765c77fd9646fad05cf862476a576ee92c74f0a262973a89e880662444ad2", + "data/LT-MRIVERA-02.meridianhcs.local/ecar.json": "986bf770537066962933d3527ef2703557d5a489857d2d2fa7f7f392ec854e29", + "data/WEB-EXT-01.meridianhcs.local/ecar.json": "f574a835779c774952c2e623fc60a44ee956deeecb0e71c30292f21e5561c9b2", + "data/WEB-EXT-01.meridianhcs.local/web_access.log": "34f05fee500a03fe67c087399d4690bf286f10f396fd8ccb583dbd60c745dac7", + "data/DC-01.meridianhcs.local/ecar.json": "c27067fe8ae5444d6631af08d68fbb967cfb0b52e3f098827c5bafb321f9d0ea", + "data/LOG-MON-01.meridianhcs.local/ecar.json": "fd602e7b2fa5fe1a04bf603316c50ad51c21f0cdbe32f1a06ef2d41152419109", + "data/PROXY-01.meridianhcs.local/ecar.json": "2c264286c1cf75626491cfbc47561fe3b15764f503230b7d42943b504d655fb7", + "data/PROXY-01.meridianhcs.local/proxy_access.log": "fec117b161822b4411361ab84e4e856dc2c212c9378a68ae2e70bb944d796361", + "data/WS-DRAMIREZ-01.meridianhcs.local/ecar.json": "a440e983e57f8aaa720a042ff88a545b6b84026202baa954f73a4a25933b922e", + "data/MAIL-FIN-01.meridianhcs.local/ecar.json": "9443412965e8fde309c47cabeab6a427096e83f96e6d7b8292502d4891fd21ce", + "data/WS-AJOHNSON-01.meridianhcs.local/ecar.json": "a14ea1127c81197d41c62b5bfe142540b93476897f610605dff4809095279053", + "data/snort-perimeter/snort_alert.log": "eb490077da9d741f51813f46c758249f9506d83cd6e7a33d113fdd13071b3a1d", + "data/zeek-db/x509.json": "5dc519f13897bdd658306b67bc1901bd60c5224c943edbb6061a8bfb7e971269", + "data/zeek-db/ocsp.json": "829bc08ff8d4281c84d3487bd5a0523a779d14a42e04c856ceddc215cb6adc65", + "data/zeek-db/dns.json": "e18572f99b6734c8235edb2a4b678a5165516cba41a26c9f75c3ac0c0684a68c", + "data/zeek-db/http.json": "e7ebcd1c98571b612b57115f6ad7b9bf09d4f5fa56a12aa7dca40ce21e277408", + "data/zeek-db/ssl.json": "d5cc4fa131f1ac92ff74a86d9da91987738df07c292a4c2c596de5a0eb910e4b", + "data/zeek-db/files.json": "030987bb41d2e5a6c7d859144195e6f28de9004133bc51f2ac5dc86bac36b076", + "data/zeek-db/conn.json": "2e02f8117db2ea194cd11002949b065702c277714cc32b64a880ca4ecf6b3b29", + "data/MAIL-CLIN-01.meridianhcs.local/ecar.json": "ae96cd53a8a3354adb636256f8183456570c5a882441a04fa8afc70db3433498", + "data/zeek-core/dhcp.json": "6e60c5e81b2723df56e646b42de489b2d6cb82cd9df1cbeca4a08d056b29ec2d", + "data/zeek-core/x509.json": "d14bb37fcffe9b8ddf778636d71f5565ce6e5c0bcf4af6ba48c48860c79d104d", + "data/zeek-core/ocsp.json": "6608417c0a9d4e401262bf74c50b07591996a9c627eae123dcad9c242c145760", + "data/zeek-core/dns.json": "a2d0edb92a6e346dd891df73f50d69679c58f422e631ce8a5ed59c58e0f625f0", + "data/zeek-core/http.json": "dbfbb7a7845c8947dd66e756e5804a665e387dc29dc09190b09c93edf5babbd3", + "data/zeek-core/smtp.json": "c0a900bf8b0a2794332c2420453dcf08955fd90e49e3d1988634a680f02dc414", + "data/zeek-core/ssl.json": "92b21544a8945fd0504b221807814c061e437df8cd8defa75ca7caf843cf3c49", + "data/zeek-core/files.json": "edf2fb09a6cf021a50405c6d81c68b8a18a4f5becd3aca3378308dff47320041", + "data/zeek-core/smb_mapping.json": "78d254a7401b078d90708b78b9e76639320bd9172206b0ce3300316c70e4e65f", + "data/zeek-core/conn.json": "1bb4fd5f89256b502f6e5acdbad422b8a7efe37a64dc14aa267f9d247bedfb7d", + "data/zeek-core/smb_files.json": "2a24b0d7495167d8f4c058762ce202276eb799b151daf3faef95879741e6906b", + "data/zeek-core/pe.json": "90a9790ca9c4b82c99a648fc2860138f45979be37b785aa024fa2b74a3cc481e", + "data/snort-core/snort_alert.log": "408c93679d346d9d1191e764b714fe178917398d903bc4626231989c924541b6", + "data/FILE-SRV-01.meridianhcs.local/ecar.json": "3bdfacf2e477f7ede5833cbde43c41bb1a1fafcca6bb0c1a0bd9439acb45b391", + "data/WS-LNGUYEN-01.meridianhcs.local/ecar.json": "007fb4e6cf81c9aca557ff69f04dc25f8cd3316ef7bd7e7f8a68f49906f20f61", + "data/WS-MCHEN-01.meridianhcs.local/ecar.json": "8e5b44c530bec399aad7913a36059dfe2b9857f64e479e76bb9e3847161b6c64", + "data/WS-SMARTINEZ-01.meridianhcs.local/ecar.json": "33546882b858a25014b609340acf0ac978560faed74760a20c2afb7dd98e52a4", + "data/WS-OHADDAD-01.meridianhcs.local/ecar.json": "256bd37a133d9337686bef3bb56646578c39b72ea8e64610e0064f2962f665ca", + "data/zeek-dmz/x509.json": "d832abe01aa4de5b321d1735e748bf523f77fe13347b3d467de9675cc59b478a", + "data/zeek-dmz/ocsp.json": "1e905c0d6be9f6dbf5ba01267cb08cd77e102c457c767826329554c61aeec669", + "data/zeek-dmz/dns.json": "efe88efe70a77e589f0fda071606a4b34f82f242b8ff13ee6f3eb6b097ad4e56", + "data/zeek-dmz/http.json": "0004ee98c65d431722330db7cac4582a1ed110af81f8cacedbd22f79d3d316bd", + "data/zeek-dmz/ssl.json": "926611dc031f81afda0d1720e248b340e7aaf9a5342c03412432365fe2a53f13", + "data/zeek-dmz/files.json": "85eb48715b98cc1747a05f40efab973b2fffb3c67a5824a3dc5aa7b2e0a56e5a", + "data/zeek-dmz/conn.json": "085c68f3b9a51026a78b0959d11fd1adedb6855155b3a1b0bdd4b480012715da", + "data/zeek-dmz/pe.json": "540a9d977ddcfdc6f2c228f5fd7796614195ba0b3cbbe4ecba8c9339c23ff1c2", + "data/FILE-LNX-01.meridianhcs.local/ecar.json": "656cab5f841bfaf06960a4fc249285450d3d8e1c56368efa1d83e3b20940aa83", + "data/WS-EBROOKS-01.meridianhcs.local/ecar.json": "b2f2d915dfd81ac28730994364d62d88734f2b055df5875eef318c0209ee710b", + "data/APP-INT-01.meridianhcs.local/ecar.json": "9c90a6428cbf7a6b82f94362573a1741203f9fb46cde9019812bff2a21ca731d", + "data/MAIL-EDGE-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "5f13e45b2dc1d9f052c7bd280b11b48c972c847bf5048dd59e9e77b04b323612", + "data/MAIL-EDGE-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "d6214a876e325b65b7ee8b83f52b353fcf248917377e207e568a31532d17c3cf", + "data/MAIL-EDGE-01.meridianhcs.local/2024/syslog.log": "01bdfbbfaab7d67330663b6615a87f3ba8d84907c3c2f3749c5f9c004e945994", + "data/DC-02.meridianhcs.local/2024/windows_event_security_snare.log": "44ecc608434196a25268d55dc519f9584350542bf9ce37e6b72d731794675194", + "data/DC-02.meridianhcs.local/2024/windows_event_sysmon_snare.log": "6c08e6fc862710901fad5adf5bd822b830d096404ff14cba617e277654c5bbcb", + "data/WS-PPATEL-01.meridianhcs.local/2024/windows_event_security_snare.log": "e3bf896fa53297c6c2c0e0b3f7b56fc923349a70a2fead28ea95e81d1d1f8fdd", + "data/WS-PPATEL-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "3fe36cedad8d86eb1cb104b7c363246b05eb3368ed63503a9588402cd8f98fe2", + "data/DB-PROD-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "2e5586e5b3ddddaf2c8af52675bb2098738c7b115df97653acdd5284e66cc7cd", + "data/DB-PROD-01.meridianhcs.local/bash_history/root.bash_history": "ae189b0c0a5626ae1613541acf992d1a9d427dda0963ae1073a06f3edc1da7d4", + "data/DB-PROD-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "ee081c06165ea9e5c4ecf4fbf595a0dfea184d116692c349f035ac8b09eb5689", + "data/DB-PROD-01.meridianhcs.local/2024/syslog.log": "f2eb8b3e78c4ce58ea7de1173d535d2d29d5732ef6397b546e02e7d3d8595806", + "data/LT-MRIVERA-02.meridianhcs.local/2024/syslog.log": "27dd64d55c2c0270cee883ab7edbd75709e47973a97669421a0074e0ddbfb616", + "data/WEB-EXT-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "8aa827dd762bca192f91e9d95630ed827ac72cf80188a242b3dc7de4489e8469", + "data/WEB-EXT-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "0699604125c3d35db981d101933b366b25a5bd93ab1aad270905045db8252de5", + "data/WEB-EXT-01.meridianhcs.local/bash_history/root.bash_history": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "data/WEB-EXT-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "debe5f709305172b6b55ec5ea8cf10aba8edc31938b37ef666e510892614b8ab", + "data/WEB-EXT-01.meridianhcs.local/2024/syslog.log": "3a8fe58da57b13ec20c3885a8d6a47728fdb12f04eb0d4ff708530b4fb4376f0", + "data/DC-01.meridianhcs.local/2024/windows_event_security_snare.log": "f05c7e12d513617a4011a47dac5793ec16c888e7ec692238039d361eef2e8594", + "data/DC-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "f18d6452f80b44b9371985451ec765806ae02fc7afb72e612663b78e9646a689", + "data/LOG-MON-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "b44c58e2e9644460ea238eb96ff44842e4a0fe6896c00edddc66b7b7a0657979", + "data/LOG-MON-01.meridianhcs.local/bash_history/priya.patel.bash_history": "cf210da7baf84812e7a4f16770bce63e4195aee5537f8d945025e672a371af65", + "data/LOG-MON-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "e20adf4468cc09dac81afa1213faf58ab88620a905e6aa57643a4ab86e9c6b81", + "data/LOG-MON-01.meridianhcs.local/2024/syslog.log": "89b2b514eacea40ed44292c7e9b967774d87deb54313ab6f62e7853f12a5476f", + "data/PROXY-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "d944c36afc66146ca1b3bb49fe725c813024bc7ba4ff8f0523d7ff31d9fd0142", + "data/PROXY-01.meridianhcs.local/bash_history/priya.patel.bash_history": "911a54a0c477a23da65373be14fdd9396fa43664b75c54804df0a9d8269e82da", + "data/PROXY-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "805e7d2ce92fc270ec8a1d20a5a4c7fb662d22bfd9146e843b81f381510f8af3", + "data/PROXY-01.meridianhcs.local/2024/syslog.log": "fd608da928402932289009d968c4bb17b04a8a1cbf3cb954fd486f72e276987b", + "data/WS-DRAMIREZ-01.meridianhcs.local/2024/windows_event_security_snare.log": "aa3b47d90ab3aec8d5f0ac7b064c97255aa97e75a977daae9340fec0dd9dcdd8", + "data/WS-DRAMIREZ-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "1d8d768328b6c3ee8cc5d6493c3a3f6f68f04b037ab41ce540465bf332532ea4", + "data/MAIL-FIN-01.meridianhcs.local/2024/windows_event_security_snare.log": "524488bfcf21e85e465a4a2bce701ecd3767ddb8758088c7d8f0143458204e4b", + "data/MAIL-FIN-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "5c6b80fab7747111b84ccb14c32b8c807787dd7dd2515822ba3457d30dca5c47", + "data/WS-AJOHNSON-01.meridianhcs.local/2024/windows_event_security_snare.log": "fee56aa5e8da65648beb8c7d1f088b10dae5663011b850365a6d5ff6cb560d39", + "data/WS-AJOHNSON-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "45f1fded6b9e53a68e994362aadb6b368e861738b4ac47037103c69347ac624b", + "data/MAIL-CLIN-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "6d2353e02422416de0c3d8a5c399955f2ecfb0c6d885ae1e0fdd6d1dfb642c60", + "data/MAIL-CLIN-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "03573d93db26675bb1ee064a21197d42542ad1e326a6b814135491992ac08906", + "data/MAIL-CLIN-01.meridianhcs.local/2024/syslog.log": "29cf4cafc4421a18d68bb631ed6a291201c6efceaeed7b06e20cb7aebdd10e4a", + "data/fw-perimeter/2024/cisco_asa.log": "b3af353fb4d44b150f3c82054f511a2b1a7741c61d0819b317c843821fc017b4", + "data/FILE-SRV-01.meridianhcs.local/2024/windows_event_security_snare.log": "53faaa37cb38dc8ed953737e076e652ce185dcaee9ff5c08b35e2f38f64d502b", + "data/FILE-SRV-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "c936c74efc84ccf62fb0d27b51c85f99ef984452176192e5828a81437942b9e8", + "data/WS-LNGUYEN-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "ccce55e03e2546c34be4c7b252be449c360a93b775b4984d081555dec7a758a8", + "data/WS-LNGUYEN-01.meridianhcs.local/2024/syslog.log": "8aaf0245f779214a2c1c7b88f096746e83c2be6c6eb5ffd407a52115cc27b2e0", + "data/WS-MCHEN-01.meridianhcs.local/2024/windows_event_security_snare.log": "9cb9736b07e7f4ad4558c07220a7140def5883199937f1d93c4f4f36eb5d3a1d", + "data/WS-MCHEN-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "c399e8d0b05254c45eb778af538d950c68dae22b8d903685da63ffff33f89df2", + "data/WS-SMARTINEZ-01.meridianhcs.local/2024/windows_event_security_snare.log": "8e3d57599fba2215226a5dc6778d6f714645dde1b336de6c2d1d0bd4856c1385", + "data/WS-SMARTINEZ-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "d6fbff5c3b73079028caad07e6bccfd636c633475875c6ab96301a2b3b55481f", + "data/WS-OHADDAD-01.meridianhcs.local/bash_history/omar.haddad.bash_history": "4b3502b37538e2b25e0b8329303dce02f65707480786f152845e4961ecc3c313", + "data/WS-OHADDAD-01.meridianhcs.local/2024/syslog.log": "5c8b3c02d067e167fc8c1d0cada0a452765a7ac5b14ac0345a28a14468732a65", + "data/FILE-LNX-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "f17b48498d601ac5bc950bd066cd017d1b092d3937b57dca3bb1c647657f9a98", + "data/FILE-LNX-01.meridianhcs.local/bash_history/priya.patel.bash_history": "7598d9a8d5cb7256007be7e433144f5c657f6f63cf88718f9daab59069b76b12", + "data/FILE-LNX-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "9d7518a98448e6fa4adb628b49a011bb9e1627ab3ce50bd1fc39307524e59a1c", + "data/FILE-LNX-01.meridianhcs.local/2024/syslog.log": "e91d85c199f0bc9299d26a87fc1a25de4c62135ef156e8356a27aec122a6200e", + "data/WS-EBROOKS-01.meridianhcs.local/2024/windows_event_security_snare.log": "b18a609a6787f51d22494bdd20d1424addbfefc27a4b6c35663bd6125f2cb66a", + "data/WS-EBROOKS-01.meridianhcs.local/2024/windows_event_sysmon_snare.log": "b5c15fc4063e353b80303219dd2b75123f19b9e1d8f339c89db88e4d0d1397f0", + "data/APP-INT-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "dfe26330c9245b119a35c320f2d7669746297e3395757ac024b9056ebdce0da1", + "data/APP-INT-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "a78af3b127b26410d787923dab8353e047c2f428ab3de82169f856592889688e", + "data/APP-INT-01.meridianhcs.local/bash_history/root.bash_history": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "data/APP-INT-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "b04c155840f7583699401a93770c5a0aa388fb8d819bbe0217739da900d19544", + "data/APP-INT-01.meridianhcs.local/2024/syslog.log": "aaf589023120a3c216872565d6e82f284ccb023d119acb698d9f42baecc844f1" + } + }, + { + "target": "splunk", + "serial": false, + "files": 141, + "equal": true, + "hashes": { + "COLLECTION_PROFILE.json": "0bca0af6d9341fc164e34bd81a5445d18621c2b4b6c244b0b39f2542f34a1f0f", + "ARTIFACTS_MANIFEST.json": "7291ceaac01333cf8ff7b283594d4f8d58f2787c513fe09f8ae1d91480a3e8ba", + "STORAGE_MANIFEST.json": "9ed5b8fab6895ac4ed9e9f95f4a6e00684a631b6b8e5518f80baf1237e13f49a", + "GROUND_TRUTH.md": "23a9a6d2a3e03b0422c85715e894a628ec868a913ec1e2cf32fa6d377f060990", + "OUTPUT_TARGET.txt": "d31a0d2ea7becadb883d33f8189e1cef71c07a907bef52c2437de1348005d004", + "OBSERVATION_MANIFEST.json": "3ca29efb16318975acb35c79aec58a46fb177924de0a4a16d101a9f35f2581d0", + "GROUND_TRUTH.json": "e23649f3e62d136271af0dbb63639c33a59d12e3579846cc00e2a75cb6450b6b", + "artifacts/email/email-000067da1b70.eml": "c5015f17a347ba2fd6673ef9733f10cdbdd57bd40a663bb636d646059e3ae495", + "artifacts/email/vendor-interface-package-msg.eml": "d5e106545bc7f3293b8f33d6e2ba3a41b3476199a0cd3870396ad349b58a1a24", + "artifacts/email/email-0000353a8db2.eml": "8e0c7fa3299b85e7fd7ba1926ebdcf6a411455770246962ecb66127124121eec", + "artifacts/email/email-0000a19a7c67.eml": "45afb9aa8ffea371b6b54a8e1206a7424ce8bcf4a7828e78a029642a2216d57c", + "artifacts/email/email-0000ac7de856.eml": "50dc20f4e0ff5eb5b8d1371e605e041b5bcbee6311d333a3a072f5487257211d", + "artifacts/email/email-0000d86f3a5a.eml": "84ec46d89faa29cb0160f36f3f8dde769b99af22afa7d1cdde7f4c991e368980", + "artifacts/email/email-000062c1e8bc.eml": "25e794da3b85d8a7a74288fcc0fec3e24ec5b334a82ee6f15ccfdf20b9b4ac2a", + "artifacts/email/email-0000c26b996c.eml": "29163f366250394374c394e7d9f2bb265588b30d44c73a149b9a10d3a00f33b5", + "artifacts/email/email-00000d636362.eml": "5907d9ff374dfd7ab93522b4207504eab629a5033d98bfed1411ae649b2467da", + "artifacts/email/email-000017856473.eml": "413fe90452348ed236ef1878354e3fc987a4afe8e81ce45ffcc62b4cd6d4e668", + "artifacts/email/email-0000038a366c.eml": "4904ea5246bbbb0e63a702e45e6e73aa29d7734110daa2d2c0567df73a1ca4f3", + "artifacts/email/email-0000c6e10117.eml": "b8509166998e77d212bd7c0d9b1d340a62c6656405b00a030569453831f98d02", + "artifacts/email/email-00002cc7948e.eml": "f8c3053c2ead1247e66ee6a5443e68de8b3aed865de9bf9cf1721ac3f3386399", + "artifacts/email/email-00006cf8c4e9.eml": "1fa60a446fc111b4cb66257dd1d8e962da02adfa42906f4835eb477d4659a1a1", + "artifacts/email/ehr-release-note-msg.eml": "d70f3ede4146534f746a6611e2f4eab69de19e3c748592e554ee58e42b25b88f", + "artifacts/email/email-0000bd32b806.eml": "3461a56c25611c9e7f03fc9aae7913181d354f7f69cf2d593e4a629be463153f", + "artifacts/email/benefits-confirmation-msg.eml": "5fa3d66ede215ab36dbeecb22d60cd40f2c32b2fb549ad8a45567f5602afc0bd", + "artifacts/email/internal-reset-lure-msg.eml": "80c25648c41069faafd66b9c0778d4df4f01c0ae7b2699effee87c383b1e42e3", + "artifacts/email/finance-forward-to-it-msg.eml": "9f00abdc22dd7344e66073bc4108966bf5ce2165ebc724ba605f0fc776bdfb58", + "artifacts/email/executive-operating-note-msg.eml": "533f85f249fd41fd24c519f9706294d271cbdd99b319554a1efe1e645f45e22d", + "artifacts/email/email-0000ddba5b5b.eml": "2d3e1476df948add47258b0413c3a05a537ac3c859e777bc23fa776e7b56543b", + "artifacts/email/email-000020db74d5.eml": "a94fa73332a03af61fa8fa59bc6c74f3dbd52682e4e0cd232ee4625ca1a4014e", + "artifacts/email/docflow-ai-summary-msg.eml": "cfd9f88f5c78ae881a66551bbc3f4cc09e45cbc91a2c65b1e35465071b2dd68e", + "artifacts/email/email-0000ca36ebc9.eml": "8f15cfecd1127bb3e007fd64c91eb0f460fb48c510dbb0e6314b690c015d0cc6", + "data/MAIL-EDGE-01.meridianhcs.local/ecar.json": "0e5736f8503c0c9d73c981eefa667e27b608203ffcfb4a1f44ab31a208f4d3ae", + "data/MAIL-EDGE-01.meridianhcs.local/syslog.log": "48817ffa142f9bb6728f9dfbd8adfe0081e4caca129d8548b1ec5d070944f98b", + "data/DC-02.meridianhcs.local/ecar.json": "606cb6ba6324cc2d85b881bea2e17783fd1be94b471c291ce34b330e33293e14", + "data/DC-02.meridianhcs.local/windows_event_sysmon.xml": "ca726cdfda0a7bf7ab3fc6ae684f592a070b66734cecb90956195c3351b08073", + "data/DC-02.meridianhcs.local/windows_event_security.xml": "8b687772211ec2a274234ce253e2957ebea980b21da2efddcc61f8f8481a994a", + "data/WS-PPATEL-01.meridianhcs.local/ecar.json": "a8987267959232fc9b34df149f4a92c737d732c4edb39a5d6447a5ad4f1ea2a3", + "data/WS-PPATEL-01.meridianhcs.local/windows_event_sysmon.xml": "62dce1d3bda5a2945b865a3c7b9e8986f993d9366b415800e21dde600e1f9c68", + "data/WS-PPATEL-01.meridianhcs.local/windows_event_security.xml": "aa95c4309c801050634818496aede563d8b5fedf9b61000363fdc0c75e5410bb", + "data/DB-PROD-01.meridianhcs.local/ecar.json": "0f1765c77fd9646fad05cf862476a576ee92c74f0a262973a89e880662444ad2", + "data/DB-PROD-01.meridianhcs.local/syslog.log": "2b7e8baf1771214ccb266ade82ca3df8b77d0a01fc17767f8c0480b60ca13c12", + "data/LT-MRIVERA-02.meridianhcs.local/ecar.json": "986bf770537066962933d3527ef2703557d5a489857d2d2fa7f7f392ec854e29", + "data/LT-MRIVERA-02.meridianhcs.local/syslog.log": "1fb48210cfe5e35a786734fdd0be58194e4fb780c5c871b294b2b15b2a1d567b", + "data/WEB-EXT-01.meridianhcs.local/ecar.json": "f574a835779c774952c2e623fc60a44ee956deeecb0e71c30292f21e5561c9b2", + "data/WEB-EXT-01.meridianhcs.local/syslog.log": "f355dc44ae32c74186a8f585a0615e827c11c990187d501c8d3404744c311847", + "data/WEB-EXT-01.meridianhcs.local/web_access.log": "f388622481771fac6bebe47d01a90072a728ebe384b9039c4d5c2969b45b4aee", + "data/DC-01.meridianhcs.local/ecar.json": "c27067fe8ae5444d6631af08d68fbb967cfb0b52e3f098827c5bafb321f9d0ea", + "data/DC-01.meridianhcs.local/windows_event_sysmon.xml": "29b2c1ee609b2e2247c7d93139bcc37b762da6d6d0c9dfdabfef445428460a4a", + "data/DC-01.meridianhcs.local/windows_event_security.xml": "ad3b7c45ce41555617d6cebe3d296d6c8c8112cfe0fbc66bcb10568d05e458c9", + "data/LOG-MON-01.meridianhcs.local/ecar.json": "fd602e7b2fa5fe1a04bf603316c50ad51c21f0cdbe32f1a06ef2d41152419109", + "data/LOG-MON-01.meridianhcs.local/syslog.log": "a9c138798c3c1b9ea5457b1a7751fe06535b14a8a02537d1bf654ce7b2c813a1", + "data/PROXY-01.meridianhcs.local/ecar.json": "2c264286c1cf75626491cfbc47561fe3b15764f503230b7d42943b504d655fb7", + "data/PROXY-01.meridianhcs.local/syslog.log": "49b481695c673b7d233ea28677233bd0048000791ca1df9f8f7830eb456973ca", + "data/PROXY-01.meridianhcs.local/proxy_access.log": "1560e1a5944aee5f29d2fa3916b4417af36d3645edc3567c38d9d4c034dbd7cd", + "data/WS-DRAMIREZ-01.meridianhcs.local/ecar.json": "a440e983e57f8aaa720a042ff88a545b6b84026202baa954f73a4a25933b922e", + "data/WS-DRAMIREZ-01.meridianhcs.local/windows_event_sysmon.xml": "b530cca3fb43f9c42817f91492c0c53fee372ba1f1137647066f7fa3b6e44b5a", + "data/WS-DRAMIREZ-01.meridianhcs.local/windows_event_security.xml": "410d9da90d08e098a7e307c8d51c69fb2584d837f569e904be3d3ee431765556", + "data/MAIL-FIN-01.meridianhcs.local/ecar.json": "9443412965e8fde309c47cabeab6a427096e83f96e6d7b8292502d4891fd21ce", + "data/MAIL-FIN-01.meridianhcs.local/windows_event_sysmon.xml": "3b2ad674ee45ed76899043fb8fc6915964e50a2492ebe2d0bdfb62f33a769025", + "data/MAIL-FIN-01.meridianhcs.local/windows_event_security.xml": "0765fead4350a05b094444b92f0f21bfd3687aec38b5fa55ba3672dc9f268ca8", + "data/WS-AJOHNSON-01.meridianhcs.local/ecar.json": "a14ea1127c81197d41c62b5bfe142540b93476897f610605dff4809095279053", + "data/WS-AJOHNSON-01.meridianhcs.local/windows_event_sysmon.xml": "71c1851abc48b2ac8b63f93e7b445f9c161c6bbf37e1045f215fa3e44f341aae", + "data/WS-AJOHNSON-01.meridianhcs.local/windows_event_security.xml": "eaf1359aaad41a97e29a0a78082a9e00d6b689a8b7b6f64c69568365073a0e7a", + "data/snort-perimeter/snort_alert.log": "eb490077da9d741f51813f46c758249f9506d83cd6e7a33d113fdd13071b3a1d", + "data/zeek-db/x509.json": "5dc519f13897bdd658306b67bc1901bd60c5224c943edbb6061a8bfb7e971269", + "data/zeek-db/ocsp.json": "829bc08ff8d4281c84d3487bd5a0523a779d14a42e04c856ceddc215cb6adc65", + "data/zeek-db/dns.json": "e18572f99b6734c8235edb2a4b678a5165516cba41a26c9f75c3ac0c0684a68c", + "data/zeek-db/http.json": "e7ebcd1c98571b612b57115f6ad7b9bf09d4f5fa56a12aa7dca40ce21e277408", + "data/zeek-db/ssl.json": "d5cc4fa131f1ac92ff74a86d9da91987738df07c292a4c2c596de5a0eb910e4b", + "data/zeek-db/files.json": "030987bb41d2e5a6c7d859144195e6f28de9004133bc51f2ac5dc86bac36b076", + "data/zeek-db/conn.json": "2e02f8117db2ea194cd11002949b065702c277714cc32b64a880ca4ecf6b3b29", + "data/MAIL-CLIN-01.meridianhcs.local/ecar.json": "ae96cd53a8a3354adb636256f8183456570c5a882441a04fa8afc70db3433498", + "data/MAIL-CLIN-01.meridianhcs.local/syslog.log": "0bb6ba257e499dc29215d1e03c45d8892ea581670c72a0afad211e50c72b56de", + "data/fw-perimeter/cisco_asa.log": "b3af353fb4d44b150f3c82054f511a2b1a7741c61d0819b317c843821fc017b4", + "data/zeek-core/dhcp.json": "6e60c5e81b2723df56e646b42de489b2d6cb82cd9df1cbeca4a08d056b29ec2d", + "data/zeek-core/x509.json": "d14bb37fcffe9b8ddf778636d71f5565ce6e5c0bcf4af6ba48c48860c79d104d", + "data/zeek-core/ocsp.json": "6608417c0a9d4e401262bf74c50b07591996a9c627eae123dcad9c242c145760", + "data/zeek-core/dns.json": "a2d0edb92a6e346dd891df73f50d69679c58f422e631ce8a5ed59c58e0f625f0", + "data/zeek-core/http.json": "dbfbb7a7845c8947dd66e756e5804a665e387dc29dc09190b09c93edf5babbd3", + "data/zeek-core/smtp.json": "c0a900bf8b0a2794332c2420453dcf08955fd90e49e3d1988634a680f02dc414", + "data/zeek-core/ssl.json": "92b21544a8945fd0504b221807814c061e437df8cd8defa75ca7caf843cf3c49", + "data/zeek-core/files.json": "edf2fb09a6cf021a50405c6d81c68b8a18a4f5becd3aca3378308dff47320041", + "data/zeek-core/smb_mapping.json": "78d254a7401b078d90708b78b9e76639320bd9172206b0ce3300316c70e4e65f", + "data/zeek-core/conn.json": "1bb4fd5f89256b502f6e5acdbad422b8a7efe37a64dc14aa267f9d247bedfb7d", + "data/zeek-core/smb_files.json": "2a24b0d7495167d8f4c058762ce202276eb799b151daf3faef95879741e6906b", + "data/zeek-core/pe.json": "90a9790ca9c4b82c99a648fc2860138f45979be37b785aa024fa2b74a3cc481e", + "data/snort-core/snort_alert.log": "408c93679d346d9d1191e764b714fe178917398d903bc4626231989c924541b6", + "data/FILE-SRV-01.meridianhcs.local/ecar.json": "3bdfacf2e477f7ede5833cbde43c41bb1a1fafcca6bb0c1a0bd9439acb45b391", + "data/FILE-SRV-01.meridianhcs.local/windows_event_sysmon.xml": "e46fbf6d00c770d70a99359c526f12d3ca505dd4b211104284d7288fd9a4d3fa", + "data/FILE-SRV-01.meridianhcs.local/windows_event_security.xml": "8674f1af3499bde8e4ee06960c1440c3fb389f4e75f616aaf7a7f46f8e481578", + "data/WS-LNGUYEN-01.meridianhcs.local/ecar.json": "007fb4e6cf81c9aca557ff69f04dc25f8cd3316ef7bd7e7f8a68f49906f20f61", + "data/WS-LNGUYEN-01.meridianhcs.local/syslog.log": "cc73ff5812b041473cfff1262d31a07f7d2650ca9f08baadb11ae212c7e229c5", + "data/WS-MCHEN-01.meridianhcs.local/ecar.json": "8e5b44c530bec399aad7913a36059dfe2b9857f64e479e76bb9e3847161b6c64", + "data/WS-MCHEN-01.meridianhcs.local/windows_event_sysmon.xml": "baa52a4c4815dbc5dd84c9c32840d8aca1e5fd45302b302708b8287350ae9ce5", + "data/WS-MCHEN-01.meridianhcs.local/windows_event_security.xml": "d2157dae680219a31ec77618ddd1ad90fe83c30f5eb8d39ed49a1ed8cd4f766f", + "data/WS-SMARTINEZ-01.meridianhcs.local/ecar.json": "33546882b858a25014b609340acf0ac978560faed74760a20c2afb7dd98e52a4", + "data/WS-SMARTINEZ-01.meridianhcs.local/windows_event_sysmon.xml": "43d90dd2da1c3a3f31a94ceb4fbf95f555bd29199e1a88d10916f3098e6eb99d", + "data/WS-SMARTINEZ-01.meridianhcs.local/windows_event_security.xml": "fc3c4e1af2638020249c631a43b5937e74299804f9de5396d4001e326672a59d", + "data/WS-OHADDAD-01.meridianhcs.local/ecar.json": "256bd37a133d9337686bef3bb56646578c39b72ea8e64610e0064f2962f665ca", + "data/WS-OHADDAD-01.meridianhcs.local/syslog.log": "4a7b8ac069b3ce13d5653d9da6e3512b505ab94fafd5311caf055ac6f78e54b2", + "data/zeek-dmz/x509.json": "d832abe01aa4de5b321d1735e748bf523f77fe13347b3d467de9675cc59b478a", + "data/zeek-dmz/ocsp.json": "1e905c0d6be9f6dbf5ba01267cb08cd77e102c457c767826329554c61aeec669", + "data/zeek-dmz/dns.json": "efe88efe70a77e589f0fda071606a4b34f82f242b8ff13ee6f3eb6b097ad4e56", + "data/zeek-dmz/http.json": "0004ee98c65d431722330db7cac4582a1ed110af81f8cacedbd22f79d3d316bd", + "data/zeek-dmz/ssl.json": "926611dc031f81afda0d1720e248b340e7aaf9a5342c03412432365fe2a53f13", + "data/zeek-dmz/files.json": "85eb48715b98cc1747a05f40efab973b2fffb3c67a5824a3dc5aa7b2e0a56e5a", + "data/zeek-dmz/conn.json": "085c68f3b9a51026a78b0959d11fd1adedb6855155b3a1b0bdd4b480012715da", + "data/zeek-dmz/pe.json": "540a9d977ddcfdc6f2c228f5fd7796614195ba0b3cbbe4ecba8c9339c23ff1c2", + "data/FILE-LNX-01.meridianhcs.local/ecar.json": "656cab5f841bfaf06960a4fc249285450d3d8e1c56368efa1d83e3b20940aa83", + "data/FILE-LNX-01.meridianhcs.local/syslog.log": "0a6ba83048d12b696338d37524d5a886b0c47924c251ae9d4c0be58b94ab0532", + "data/WS-EBROOKS-01.meridianhcs.local/ecar.json": "b2f2d915dfd81ac28730994364d62d88734f2b055df5875eef318c0209ee710b", + "data/WS-EBROOKS-01.meridianhcs.local/windows_event_sysmon.xml": "0d8efee1b5381b64e6e3db04ddbc300660dd267860fa8c610e042a02a385c5b8", + "data/WS-EBROOKS-01.meridianhcs.local/windows_event_security.xml": "0916d6d85255898762cd5b751a653c4b903df1d20b37f62ce0ed07e3f1fcf00b", + "data/APP-INT-01.meridianhcs.local/ecar.json": "9c90a6428cbf7a6b82f94362573a1741203f9fb46cde9019812bff2a21ca731d", + "data/APP-INT-01.meridianhcs.local/syslog.log": "45b8ac973c5c2ade7ddb0e7b941ebe5edf9ea664215dc855c017f292a08997d7", + "data/MAIL-EDGE-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "5f13e45b2dc1d9f052c7bd280b11b48c972c847bf5048dd59e9e77b04b323612", + "data/MAIL-EDGE-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "d6214a876e325b65b7ee8b83f52b353fcf248917377e207e568a31532d17c3cf", + "data/DB-PROD-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "2e5586e5b3ddddaf2c8af52675bb2098738c7b115df97653acdd5284e66cc7cd", + "data/DB-PROD-01.meridianhcs.local/bash_history/root.bash_history": "ae189b0c0a5626ae1613541acf992d1a9d427dda0963ae1073a06f3edc1da7d4", + "data/DB-PROD-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "ee081c06165ea9e5c4ecf4fbf595a0dfea184d116692c349f035ac8b09eb5689", + "data/WEB-EXT-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "8aa827dd762bca192f91e9d95630ed827ac72cf80188a242b3dc7de4489e8469", + "data/WEB-EXT-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "0699604125c3d35db981d101933b366b25a5bd93ab1aad270905045db8252de5", + "data/WEB-EXT-01.meridianhcs.local/bash_history/root.bash_history": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "data/WEB-EXT-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "debe5f709305172b6b55ec5ea8cf10aba8edc31938b37ef666e510892614b8ab", + "data/LOG-MON-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "b44c58e2e9644460ea238eb96ff44842e4a0fe6896c00edddc66b7b7a0657979", + "data/LOG-MON-01.meridianhcs.local/bash_history/priya.patel.bash_history": "cf210da7baf84812e7a4f16770bce63e4195aee5537f8d945025e672a371af65", + "data/LOG-MON-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "e20adf4468cc09dac81afa1213faf58ab88620a905e6aa57643a4ab86e9c6b81", + "data/PROXY-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "d944c36afc66146ca1b3bb49fe725c813024bc7ba4ff8f0523d7ff31d9fd0142", + "data/PROXY-01.meridianhcs.local/bash_history/priya.patel.bash_history": "911a54a0c477a23da65373be14fdd9396fa43664b75c54804df0a9d8269e82da", + "data/PROXY-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "805e7d2ce92fc270ec8a1d20a5a4c7fb662d22bfd9146e843b81f381510f8af3", + "data/MAIL-CLIN-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "6d2353e02422416de0c3d8a5c399955f2ecfb0c6d885ae1e0fdd6d1dfb642c60", + "data/MAIL-CLIN-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "03573d93db26675bb1ee064a21197d42542ad1e326a6b814135491992ac08906", + "data/WS-LNGUYEN-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "ccce55e03e2546c34be4c7b252be449c360a93b775b4984d081555dec7a758a8", + "data/WS-OHADDAD-01.meridianhcs.local/bash_history/omar.haddad.bash_history": "4b3502b37538e2b25e0b8329303dce02f65707480786f152845e4961ecc3c313", + "data/FILE-LNX-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "f17b48498d601ac5bc950bd066cd017d1b092d3937b57dca3bb1c647657f9a98", + "data/FILE-LNX-01.meridianhcs.local/bash_history/priya.patel.bash_history": "7598d9a8d5cb7256007be7e433144f5c657f6f63cf88718f9daab59069b76b12", + "data/FILE-LNX-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "9d7518a98448e6fa4adb628b49a011bb9e1627ab3ce50bd1fc39307524e59a1c", + "data/APP-INT-01.meridianhcs.local/bash_history/marcus.chen.bash_history": "dfe26330c9245b119a35c320f2d7669746297e3395757ac024b9056ebdce0da1", + "data/APP-INT-01.meridianhcs.local/bash_history/lina.nguyen.bash_history": "a78af3b127b26410d787923dab8353e047c2f428ab3de82169f856592889688e", + "data/APP-INT-01.meridianhcs.local/bash_history/root.bash_history": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "data/APP-INT-01.meridianhcs.local/bash_history/aisha.johnson.bash_history": "b04c155840f7583699401a93770c5a0aa388fb8d819bbe0217739da900d19544" + } + } + ] + }, + "checkpoint": { + "exact_exit": 1, + "checkpoint_unchanged": true, + "status": { + "behavior_change": "localized", + "behavior_differences": { + "behavior_history_sha256": { + "current": "f01ca7faeebe06b09572744926b89d442d27baa2cac5036bd7402927d71ad6ce", + "stored": "7b54114a8c15f587f5fa31f80892ecdac037a99e864fb5862bdf1ffd0b082482" + }, + "behavior_revision": { + "current": 92, + "stored": 89 + }, + "behavior_surface_sha256": { + "current": "7f12bd02b78cac7e8ccae605df62083bfccca7a2dc0e7b7356dcc484e063e7ff", + "stored": "120dd81053c2116d467a2637f2ccc52e0f155ce4b546a114acde26eee4e9705c" + }, + "evidenceforge_build_sha256": { + "current": "968ddd39803290d8f115e33cf55fea6b6f494c7656a6fa8033806a298331d86f", + "stored": "c90af0b333c28990fcef11bc84fb3830339e050db24cebe25b466800a57aa2c3" + } + }, + "checkpoint_hours": 1, + "compatibility": "passed", + "compatibility_level": "load-compatible", + "confirmation_required": false, + "diagnostics": { + "behavior_change_ids": [ + "typed-record-validation", + "evaluator-source-routing", + "legacy-validation-snapshot-decoding" + ], + "behavior_domains": [ + "record-validation", + "validation-preflight" + ], + "behavior_formats": [], + "behavior_summaries": [ + "Replace record validation contracts without changing rendered evidence.", + "Declares parser validation ownership and explicit evaluation failures without changing rendered evidence.", + "Decodes recognized legacy validation metadata for compatible checkpoint hydration without changing rendering definitions." + ], + "checkpoint_schema": "2.0", + "checkpoint_workspace_forecast": { + "expected_bytes": 7283181, + "lower_bytes": 1553538, + "upper_bytes": 11977116 + }, + "checkpoint_workspace_forecast_vs_actual": { + "actual_bytes": 5450278, + "actual_to_expected_ratio": 0.7483375739254592, + "expected_bytes": 7283181 + }, + "component_mismatches": { + "behavior_history_sha256": { + "current": "f01ca7faeebe06b09572744926b89d442d27baa2cac5036bd7402927d71ad6ce", + "stored": "7b54114a8c15f587f5fa31f80892ecdac037a99e864fb5862bdf1ffd0b082482" + }, + "behavior_revision": { + "current": 92, + "stored": 89 + }, + "behavior_surface_sha256": { + "current": "7f12bd02b78cac7e8ccae605df62083bfccca7a2dc0e7b7356dcc484e063e7ff", + "stored": "120dd81053c2116d467a2637f2ccc52e0f155ce4b546a114acde26eee4e9705c" + }, + "dependencies": { + "current": { + "jinja2": "3.1.6", + "pydantic": "2.13.5", + "pytz": "2026.3.post1", + "pyyaml": "6.0.3", + "typer": "0.27.2" + }, + "stored": { + "jinja2": "3.1.6", + "json-logic-qubit": "0.9.1", + "pydantic": "2.13.5", + "pytz": "2026.3.post1", + "pyyaml": "6.0.3", + "typer": "0.27.2" + } + }, + "evidenceforge_build_sha256": { + "current": "968ddd39803290d8f115e33cf55fea6b6f494c7656a6fa8033806a298331d86f", + "stored": "c90af0b333c28990fcef11bc84fb3830339e050db24cebe25b466800a57aa2c3" + } + }, + "current_components": { + "behavior_history_sha256": "f01ca7faeebe06b09572744926b89d442d27baa2cac5036bd7402927d71ad6ce", + "behavior_history_start_revision": 1, + "behavior_manifest_schema": "1.0", + "behavior_revision": 92, + "behavior_surface_sha256": "7f12bd02b78cac7e8ccae605df62083bfccca7a2dc0e7b7356dcc484e063e7ff", + "checkpoint_schema": "2.0", + "dependencies": { + "jinja2": "3.1.6", + "pydantic": "2.13.5", + "pytz": "2026.3.post1", + "pyyaml": "6.0.3", + "typer": "0.27.2" + }, + "evidenceforge_build_sha256": "968ddd39803290d8f115e33cf55fea6b6f494c7656a6fa8033806a298331d86f", + "evidenceforge_version": "2.1.0", + "formats": [ + "bash_history", + "cisco_asa", + "ecar", + "proxy_access", + "snort_alert", + "syslog", + "web_access", + "windows", + "zeek" + ], + "interpreter_cache_tag": "cpython-312", + "machine": "arm64", + "oob_hosts": [], + "output_target": "default", + "platform": "darwin", + "python": "3.12.9", + "python_compiler": "Clang 16.0.0 (clang-1600.0.26.6)", + "python_implementation": "CPython", + "resolved_sha256": "2d44f65d765f35d8f508fae6f00d7abd9e7c2a00ba071b2a621983e01e21df2e", + "sys_byteorder": "little" + }, + "current_fingerprint": "2d280877ca174a5fa86fdd6dc54d1ad786bc87123a9a3a94290c2f69db906a45", + "filesystem": { + "durability_probe": "not repeated by read-only status; required when generation starts", + "ownership_and_no_symlink_validation": "performed" + }, + "hard_component_mismatches": [], + "lock": { + "detail": null, + "heartbeat": "not used; local liveness is process-probed", + "owner": null, + "state": "absent" + }, + "participant_heads": 26, + "phase_completed_hours": 2, + "phase_total_hours": 3, + "run_id": "bb1b50d183004c67b29688c4f67ba2eb", + "segment_bytes": 1537705, + "segment_count": 60, + "selected_sequence": 2, + "stored_components": { + "behavior_history_sha256": "7b54114a8c15f587f5fa31f80892ecdac037a99e864fb5862bdf1ffd0b082482", + "behavior_history_start_revision": 1, + "behavior_manifest_schema": "1.0", + "behavior_revision": 89, + "behavior_surface_sha256": "120dd81053c2116d467a2637f2ccc52e0f155ce4b546a114acde26eee4e9705c", + "checkpoint_schema": "2.0", + "dependencies": { + "jinja2": "3.1.6", + "json-logic-qubit": "0.9.1", + "pydantic": "2.13.5", + "pytz": "2026.3.post1", + "pyyaml": "6.0.3", + "typer": "0.27.2" + }, + "evidenceforge_build_sha256": "c90af0b333c28990fcef11bc84fb3830339e050db24cebe25b466800a57aa2c3", + "evidenceforge_version": "2.1.0", + "formats": [ + "bash_history", + "cisco_asa", + "ecar", + "proxy_access", + "snort_alert", + "syslog", + "web_access", + "windows", + "zeek" + ], + "interpreter_cache_tag": "cpython-312", + "machine": "arm64", + "oob_hosts": [], + "output_target": "default", + "platform": "darwin", + "python": "3.12.9", + "python_compiler": "Clang 16.0.0 (clang-1600.0.26.6)", + "python_implementation": "CPython", + "resolved_sha256": "2d44f65d765f35d8f508fae6f00d7abd9e7c2a00ba071b2a621983e01e21df2e", + "sys_byteorder": "little" + }, + "stored_fingerprint": "0a3805af6279d69710ad27129f583ebca4105f50c7e1a9fe6656984573661f7d", + "validation_bytes_hashed": 8730962, + "validation_seconds": 0.9442476669792086, + "workspace_bytes": 5450278 + }, + "errors": [], + "integrity": "passed", + "loadability": "not-verified", + "output_equivalence": "not-guaranteed", + "output_root": "/private/tmp/eforge-gap-slow-final/test_baseline_checkpoint_upgra0/suspended", + "phase": "collection", + "phase_completed_hours": 2, + "phase_total_hours": 3, + "recovery_points": [ + { + "error": null, + "phase": "collection", + "role": "latest", + "sequence": 2, + "simulated_hour": 3, + "valid": true + }, + { + "error": null, + "phase": "collection", + "role": "previous", + "sequence": 1, + "simulated_hour": 2, + "valid": true + } + ], + "restore_verified": false, + "resume_command": "eforge generate --output /private/tmp/eforge-gap-slow-final/test_baseline_checkpoint_upgra0/suspended --resume", + "run_differences": {}, + "run_identity": "matched", + "runtime_differences": { + "dependencies": { + "current": { + "jinja2": "3.1.6", + "pydantic": "2.13.5", + "pytz": "2026.3.post1", + "pyyaml": "6.0.3", + "typer": "0.27.2" + }, + "stored": { + "jinja2": "3.1.6", + "json-logic-qubit": "0.9.1", + "pydantic": "2.13.5", + "pytz": "2026.3.post1", + "pyyaml": "6.0.3", + "typer": "0.27.2" + } + } + }, + "schema_version": "1.1", + "simulated_hour": 3, + "state": "resumable", + "state_contract_differences": {}, + "storage": { + "available_bytes": 337081720832, + "checkpoint_bytes": 5450278, + "generated_bytes": 745908, + "managed_file_count": 165, + "prior_bundle_bytes": 0, + "recovery_overhead_bytes": 5450278, + "total_managed_bytes": 6196186, + "unrelated_entry_count": 0 + }, + "suspended": true, + "suspension_requested": false, + "used_fallback": false, + "warnings": [ + "checkpoint has attemptable build or runtime drift; serialized state must be fully verified, and remaining output equivalence is not guaranteed" + ] + }, + "resume_exit": 0, + "evidence_files": 24 + }, + "evaluation": { + "sof-elk": { + "records": 123105, + "sources": { + "bash_history": 283, + "cisco_asa": 18930, + "ecar": 33307, + "email_artifacts": 25, + "proxy_access": 2236, + "snort_alert": 146, + "syslog": 3948, + "web_access": 822, + "windows_event_security": 18718, + "windows_event_sysmon": 11517, + "zeek_conn": 19850, + "zeek_dhcp": 47, + "zeek_dns": 3728, + "zeek_files": 2113, + "zeek_http": 3376, + "zeek_ocsp": 89, + "zeek_pe": 3, + "zeek_smb_files": 215, + "zeek_smb_mapping": 125, + "zeek_smtp": 46, + "zeek_ssl": 2496, + "zeek_x509": 1085 + }, + "overall": 92.00543296527613, + "acceptance_passed": false, + "failed_gates": [ + { + "name": "parseability.spec_conformance", + "pillar": "parseability", + "sub_score_key": "spec_conformance", + "threshold": 100.0, + "aspirational": 100.0, + "actual": 75.43966532634742, + "passed": false, + "applicable": true, + "meets_aspirational": false, + "level": "hard" + }, + { + "name": "causality.pivot_linkability", + "pillar": "causality", + "sub_score_key": "pivot_linkability", + "threshold": 80.0, + "aspirational": 95.0, + "actual": 79.16666666666667, + "passed": false, + "applicable": true, + "meets_aspirational": false, + "level": "hard" + }, + { + "name": "causality.temporal_integrity", + "pillar": "causality", + "sub_score_key": "temporal_integrity", + "threshold": 85.0, + "aspirational": 95.0, + "actual": 79.16666666666667, + "passed": false, + "applicable": true, + "meets_aspirational": false, + "level": "hard" + } + ], + "schema": 75.43966532634742, + "correctness": 100.0 + }, + "splunk": { + "records": 123105, + "sources": { + "bash_history": 283, + "cisco_asa": 18930, + "ecar": 33307, + "email_artifacts": 25, + "proxy_access": 2236, + "snort_alert": 146, + "syslog": 3948, + "web_access": 822, + "windows_event_security": 18718, + "windows_event_sysmon": 11517, + "zeek_conn": 19850, + "zeek_dhcp": 47, + "zeek_dns": 3728, + "zeek_files": 2113, + "zeek_http": 3376, + "zeek_ocsp": 89, + "zeek_pe": 3, + "zeek_smb_files": 215, + "zeek_smb_mapping": 125, + "zeek_smtp": 46, + "zeek_ssl": 2496, + "zeek_x509": 1085 + }, + "overall": 95.33304610265087, + "acceptance_passed": false, + "failed_gates": [ + { + "name": "causality.indicator_accuracy", + "pillar": "causality", + "sub_score_key": "indicator_accuracy", + "threshold": 85.0, + "aspirational": 95.0, + "actual": 71.92151556156969, + "passed": false, + "applicable": true, + "meets_aspirational": false, + "level": "hard" + }, + { + "name": "causality.temporal_integrity", + "pillar": "causality", + "sub_score_key": "temporal_integrity", + "threshold": 85.0, + "aspirational": 95.0, + "actual": 83.33333333333333, + "passed": false, + "applicable": true, + "meets_aspirational": false, + "level": "hard" + } + ], + "schema": 100.0, + "correctness": 100.0 + } + }, + "tests": { + "routine": { + "passed": 11439, + "skipped": 68, + "deselected": 2025, + "seconds": 368.81 + }, + "slow": { + "passed": 5, + "deselected": 7, + "seconds": 482.28 + }, + "focused": { + "passed": 152, + "deselected": 2456, + "seconds": 8.11 + } + }, + "pending": [ + "SOF-ELK Snare projection contract and identity label information preservation", + "Splunk indicator matching investigation", + "Existing temporal integrity failure", + "Zeek diagnostic-source generation coverage investigation", + "Linux/Windows CI", + "Independent review" + ], + "performance": { + "summary": { + "baseline": { + "seconds": 12.302766000037082, + "peak_rss_bytes": 777846784 + }, + "candidate": { + "seconds": 12.103271708008833, + "peak_rss_bytes": 774471680 + } + }, + "runs": [ + { + "revision": "baseline", + "run": 0, + "seconds": 12.288577334024012, + "peak_rss_bytes": 777846784, + "records": 123105, + "exit": 0 + }, + { + "revision": "candidate", + "run": 0, + "seconds": 12.110443916986696, + "peak_rss_bytes": 776798208, + "records": 123105, + "exit": 0 + }, + { + "revision": "baseline", + "run": 1, + "seconds": 12.293113749939948, + "peak_rss_bytes": 778043392, + "records": 123105, + "exit": 0 + }, + { + "revision": "candidate", + "run": 1, + "seconds": 12.103271708008833, + "peak_rss_bytes": 772997120, + "records": 123105, + "exit": 0 + }, + { + "revision": "baseline", + "run": 2, + "seconds": 12.312071250053123, + "peak_rss_bytes": 774012928, + "records": 123105, + "exit": 0 + }, + { + "revision": "candidate", + "run": 2, + "seconds": 12.09251404099632, + "peak_rss_bytes": 778059776, + "records": 123105, + "exit": 0 + }, + { + "revision": "baseline", + "run": 3, + "seconds": 12.345635375007987, + "peak_rss_bytes": 778321920, + "records": 123105, + "exit": 0 + }, + { + "revision": "candidate", + "run": 3, + "seconds": 12.117104000062682, + "peak_rss_bytes": 773128192, + "records": 123105, + "exit": 0 + }, + { + "revision": "baseline", + "run": 4, + "seconds": 12.302766000037082, + "peak_rss_bytes": 773832704, + "records": 123105, + "exit": 0 + }, + { + "revision": "candidate", + "run": 4, + "seconds": 12.059598000021651, + "peak_rss_bytes": 774471680, + "records": 123105, + "exit": 0 + } + ] + }, + "baseline_target_evaluation": { + "sof-elk": { + "records": 123105, + "overall": 88.5760678165854, + "schema": 75.43885301165672, + "correctness": 75.43885301165672, + "acceptance_passed": false + }, + "splunk": { + "records": 123105, + "overall": 94.6609994150794, + "schema": 97.51512936111449, + "correctness": 99.99916699292777, + "acceptance_passed": false + } + } +} diff --git a/pyproject.toml b/pyproject.toml index 803de6993..9597f94a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ [project] name = "evidence-forge" -version = "2.1.0" +version = "2.1.1" description = "Generate realistic synthetic security logs for cybersecurity threat hunting training and research" readme = "README.md" license = "MIT" @@ -39,7 +39,6 @@ dependencies = [ "pyyaml>=6.0", "pytz>=2026.3.post1", "jinja2>=3.1.0", - "json-logic-qubit>=0.9.1", "python-dotenv>=1.2.2", "cryptography>=50.0.0", "psutil>=7.0.0", diff --git a/scenarios/iteration-test/scenario.yaml b/scenarios/iteration-test/scenario.yaml index 758d0a027..d43e85506 100644 --- a/scenarios/iteration-test/scenario.yaml +++ b/scenarios/iteration-test/scenario.yaml @@ -815,7 +815,7 @@ storyline: - id: evt-011 time: "+2h59m" actor: root - system: LT-MRIVERA-02 + system: WS-AJOHNSON-01 activity: "Wrong-password fumble before broader credential spray" events: - type: failed_logon diff --git a/scripts/benchmark_validation.py b/scripts/benchmark_validation.py new file mode 100644 index 000000000..b4680dd10 --- /dev/null +++ b/scripts/benchmark_validation.py @@ -0,0 +1,93 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Measure five isolated full CLI evaluations per revision on macOS/Linux. + +Includes imports, parsing and all scoring pillars. Records wall time and peak child RSS; +20% is an investigation threshold, never a timing-sensitive CI assertion. +""" + +import argparse +import json +import os +import statistics +import subprocess +import sys +import time +from pathlib import Path +from typing import Any + + +def main() -> None: + """Alternate the two interpreters against exactly the same retained bundle.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--baseline-python", type=Path, required=True) + parser.add_argument("--candidate-python", type=Path, required=True) + parser.add_argument("--bundle", type=Path, required=True) + parser.add_argument("--output", type=Path, required=True) + args = parser.parse_args() + if not hasattr(os, "wait4"): + parser.error("Peak child RSS collection requires macOS or Linux wait4") + output = args.output.resolve() + output.mkdir(exist_ok=False) + rows: list[dict[str, Any]] = [] + for index in range(5): + for revision, executable in ( + ("baseline", args.baseline_python), + ("candidate", args.candidate_python), + ): + stem = output / f"{revision}-{index}" + with ( + stem.with_suffix(".json").open("w") as stdout, + stem.with_suffix(".err").open("w") as stderr, + ): + start = time.monotonic() + process = subprocess.Popen( + [ + str(executable.absolute()), + "-m", + "evidenceforge", + "eval", + str(args.bundle.resolve()), + "--format", + "json", + ], + stdout=stdout, + stderr=stderr, + ) + _pid, status, usage = os.wait4(process.pid, 0) + process.returncode = os.waitstatus_to_exitcode(status) + seconds = time.monotonic() - start + if process.returncode: + raise RuntimeError( + f"{revision} evaluation failed; inspect {stem.with_suffix('.err')}" + ) + text = stem.with_suffix(".json").read_text() + # The baseline can emit warnings before its JSON; retain original bytes. + report = json.JSONDecoder().raw_decode(text[text.index("{") :])[0] + if len(report["pillars"]) != 4 or any(p["score"] is None for p in report["pillars"]): + raise RuntimeError(f"{revision} did not complete all scoring pillars") + rows.append( + { + "revision": revision, + "run": index, + "seconds": seconds, + "peak_rss_bytes": usage.ru_maxrss * (1 if sys.platform == "darwin" else 1024), + "records": report["total_records"], + "exit": process.returncode, + } + ) + (output / "runs.json").write_text(json.dumps(rows, indent=2)) + summary = { + revision: { + metric: statistics.median(row[metric] for row in rows if row["revision"] == revision) + for metric in ("seconds", "peak_rss_bytes") + } + for revision in ("baseline", "candidate") + } + (output / "summary.json").write_text(json.dumps(summary, indent=2)) + print(json.dumps(summary, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/scripts/capture_validation_compatibility.py b/scripts/capture_validation_compatibility.py new file mode 100644 index 000000000..50bce5fc8 --- /dev/null +++ b/scripts/capture_validation_compatibility.py @@ -0,0 +1,168 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Capture CLI/configuration compatibility in either revision's isolated interpreter. + +Run once per revision with distinct --output directories, using the same fixture repository. +The capture is diagnostic; compare package validation documents/digests separately from user data. +""" + +import argparse +import json +import os +import shutil +from pathlib import Path +from typing import Any + +import yaml +from typer.testing import CliRunner + +from evidenceforge.cli.commands import app +from evidenceforge.composition import compile_scenario + + +def main() -> None: + """Capture both scenario versions, project scopes, and immutable pack operations.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--repository", type=Path, default=Path(__file__).resolve().parents[1]) + args = parser.parse_args() + root = args.output.resolve() + root.mkdir(exist_ok=False) + repo = args.repository.resolve() + runner = CliRunner() + rows: dict[str, Any] = {} + + def call(key: str, args: list[str], cwd: Path | None = None) -> Any: + os.chdir(cwd or root) + r = runner.invoke(app, args) + payload = None + try: + payload = json.loads(r.stdout) + except ValueError: + pass + rows[key] = { + "exit": r.exit_code, + "stdout": r.stdout, + "stderr": r.stderr, + "payload": payload, + } + (root / "results.json").write_text(json.dumps(rows, indent=2, default=str)) + return r + + for p in ("a", "b"): + project = root / p + project.mkdir() + child = project / "child" + child.mkdir() + overlay = project / ".eforge/config/activity" + overlay.mkdir(parents=True) + (overlay / "dns_registry.yaml").write_text( + yaml.safe_dump( + { + "domains": [ + { + "domain": "claims.healthcare.example", + "ips": ["203.0.113." + ("44" if p == "a" else "45")], + "tags": ["healthcare"], + "_replace": True, + } + ] + } + ) + ) + for version, fixture in [("v1", "minimal.yaml"), ("v2", "northstar-health-pack.yaml")]: + scenario = project / (version + ".yaml") + shutil.copyfile(repo / "tests/fixtures/scenarios" / fixture, scenario) + for mode, cwd, extra in [ + ("cwd", project, []), + ("explicit", child, ["--project-root", str(project)]), + ("no_ancestor", child, []), + ]: + prefix = p + "-" + version + "-" + mode + call(prefix + "-validate", ["validate", str(scenario), *extra], cwd) + call( + prefix + "-resolve", + [ + "resolve", + str(scenario), + "--output", + str(project / (prefix + "-resolved.yaml")), + "--json", + *extra, + ], + cwd, + ) + compiled = compile_scenario(scenario, project_root=project if extra else None) + rows[prefix + "-compiled"] = {"payload": compiled.model_dump(mode="json")} + call( + p + "-" + version + "-resolved-validate", + ["validate", str(project / (p + "-" + version + "-cwd-resolved.yaml"))], + project, + ) + call(p + "-config", ["validate-config", "--json"], project) + call( + p + "-config-explicit", + ["validate-config", "--json", "--project-root", str(project)], + child, + ) + call(p + "-config-no-ancestor", ["validate-config", "--json"], child) + # Reenter A after B in one interpreter to detect stale configuration. + call("a-config-repeat", ["validate-config", "--json"], root / "a") + ref = "package:evidenceforge:organization:metrolink-specialty-care@1.0.0" + archive = root / "pack.efpack" + for key, args in [ + ("pack-validate", ["pack", "validate", ref, "--json"]), + ("pack-build", ["pack", "build", ref, "--output", str(archive), "--json"]), + ("pack-inspect", ["pack", "inspect", str(archive), "--json"]), + ( + "pack-import", + [ + "pack", + "import", + str(archive), + "--scope", + "project", + "--accept-publisher", + "evidenceforge", + "--project-root", + str(root / "a"), + "--json", + ], + ), + ( + "pack-hydrate", + [ + "pack", + "hydrate", + "evidenceforge:organization:metrolink-specialty-care@1.0.0", + "--scope", + "project", + "--project-root", + str(root / "a"), + "--json", + ], + ), + ]: + call(key, args) + for fmt in ("text", "json"): + call( + "legacy-eval-" + fmt, + [ + "eval", + str(repo / "tests/fixtures/eval/good"), + "--scenario", + str(repo / "tests/fixtures/scenarios/retail-store-ftp-attack.yaml"), + "--format", + fmt, + ], + ) + rows["installed-locks"] = { + "payload": {str(p.relative_to(root)): p.read_text() for p in root.rglob("pack.lock.yaml")} + } + (root / "results.json").write_text(json.dumps(rows, indent=2, default=str)) + print({k: v.get("exit") for k, v in rows.items() if v.get("exit")}) + + +if __name__ == "__main__": + main() diff --git a/src/evidenceforge/__init__.py b/src/evidenceforge/__init__.py index ee15ca33f..3fc16be97 100644 --- a/src/evidenceforge/__init__.py +++ b/src/evidenceforge/__init__.py @@ -27,5 +27,5 @@ architecture combining LLM-driven scenario creation with deterministic log generation. """ -__version__ = "2.1.0" +__version__ = "2.1.1" __all__ = [] # Will be expanded as modules are implemented diff --git a/src/evidenceforge/cli/commands.py b/src/evidenceforge/cli/commands.py index 19ae68a7a..351fb1054 100644 --- a/src/evidenceforge/cli/commands.py +++ b/src/evidenceforge/cli/commands.py @@ -698,7 +698,8 @@ def setup_logging(verbose: bool = False, debug: bool = False) -> None: logging.basicConfig( level=level, format="%(message)s", - handlers=[RichHandler(console=console, rich_tracebacks=True)], + handlers=[RichHandler(console=Console(stderr=True), rich_tracebacks=debug)], + force=True, ) @@ -1157,6 +1158,9 @@ def _validate_compiled_scenario( if not isinstance(compiled, CompiledScenario): raise TypeError("compiled must be a CompiledScenario") with effective_config_scope(compiled.effective_config): + from evidenceforge.formats.loader import validate_packaged_contracts + + validate_packaged_contracts() validator = ScenarioValidator( compiled.scenario, oob_hosts=oob_hosts, @@ -2551,12 +2555,25 @@ def validate( console.print(f" Network: {segments} segments, {sensors} sensors") console.print("\n[bold]Validating cross-references...[/bold]") - validator, issues = _validate_compiled_scenario( - compiled, - oob_hosts, - scenario_file.parent, - allow_large_workload=allow_large_workload, - ) + try: + validator, issues = _validate_compiled_scenario( + compiled, + oob_hosts, + scenario_file.parent, + allow_large_workload=allow_large_workload, + ) + except EvidenceForgeError as exc: + if json_output: + payload = _validation_json_payload( + scenario_file=scenario_file, + input_kind=compiled.authored_kind, + project_root=resolved_project_root, + issues=_exception_issue_payloads(exc, scenario_file), + ) + print(json.dumps(payload, indent=2, sort_keys=True)) + else: + console.print(Text(f"Configuration validation failed: {exc}", style="red")) + raise typer.Exit(EXIT_SCHEMA_VALIDATION) from exc issues.extend(_legacy_public_identity_deprecation_issues(compiled)) from evidenceforge.config.provider import effective_config_scope @@ -2702,7 +2719,7 @@ def eval_cmd( help="Evaluate the authoritative bundle despite an authored-scenario digest mismatch.", ), ) -> None: - """Evaluate a generated dataset for quality across four pillars. + """Evaluate a generated dataset; schema and record correctness require 100%. Reads generated log files and the original scenario, runs deterministic and statistical quality checks, and produces a quality report. @@ -2711,7 +2728,9 @@ def eval_cmd( - 0: Evaluation completed (check report for pass/fail) - 1: Input error (file not found, invalid path) - 2: Schema validation error in scenario - - 22: Evaluation engine error + - 22: Evaluation engine or scoring-pillar error (no report) + + JSON reports use stdout; logging and progress use stderr. """ if output_format not in {"text", "json"}: console.print( diff --git a/src/evidenceforge/cli/install_skills.py b/src/evidenceforge/cli/install_skills.py index 0cde2ac47..6d8f203be 100644 --- a/src/evidenceforge/cli/install_skills.py +++ b/src/evidenceforge/cli/install_skills.py @@ -45,6 +45,7 @@ _CHATGPT_REFERENCES_BY_SKILL = { "config": ( + "references/record-validation.md", "references/project-context.md", "references/config-apps-processes.md", "references/config-compatibility.md", @@ -56,6 +57,7 @@ "references/config-validation.md", ), "evaluate": ( + "references/record-validation.md", "references/evidence-endpoint-linux.md", "references/evidence-network-ids.md", "references/evidence-web-email.md", @@ -63,6 +65,7 @@ "references/generation-bundle-targets.md", ), "generate": ( + "references/record-validation.md", "references/project-context.md", "references/checkpoint-recovery.md", "references/evidence-endpoint-linux.md", @@ -72,6 +75,7 @@ "references/generation-bundle-targets.md", ), "industry-pack": ( + "references/record-validation.md", "references/project-context.md", "references/pack-reference.md", "references/scenario-baseline-output.md", @@ -82,6 +86,7 @@ "references/scenario-smb.md", ), "organization-pack": ( + "references/record-validation.md", "references/project-context.md", "references/pack-reference.md", "references/scenario-baseline-output.md", @@ -92,9 +97,18 @@ "references/scenario-http.md", "references/scenario-smb.md", ), - "pack": ("references/project-context.md", "references/pack-reference.md"), - "pack-release": ("references/project-context.md", "references/pack-reference.md"), + "pack": ( + "references/project-context.md", + "references/pack-reference.md", + "references/record-validation.md", + ), + "pack-release": ( + "references/project-context.md", + "references/pack-reference.md", + "references/record-validation.md", + ), "scenario": ( + "references/record-validation.md", "references/project-context.md", "references/evidence-endpoint-linux.md", "references/evidence-network-ids.md", @@ -118,6 +132,7 @@ "references/scenario-storyline.md", ), "validate": ( + "references/record-validation.md", "references/project-context.md", "references/validation-safety.md", "references/validation-storage.md", diff --git a/src/evidenceforge/config/evaluation/co_occurrence.yaml b/src/evidenceforge/config/evaluation/co_occurrence.yaml index ed771f354..55a21f30a 100644 --- a/src/evidenceforge/config/evaluation/co_occurrence.yaml +++ b/src/evidenceforge/config/evaluation/co_occurrence.yaml @@ -1,360 +1,2 @@ -# co_occurrence.yaml — Tier B record-level fidelity rules -# -# Purpose: Checks that when a condition matches in a generated record, -# required field constraints hold (e.g., network logon has valid IP). -# -# Depends on: format definitions in config/formats/ (field names must exist) -# Depended on by: evaluation engine (eforge eval) -# -# To add a new rule: -# 1. Add under the format name key (e.g., windows_event_security:) -# 2. Define condition: fields that must match for the rule to apply -# 3. Define checks: constraints that must hold when condition matches -# 4. Valid check types: not_equal, present, min_length, matches -# -# Full schema: see commands/eforge/references/config-evaluation.md - -windows_event_security: - - name: "Network logon (type 3) requires valid IP" - condition: - EventID: 4624 - LogonType: 3 - exclude: - TargetUserName: "ANONYMOUS LOGON" - checks: - - field: IpAddress - not_equal: "-" - - field: IpAddress - not_equal: "" - - - name: "Interactive logon (type 2) uses local workstation" - condition: - EventID: 4624 - LogonType: 2 - checks: - - field: WorkstationName - not_equal: "" - - - name: "Process creation has process name" - condition: - EventID: 4688 - checks: - - field: NewProcessName - min_length: 1 - - - name: "Logoff must have a logon type" - condition: - EventID: 4634 - checks: - - field: LogonType - present: true - - - name: "Logon has valid SID" - condition: - EventID: 4624 - checks: - - field: TargetUserSid - not_equal: "" - - - name: "Failed logon has status code" - condition: - EventID: 4625 - checks: - - field: Status - present: true - - field: TargetUserName - min_length: 1 - - - name: "Special privileges has privilege list" - condition: - EventID: 4672 - checks: - - field: PrivilegeList - min_length: 1 - - - name: "Process termination has process name" - condition: - EventID: 4689 - checks: - - field: ProcessName - min_length: 1 - - field: ProcessId - present: true - - - name: "Kerberos TGT has krbtgt service" - condition: - EventID: 4768 - checks: - - field: ServiceName - equals: "krbtgt" - - field: IpAddress - not_equal: "-" - - - name: "Kerberos service ticket has service name" - condition: - EventID: 4769 - checks: - - field: ServiceName - min_length: 1 - - field: IpAddress - not_equal: "-" - - - name: "NTLM validation has workstation" - condition: - EventID: 4776 - checks: - - field: Workstation - min_length: 1 - - field: TargetUserName - min_length: 1 - - - name: "Kerberos preauth failure has status" - condition: - EventID: 4771 - checks: - - field: Status - present: true - - field: TargetUserName - min_length: 1 - - - name: "WFP connection has direction" - condition: - EventID: 5156 - checks: - - field: Direction - in: ["%%14592", "%%14593"] - - field: SourceAddress - present: true - - field: DestAddress - present: true - - - name: "Explicit creds has target server" - condition: - EventID: 4648 - checks: - - field: TargetServerName - min_length: 1 - - field: TargetUserName - min_length: 1 - -zeek_conn: - - name: "Completed connection (SF) has duration" - condition: - conn_state: "SF" - checks: - - field: duration - present: true - - - name: "Completed connection (SF) has byte counts" - condition: - conn_state: "SF" - checks: - - field: orig_bytes - present: true - - field: resp_bytes - present: true - - - name: "Connection has valid protocol" - condition: {} - checks: - - field: proto - in: ["tcp", "udp", "icmp"] - - # Impossible combinations - - name: "Completed TCP (SF) cannot have zero duration" - condition: - conn_state: "SF" - proto: "tcp" - checks: - - field: duration - not_equal: 0 - - -ecar: - # Process-owned eCAR records should carry source-native process/thread IDs. - # Session rows and listenerless/failure FLOW rows may legitimately omit them. - - name: "PROCESS records have pid" - condition: - object: "PROCESS" - checks: - - field: pid - present: true - - - name: "PROCESS/CREATE records have canonical primary tid" - condition: - object: "PROCESS" - action: "CREATE" - checks: - - field: tid - present: true - - - name: "PROCESS/TERMINATE records have canonical primary tid" - condition: - object: "PROCESS" - action: "TERMINATE" - checks: - - field: tid - present: true - - - name: "All records have objectID" - condition: {} - checks: - - field: objectID - present: true - - # PROCESS-specific - - name: "PROCESS/CREATE has image_path" - condition: - object: "PROCESS" - action: "CREATE" - checks: - - field: image_path - present: true - - - name: "PROCESS/CREATE has ppid" - condition: - object: "PROCESS" - action: "CREATE" - checks: - - field: ppid - present: true - - - name: "PROCESS/CREATE has command_line" - condition: - object: "PROCESS" - action: "CREATE" - checks: - - field: command_line - present: true - - # THREAD-specific - - name: "THREAD/REMOTE_CREATE has target info" - condition: - object: "THREAD" - action: "REMOTE_CREATE" - checks: - - field: target_pid - present: true - - field: image_path - present: true - - # PROCESS/OPEN-specific - - name: "PROCESS/OPEN has source image" - condition: - object: "PROCESS" - action: "OPEN" - checks: - - field: image_path - present: true - - # FLOW-specific - - name: "FLOW events have network fields" - condition: - object: "FLOW" - checks: - - field: src_ip - present: true - - field: dst_ip - present: true - - # SERVICE-specific - - name: "SERVICE/CREATE has service name" - condition: - object: "SERVICE" - action: "CREATE" - checks: - - field: service_name - present: true - - # USER_SESSION-specific - - name: "USER_SESSION LOGIN has principal" - condition: - object: "USER_SESSION" - action: "LOGIN" - checks: - - field: principal - present: true - -syslog: - - name: "Syslog has non-empty message" - condition: {} - checks: - - field: message - min_length: 1 - - - name: "Syslog has hostname" - condition: {} - checks: - - field: hostname - not_equal: "" - -snort_alert: - - name: "Alert has valid priority" - condition: {} - checks: - - field: priority - min_value: 1 - max_value: 4 - - - name: "Alert has source and destination" - condition: {} - checks: - - field: src_ip - present: true - - field: dst_ip - present: true - -web_access: - - name: "Request has valid status code" - condition: {} - checks: - - field: status_code - min_value: 100 - max_value: 599 - - - name: "Request has HTTP method" - condition: {} - checks: - - field: method - in: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"] - -zeek_dns: - - name: "DNS query has non-empty query field" - condition: {} - checks: - - field: query - min_length: 1 - - - name: "DNS response has rcode" - condition: {} - checks: - - field: rcode_name - present: true - -zeek_http: - - name: "HTTP CONNECT must not have response body" - condition: - method: "CONNECT" - status_code: 200 - checks: - - field: response_body_len - equals: 0 - - - name: "HTTP response has method" - condition: {} - checks: - - field: method - in: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH", "CONNECT", "TRACE"] - -bash_history: - - name: "Command is non-empty" - condition: {} - checks: - - field: command - min_length: 1 - - - name: "Has username" - condition: {} - checks: - - field: username - not_equal: "" +# Record rules now live in config/formats/*.yaml as typed validators. +{} diff --git a/src/evidenceforge/config/evaluation/thresholds.yaml b/src/evidenceforge/config/evaluation/thresholds.yaml index af6362059..4613a74b9 100644 --- a/src/evidenceforge/config/evaluation/thresholds.yaml +++ b/src/evidenceforge/config/evaluation/thresholds.yaml @@ -18,15 +18,15 @@ pillars: weight: 0.30 sub_scores: spec_conformance: - minimum: 95 - aspirational: 99 + minimum: 100 + aspirational: 100 hard_gate: true - # Real SIEMs tolerate ~5% parse failures; 98 was aspirational, not achievable. + # Every observed record must satisfy the source schema. format_constraints: - minimum: 90 - aspirational: 98 + minimum: 100 + aspirational: 100 hard_gate: true - # Constraint violations are authoring errors; more forgiving floor. + # Correctness violations cannot be averaged away. # Pillar 2 — Plausibility # Goal: no impossible or highly-improbable field values, combinations, or @@ -43,7 +43,7 @@ pillars: minimum: 85 aspirational: 95 hard_gate: false - # Rules are incomplete; tighten as co_occurrence.yaml coverage grows. + # Context-dependent record realism is diagnostic, not a correctness gate. distribution_fit: minimum: 70 aspirational: 85 diff --git a/src/evidenceforge/config/formats/README.md b/src/evidenceforge/config/formats/README.md index 11d297d29..d5be555ae 100644 --- a/src/evidenceforge/config/formats/README.md +++ b/src/evidenceforge/config/formats/README.md @@ -14,10 +14,10 @@ The filename (without `.yaml`) is the format name used throughout the system. name: format_name version: "1.0" description: "Human-readable description" -category: host | network | ids # Where this format originates +category: host | network | application | cloud # Where this format originates fields: - name: field_name - type: string | integer | float | datetime | boolean | ip_address | enum + type: string | integer | float | timestamp | boolean | ip_address | enum required: true | false description: "Field description" constraints: # Optional validation rules @@ -25,7 +25,8 @@ fields: allowed_values: [...] variants: # Optional event-type variants - name: variant_name - condition: { ... } # JSON Logic condition + event_id: "4624" # Source event selector + event_ids: [4624] # Optional explicit aliases fields: [...] # Additional/overriding fields output: format: text | json | xml | csv @@ -38,3 +39,6 @@ output: 1. Create `{name}.yaml` in this directory following the structure above. 2. See `docs/reference/EVIDENCE_FORMATS.md` for the full field type and constraint reference. 3. Run `uv run pytest tests/unit/test_format_loader.py` to validate. + +See `docs/reference/RECORD_VALIDATION.md` for typed predicates, structured findings, and +exact correctness gates. JSON Logic is no longer a supported internal contract. diff --git a/src/evidenceforge/config/formats/bash_history.yaml b/src/evidenceforge/config/formats/bash_history.yaml index 28a369567..b27ad8695 100644 --- a/src/evidenceforge/config/formats/bash_history.yaml +++ b/src/evidenceforge/config/formats/bash_history.yaml @@ -39,3 +39,23 @@ output: template: | #{{ timestamp.timestamp() | int }} {{ command }} + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: bash_history.legacy-1 + message: Command is non-empty + severity: error + when: [] + checks: + - op: length + field: command + minimum: 1 +- id: bash_history.legacy-2 + message: Has username + severity: error + when: [] + checks: + - op: compare + field: username + relation: ne + value: '' diff --git a/src/evidenceforge/config/formats/ecar.yaml b/src/evidenceforge/config/formats/ecar.yaml index 444742a1b..195cadbda 100644 --- a/src/evidenceforge/config/formats/ecar.yaml +++ b/src/evidenceforge/config/formats/ecar.yaml @@ -108,8 +108,9 @@ fields: - name: content_version type: integer required: false - description: "Canonical file content version when available" - + description: Canonical file content version when available + constraints: + min_value: 0 - name: src_ip type: ip_address required: false @@ -360,3 +361,283 @@ output: # Template not used — EcarEmitter builds JSON directly in Python. # Kept as an empty placeholder for format loader compatibility. template: "{}" + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: ecar.legacy-1 + message: PROCESS records have pid + severity: error + when: + - op: compare + field: object + relation: eq + value: PROCESS + checks: + - op: presence + field: pid + present: true +- id: ecar.legacy-2 + message: PROCESS/CREATE records have canonical primary tid + severity: warning + when: + - op: compare + field: object + relation: eq + value: PROCESS + - op: compare + field: action + relation: eq + value: CREATE + checks: + - op: presence + field: tid + present: true +- id: ecar.legacy-3 + message: PROCESS/TERMINATE records have canonical primary tid + severity: warning + when: + - op: compare + field: object + relation: eq + value: PROCESS + - op: compare + field: action + relation: eq + value: TERMINATE + checks: + - op: presence + field: tid + present: true +- id: ecar.legacy-4 + message: All records have objectID + severity: error + when: [] + checks: + - op: presence + field: objectID + present: true +- id: ecar.legacy-5 + message: PROCESS/CREATE has image_path + severity: error + when: + - op: compare + field: object + relation: eq + value: PROCESS + - op: compare + field: action + relation: eq + value: CREATE + checks: + - op: presence + field: image_path + present: true +- id: ecar.legacy-6 + message: PROCESS/CREATE has ppid + severity: warning + when: + - op: compare + field: object + relation: eq + value: PROCESS + - op: compare + field: action + relation: eq + value: CREATE + checks: + - op: presence + field: ppid + present: true +- id: ecar.legacy-7 + message: PROCESS/CREATE has command_line + severity: warning + when: + - op: compare + field: object + relation: eq + value: PROCESS + - op: compare + field: action + relation: eq + value: CREATE + checks: + - op: presence + field: command_line + present: true +- id: ecar.legacy-8 + message: THREAD/REMOTE_CREATE has target info + severity: warning + when: + - op: compare + field: object + relation: eq + value: THREAD + - op: compare + field: action + relation: eq + value: REMOTE_CREATE + checks: + - op: presence + field: target_pid + present: true + - op: presence + field: image_path + present: true +- id: ecar.legacy-9 + message: PROCESS/OPEN has source image + severity: warning + when: + - op: compare + field: object + relation: eq + value: PROCESS + - op: compare + field: action + relation: eq + value: OPEN + checks: + - op: presence + field: image_path + present: true +- id: ecar.legacy-10 + message: FLOW events have network fields + severity: error + when: + - op: compare + field: object + relation: eq + value: FLOW + checks: + - op: presence + field: src_ip + present: true + - op: presence + field: dst_ip + present: true +- id: ecar.legacy-11 + message: SERVICE/CREATE has service name + severity: error + when: + - op: compare + field: object + relation: eq + value: SERVICE + - op: compare + field: action + relation: eq + value: CREATE + checks: + - op: presence + field: service_name + present: true +- id: ecar.legacy-12 + message: USER_SESSION LOGIN has principal + severity: warning + when: + - op: compare + field: object + relation: eq + value: USER_SESSION + - op: compare + field: action + relation: eq + value: LOGIN + checks: + - op: presence + field: principal + present: true +- id: ecar.object-action + message: Unsupported object/action combination + severity: error + when: [] + checks: + - op: combination + field: object + other_field: action + pairs: + - - PROCESS + - CREATE + - - PROCESS + - TERMINATE + - - PROCESS + - OPEN + - - FILE + - CREATE + - - FILE + - OPEN + - - FILE + - CLOSE + - - FILE + - MODIFY + - - FILE + - DELETE + - - FILE + - WRITE + - - FILE + - READ + - - FILE + - RENAME + - - FLOW + - OPEN + - - FLOW + - CLOSE + - - FLOW + - CONNECT + - - FLOW + - ACCEPT + - - FLOW + - SEND + - - FLOW + - RECEIVE + - - REGISTRY + - CREATE + - - REGISTRY + - MODIFY + - - REGISTRY + - DELETE + - - REGISTRY + - READ + - - REGISTRY + - WRITE + - - MODULE + - LOAD + - - MODULE + - UNLOAD + - - THREAD + - CREATE + - - THREAD + - REMOTE_CREATE + - - THREAD + - TERMINATE + - - USER_SESSION + - LOGIN + - - USER_SESSION + - LOGOUT + - - SOCKET + - CREATE + - - SOCKET + - OPEN + - - SOCKET + - CLOSE + - - SOCKET + - CONNECT + - - SOCKET + - ACCEPT + - - SOCKET + - SEND + - - SOCKET + - RECEIVE + - - DRIVER + - LOAD + - - DRIVER + - UNLOAD + - - SERVICE + - CREATE + - - SERVICE + - START + - - SERVICE + - STOP + - - SERVICE + - MODIFY + - - SERVICE + - DELETE diff --git a/src/evidenceforge/config/formats/proxy_access.yaml b/src/evidenceforge/config/formats/proxy_access.yaml index a3389a43b..e852fd50d 100644 --- a/src/evidenceforge/config/formats/proxy_access.yaml +++ b/src/evidenceforge/config/formats/proxy_access.yaml @@ -53,13 +53,15 @@ fields: - name: sc_bytes type: integer required: false - description: "Server to client transaction bytes; CONNECT rows contain only setup response bytes" - + description: Server to client transaction bytes; CONNECT rows contain only setup response bytes + constraints: + min_value: 0 - name: cs_bytes type: integer required: false - description: "Client to server transaction bytes; CONNECT rows contain only setup request bytes" - + description: Client to server transaction bytes; CONNECT rows contain only setup request bytes + constraints: + min_value: 0 - name: byte_scope type: string required: false @@ -68,18 +70,21 @@ fields: - name: tunnel_cs_bytes type: integer required: false - description: "Canonical client-to-proxy tunnel bytes when transport accounting is available" - + description: Canonical client-to-proxy tunnel bytes when transport accounting is available + constraints: + min_value: 0 - name: tunnel_sc_bytes type: integer required: false - description: "Canonical proxy-to-client tunnel bytes when transport accounting is available" - + description: Canonical proxy-to-client tunnel bytes when transport accounting is available + constraints: + min_value: 0 - name: tunnel_duration_ms type: integer required: false - description: "Canonical client-to-proxy tunnel duration in milliseconds when available" - + description: Canonical client-to-proxy tunnel duration in milliseconds when available + constraints: + min_value: 0 - name: tunnel_id type: string required: false @@ -88,13 +93,16 @@ fields: - name: client_src_port type: integer required: false - description: "Client source port for exact proxy-tunnel transport correlation" - + description: Client source port for exact proxy-tunnel transport correlation + constraints: + min_value: 0 + max_value: 65535 - name: time_taken type: integer required: false - description: "Request duration in milliseconds" - + description: Request duration in milliseconds + constraints: + min_value: 0 - name: user_agent type: string required: false diff --git a/src/evidenceforge/config/formats/snort_alert.yaml b/src/evidenceforge/config/formats/snort_alert.yaml index 1363dfb07..2cd974d70 100644 --- a/src/evidenceforge/config/formats/snort_alert.yaml +++ b/src/evidenceforge/config/formats/snort_alert.yaml @@ -83,3 +83,26 @@ output: encoding: utf-8 template: | {{ timestamp.strftime('%m/%d-%H:%M:%S.%f') }} [**] [{{ gid | default(1) }}:{{ sid }}:{{ rev | default(1) }}] {{ message }} [**] [Classification: {{ classification }}] [Priority: {{ priority }}] {{ '{' }}{{ protocol }}{{ '}' }} {% if ':' in src_ip %}[{{ src_ip }}]{% else %}{{ src_ip }}{% endif %}{% if src_port %}:{{ src_port }}{% endif %} -> {% if ':' in dst_ip %}[{{ dst_ip }}]{% else %}{{ dst_ip }}{% endif %}{% if dst_port %}:{{ dst_port }}{% endif %} + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: snort_alert.legacy-1 + message: Alert has valid priority + severity: error + when: [] + checks: + - op: bounds + field: priority + minimum: 1 + maximum: 4 +- id: snort_alert.legacy-2 + message: Alert has source and destination + severity: error + when: [] + checks: + - op: presence + field: src_ip + present: true + - op: presence + field: dst_ip + present: true diff --git a/src/evidenceforge/config/formats/syslog.yaml b/src/evidenceforge/config/formats/syslog.yaml index 018c1d78b..9b27fa4b1 100644 --- a/src/evidenceforge/config/formats/syslog.yaml +++ b/src/evidenceforge/config/formats/syslog.yaml @@ -96,3 +96,23 @@ output: encoding: utf-8 template: | <{{ pri }}>1 {{ timestamp.isoformat().replace('+00:00', 'Z') }} {{ hostname }} {{ app_name }} {{ pid | default('-', true) }} {{ msgid | default('-', true) }} {{ structured_data | default('-', true) }} {{ message }} + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: syslog.legacy-1 + message: Syslog has non-empty message + severity: error + when: [] + checks: + - op: length + field: message + minimum: 1 +- id: syslog.legacy-2 + message: Syslog has hostname + severity: error + when: [] + checks: + - op: compare + field: hostname + relation: ne + value: '' diff --git a/src/evidenceforge/config/formats/web_access.yaml b/src/evidenceforge/config/formats/web_access.yaml index 65fe083c1..2ea1a2435 100644 --- a/src/evidenceforge/config/formats/web_access.yaml +++ b/src/evidenceforge/config/formats/web_access.yaml @@ -32,7 +32,7 @@ fields: required: true description: "HTTP method" constraints: - allowed_values: [GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK] + allowed_values: [GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH, TRACE, CONNECT, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK] - name: path type: string @@ -55,8 +55,9 @@ fields: - name: bytes_sent type: integer required: false - description: "Response size in bytes" - + description: Response size in bytes + constraints: + min_value: 0 - name: referer type: string required: false @@ -73,3 +74,39 @@ output: encoding: utf-8 template: | {{ client_ip }} - {{ username if username else '-' }} [{{ timestamp.strftime('%d/%b/%Y:%H:%M:%S %z') }}] "{{ method }} {{ path }} {{ protocol }}" {{ status_code }} {{ bytes_sent if bytes_sent else '-' }} "{{ referer if referer else '-' }}" "{{ user_agent if user_agent else '-' }}" + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: web_access.legacy-1 + message: Request has valid status code + severity: error + when: [] + checks: + - op: bounds + field: status_code + minimum: 100 + maximum: 599 +- id: web_access.legacy-2 + message: Request has HTTP method + severity: error + when: [] + checks: + - op: membership + field: method + values: + - GET + - POST + - PUT + - DELETE + - HEAD + - OPTIONS + - PATCH + - TRACE + - CONNECT + - PROPFIND + - PROPPATCH + - MKCOL + - COPY + - MOVE + - LOCK + - UNLOCK diff --git a/src/evidenceforge/config/formats/windows_event_security.yaml b/src/evidenceforge/config/formats/windows_event_security.yaml index 7c73f564c..5b6dbda0c 100644 --- a/src/evidenceforge/config/formats/windows_event_security.yaml +++ b/src/evidenceforge/config/formats/windows_event_security.yaml @@ -728,6 +728,7 @@ variants: # EventID 4769: A Kerberos service ticket was requested - name: kerberos_service_ticket event_id: "4769" + event_ids: [4769, 4770] description: "Kerberos service ticket request" fields: - name: TargetUserName @@ -804,12 +805,18 @@ variants: - name: SourcePort type: integer required: true + constraints: + min_value: 0 + max_value: 65535 - name: DestAddress type: string required: true - name: DestPort type: integer required: true + constraints: + min_value: 0 + max_value: 65535 - name: Protocol type: integer required: true @@ -854,7 +861,7 @@ variants: type: integer required: false - name: IpAddress - type: string + type: ip_address required: true - name: IpPort type: integer @@ -947,6 +954,7 @@ variants: # EventID 4728/4729/4732/4733/4756/4757: Group membership changes - name: group_membership_change event_id: "4728" + event_ids: [4728, 4729, 4732, 4733, 4756, 4757] description: "Member added/removed from security group" fields: - name: MemberName @@ -1321,6 +1329,73 @@ variants: - {name: AccessReason, type: string, required: true} # Output template in Windows Event Log XML format + - name: scheduled_task_deleted + event_id: '4699' + description: scheduled task deleted + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: TaskName + type: string + required: true + - name: TaskContent + type: string + required: false + - name: scheduled_task_enabled + event_id: '4700' + description: scheduled task enabled + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: TaskName + type: string + required: true + - name: TaskContent + type: string + required: false + - name: scheduled_task_disabled + event_id: '4701' + description: scheduled task disabled + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: TaskName + type: string + required: true + - name: TaskContent + type: string + required: false + output: format: xml file_extension: ".xml" @@ -1689,12 +1764,227 @@ output: {% endif %} -# Cross-field validators using JSON Logic +# Typed cross-field record validators + +# Typed record contracts; evaluated after scalar validation. validators: - # Network logons (type 3) should have valid IP address (not "-") - - if: - - and: - - "==": [{"var": "EventID"}, 4624] - - "==": [{"var": "LogonType"}, 3] - then: - "!=": [{"var": "IpAddress"}, "-"] +- id: windows_event_security.legacy-1 + message: Network logon (type 3) requires valid IP + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4624 + - op: compare + field: LogonType + relation: eq + value: 3 + checks: + - op: compare + field: IpAddress + relation: ne + value: '-' + - op: compare + field: IpAddress + relation: ne + value: '' + exclude: + - op: compare + field: TargetUserName + relation: eq + value: ANONYMOUS LOGON +- id: windows_event_security.legacy-2 + message: Interactive logon (type 2) uses local workstation + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4624 + - op: compare + field: LogonType + relation: eq + value: 2 + checks: + - op: compare + field: WorkstationName + relation: ne + value: '' +- id: windows_event_security.legacy-3 + message: Process creation has process name + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4688 + checks: + - op: length + field: NewProcessName + minimum: 1 +- id: windows_event_security.legacy-4 + message: Logoff must have a logon type + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4634 + checks: + - op: presence + field: LogonType + present: true +- id: windows_event_security.legacy-5 + message: Logon has valid SID + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4624 + checks: + - op: compare + field: TargetUserSid + relation: ne + value: '' +- id: windows_event_security.legacy-6 + message: Failed logon has status code + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4625 + checks: + - op: presence + field: Status + present: true + - op: length + field: TargetUserName + minimum: 1 +- id: windows_event_security.legacy-7 + message: Special privileges has privilege list + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4672 + checks: + - op: length + field: PrivilegeList + minimum: 1 +- id: windows_event_security.legacy-8 + message: Process termination has process name + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4689 + checks: + - op: length + field: ProcessName + minimum: 1 + - op: presence + field: ProcessId + present: true +- id: windows_event_security.legacy-9 + message: Kerberos TGT has krbtgt service + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4768 + checks: + - op: compare + field: ServiceName + relation: eq + value: krbtgt + - op: compare + field: IpAddress + relation: ne + value: '-' +- id: windows_event_security.legacy-10 + message: Kerberos service ticket has service name + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4769 + checks: + - op: length + field: ServiceName + minimum: 1 + - op: compare + field: IpAddress + relation: ne + value: '-' +- id: windows_event_security.legacy-11 + message: NTLM validation has workstation + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4776 + checks: + - op: length + field: Workstation + minimum: 1 + - op: length + field: TargetUserName + minimum: 1 +- id: windows_event_security.legacy-12 + message: Kerberos preauth failure has status + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4771 + checks: + - op: presence + field: Status + present: true + - op: length + field: TargetUserName + minimum: 1 +- id: windows_event_security.legacy-13 + message: WFP connection has direction + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 5156 + checks: + - op: membership + field: Direction + values: + - '%%14592' + - '%%14593' + - op: presence + field: SourceAddress + present: true + - op: presence + field: DestAddress + present: true +- id: windows_event_security.legacy-14 + message: Explicit creds has target server + severity: warning + when: + - op: compare + field: EventID + relation: eq + value: 4648 + checks: + - op: length + field: TargetServerName + minimum: 1 + - op: length + field: TargetUserName + minimum: 1 diff --git a/src/evidenceforge/config/formats/windows_event_sysmon.yaml b/src/evidenceforge/config/formats/windows_event_sysmon.yaml index c54456104..88268d741 100644 --- a/src/evidenceforge/config/formats/windows_event_sysmon.yaml +++ b/src/evidenceforge/config/formats/windows_event_sysmon.yaml @@ -284,7 +284,7 @@ variants: type: string required: true - name: SourceIp - type: string + type: ip_address required: true - name: SourceHostname type: string @@ -292,6 +292,9 @@ variants: - name: SourcePort type: integer required: true + constraints: + min_value: 0 + max_value: 65535 - name: SourcePortName type: string required: false @@ -299,7 +302,7 @@ variants: type: string required: true - name: DestinationIp - type: string + type: ip_address required: true - name: DestinationHostname type: string @@ -307,6 +310,9 @@ variants: - name: DestinationPort type: integer required: true + constraints: + min_value: 0 + max_value: 65535 - name: DestinationPortName type: string required: false @@ -656,3 +662,38 @@ output: {% endif %} + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: sysmon.source-family + message: IP address must agree with IPv6 flag + severity: error + when: + - op: compare + field: EventID + relation: eq + value: 3 + - op: presence + field: SourceIp + - op: presence + field: SourceIsIpv6 + checks: + - op: address_family + field: SourceIp + other_field: SourceIsIpv6 +- id: sysmon.destination-family + message: IP address must agree with IPv6 flag + severity: error + when: + - op: compare + field: EventID + relation: eq + value: 3 + - op: presence + field: DestinationIp + - op: presence + field: DestinationIsIpv6 + checks: + - op: address_family + field: DestinationIp + other_field: DestinationIsIpv6 diff --git a/src/evidenceforge/config/formats/zeek_conn.yaml b/src/evidenceforge/config/formats/zeek_conn.yaml index 506d1709e..944e1a915 100644 --- a/src/evidenceforge/config/formats/zeek_conn.yaml +++ b/src/evidenceforge/config/formats/zeek_conn.yaml @@ -60,8 +60,9 @@ fields: - name: duration type: float required: false - description: "Connection duration in seconds (unset if not ended)" - + description: Connection duration in seconds (unset if not ended) + constraints: + min_value: 0 - name: orig_bytes type: integer required: false @@ -210,24 +211,61 @@ output: } # Cross-field validators + +# Typed record contracts; evaluated after scalar validation. validators: - # If duration is set, it should be non-negative - - if: - - "!=": [{"var": "duration"}, null] - then: - ">=": [{"var": "duration"}, 0] - - # If service is set, duration should also be set (established connection) - - if: - - "!=": [{"var": "service"}, null] - then: - "!=": [{"var": "duration"}, null] - - # SF state (normal connection) should have duration and bytes - - if: - - "==": [{"var": "conn_state"}, "SF"] - then: - and: - - "!=": [{"var": "duration"}, null] - - "!=": [{"var": "orig_bytes"}, null] - - "!=": [{"var": "resp_bytes"}, null] +- id: zeek_conn.legacy-1 + message: Completed connection (SF) has duration + severity: error + when: + - op: compare + field: conn_state + relation: eq + value: SF + checks: + - op: presence + field: duration + present: true +- id: zeek_conn.legacy-2 + message: Completed connection (SF) has byte counts + severity: error + when: + - op: compare + field: conn_state + relation: eq + value: SF + checks: + - op: presence + field: orig_bytes + present: true + - op: presence + field: resp_bytes + present: true +- id: zeek_conn.legacy-3 + message: Connection has valid protocol + severity: error + when: [] + checks: + - op: membership + field: proto + values: + - tcp + - udp + - icmp +- id: zeek_conn.legacy-4 + message: Completed TCP (SF) cannot have zero duration + severity: warning + when: + - op: compare + field: conn_state + relation: eq + value: SF + - op: compare + field: proto + relation: eq + value: tcp + checks: + - op: compare + field: duration + relation: ne + value: 0 diff --git a/src/evidenceforge/config/formats/zeek_dhcp.yaml b/src/evidenceforge/config/formats/zeek_dhcp.yaml index 4c6266486..e35133148 100644 --- a/src/evidenceforge/config/formats/zeek_dhcp.yaml +++ b/src/evidenceforge/config/formats/zeek_dhcp.yaml @@ -20,8 +20,8 @@ fields: - name: uids type: list required: true - description: "Connection UIDs (JSON array of strings)" - + description: Connection UIDs (JSON array of strings) + item_type: string - name: client_addr type: ip_address required: true @@ -55,18 +55,20 @@ fields: - name: msg_types type: list required: true - description: "DHCP message types (JSON array of strings)" - + description: DHCP message types (JSON array of strings) + item_type: string - name: lease_time type: float required: false - description: "Lease lifetime in seconds" - + description: Lease lifetime in seconds + constraints: + min_value: 0 - name: duration type: float required: false - description: "Transaction duration in seconds" - + description: Transaction duration in seconds + constraints: + min_value: 0 output: format: json file_extension: ".json" diff --git a/src/evidenceforge/config/formats/zeek_dns.yaml b/src/evidenceforge/config/formats/zeek_dns.yaml index cead27e7d..d40015e2b 100644 --- a/src/evidenceforge/config/formats/zeek_dns.yaml +++ b/src/evidenceforge/config/formats/zeek_dns.yaml @@ -53,7 +53,7 @@ fields: - name: trans_id type: integer - required: true + required: false description: "DNS transaction ID" constraints: min_value: 0 @@ -62,11 +62,12 @@ fields: - name: rtt type: float required: false - description: "Round-trip time for the query (seconds)" - + description: Round-trip time for the query (seconds) + constraints: + min_value: 0 - name: query type: string - required: true + required: false description: "Domain name queried" - name: qclass @@ -86,10 +87,8 @@ fields: - name: qtype_name type: string - required: true + required: false description: "Query type name" - constraints: - allowed_values: ["A", "AAAA", "CNAME", "MX", "NIMLOC", "NS", "PTR", "SOA", "SRV", "TXT"] - name: rcode type: integer @@ -98,49 +97,47 @@ fields: - name: rcode_name type: string - required: true + required: false description: "Response code name" - constraints: - allowed_values: ["NOERROR", "NXDOMAIN", "SERVFAIL", "REFUSED", "NOTIMP"] - name: AA type: boolean - required: true + required: false description: "Authoritative Answer flag" - name: TC type: boolean - required: true + required: false description: "Truncation flag" - name: RD type: boolean - required: true + required: false description: "Recursion Desired flag" - name: RA type: boolean - required: true + required: false description: "Recursion Available flag" - name: Z type: integer - required: true + required: false description: "DNS header reserved bits (Z field), typically 0" - name: answers type: list required: false - description: "Answer records (JSON array of strings)" - + description: Answer records (JSON array of strings) + item_type: string - name: TTLs type: list required: false - description: "Answer TTLs (JSON array of floats)" - + description: Answer TTLs (JSON array of floats) + item_type: float - name: rejected type: boolean - required: true + required: false description: "Whether the query was rejected" - name: opcode @@ -192,3 +189,111 @@ output: "opcode": {{ opcode | tojson }}, "opcode_name": {{ opcode_name | tojson }} } + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: zeek_dns.legacy-1 + message: DNS query has non-empty query field + severity: warning + when: [] + checks: + - op: length + field: query + minimum: 1 +- id: zeek_dns.legacy-2 + message: DNS response has rcode + severity: warning + when: [] + checks: + - op: presence + field: rcode_name + present: true +- id: dns.qtype-name + message: qtype and its name must agree + severity: error + when: + - op: presence + field: qtype + - op: presence + field: qtype_name + - op: membership + field: qtype + values: + - 1 + - 28 + - 5 + - 15 + - 2 + - 12 + - 6 + - 33 + - 16 + - 32 + checks: + - op: combination + field: qtype + other_field: qtype_name + pairs: + - - 1 + - A + - - 28 + - AAAA + - - 5 + - CNAME + - - 15 + - MX + - - 2 + - NS + - - 12 + - PTR + - - 6 + - SOA + - - 33 + - SRV + - - 16 + - TXT + - - 32 + - NIMLOC +- id: dns.rcode-name + message: rcode and its name must agree + severity: error + when: + - op: presence + field: rcode + - op: presence + field: rcode_name + - op: membership + field: rcode + values: + - 0 + - 3 + - 2 + - 5 + - 4 + checks: + - op: combination + field: rcode + other_field: rcode_name + pairs: + - - 0 + - NOERROR + - - 3 + - NXDOMAIN + - - 2 + - SERVFAIL + - - 5 + - REFUSED + - - 4 + - NOTIMP +- id: dns.answer-ttls + message: Answers and TTLs must correspond + severity: error + when: + - op: presence + field: answers + - op: presence + field: TTLs + checks: + - op: same_length + field: answers + other_field: TTLs diff --git a/src/evidenceforge/config/formats/zeek_files.yaml b/src/evidenceforge/config/formats/zeek_files.yaml index a69cbdae8..3cd7e1aa7 100644 --- a/src/evidenceforge/config/formats/zeek_files.yaml +++ b/src/evidenceforge/config/formats/zeek_files.yaml @@ -27,18 +27,18 @@ fields: - name: tx_hosts type: list required: true - description: "Hosts that transmitted the file (JSON array of IP strings)" - + description: Hosts that transmitted the file (JSON array of IP strings) + item_type: string - name: rx_hosts type: list required: true - description: "Hosts that received the file (JSON array of IP strings)" - + description: Hosts that received the file (JSON array of IP strings) + item_type: string - name: conn_uids type: list required: true - description: "Connection UIDs that carried the file (JSON array of C-prefix UID strings)" - + description: Connection UIDs that carried the file (JSON array of C-prefix UID strings) + item_type: string - name: source type: string required: true @@ -57,8 +57,8 @@ fields: - name: analyzers type: list required: false - description: "Analyzers that ran on this file (JSON array of strings)" - + description: Analyzers that ran on this file (JSON array of strings) + item_type: string - name: mime_type type: string required: false @@ -67,8 +67,9 @@ fields: - name: duration type: float required: false - description: "Transfer duration in seconds" - + description: Transfer duration in seconds + constraints: + min_value: 0 - name: local_orig type: boolean required: false @@ -82,23 +83,27 @@ fields: - name: seen_bytes type: integer required: true - description: "Bytes observed" - + description: Bytes observed + constraints: + min_value: 0 - name: total_bytes type: integer required: false - description: "Total bytes expected" - + description: Total bytes expected + constraints: + min_value: 0 - name: missing_bytes type: integer required: true - description: "Missing bytes" - + description: Missing bytes + constraints: + min_value: 0 - name: overflow_bytes type: integer required: true - description: "Overflow bytes" - + description: Overflow bytes + constraints: + min_value: 0 - name: timedout type: boolean required: true diff --git a/src/evidenceforge/config/formats/zeek_http.yaml b/src/evidenceforge/config/formats/zeek_http.yaml index f817c5166..5487c3400 100644 --- a/src/evidenceforge/config/formats/zeek_http.yaml +++ b/src/evidenceforge/config/formats/zeek_http.yaml @@ -77,13 +77,15 @@ fields: - name: request_body_len type: integer required: true - description: "Request body length" - + description: Request body length + constraints: + min_value: 0 - name: response_body_len type: integer required: true - description: "Response body length" - + description: Response body length + constraints: + min_value: 0 - name: status_code type: integer required: true @@ -97,8 +99,8 @@ fields: - name: tags type: list required: false - description: "Zeek http.log tags (JSON array of strings)" - + description: Zeek http.log tags (JSON array of strings) + item_type: string - name: referrer type: string required: false @@ -107,33 +109,33 @@ fields: - name: resp_fuids type: list required: false - description: "Response file UIDs (JSON array)" - + description: Response file UIDs (JSON array) + item_type: string - name: orig_fuids type: list required: false - description: "Request file UIDs (JSON array)" - + description: Request file UIDs (JSON array) + item_type: string - name: orig_filenames type: list required: false - description: "Request filenames exposed on the wire (JSON array)" - + description: Request filenames exposed on the wire (JSON array) + item_type: string - name: orig_mime_types type: list required: false - description: "Request MIME types (JSON array)" - + description: Request MIME types (JSON array) + item_type: string - name: resp_filenames type: list required: false - description: "Response filenames exposed on the wire (JSON array)" - + description: Response filenames exposed on the wire (JSON array) + item_type: string - name: resp_mime_types type: list required: false - description: "Response MIME types (JSON array)" - + description: Response MIME types (JSON array) + item_type: string output: format: json file_extension: ".json" @@ -185,3 +187,47 @@ output: "resp_mime_types": {{ resp_mime_types | tojson }} {%- endif %} } + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: zeek_http.legacy-1 + message: HTTP CONNECT must not have response body + severity: error + when: + - op: compare + field: method + relation: eq + value: CONNECT + - op: bounds + field: status_code + minimum: 200 + maximum: 299 + checks: + - op: compare + field: response_body_len + relation: eq + value: 0 +- id: zeek_http.legacy-2 + message: HTTP response has method + severity: error + when: [] + checks: + - op: membership + field: method + values: + - GET + - POST + - PUT + - DELETE + - HEAD + - OPTIONS + - PATCH + - TRACE + - CONNECT + - PROPFIND + - PROPPATCH + - MKCOL + - COPY + - MOVE + - LOCK + - UNLOCK diff --git a/src/evidenceforge/config/formats/zeek_ntp.yaml b/src/evidenceforge/config/formats/zeek_ntp.yaml index 0e2417e30..7eb67133a 100644 --- a/src/evidenceforge/config/formats/zeek_ntp.yaml +++ b/src/evidenceforge/config/formats/zeek_ntp.yaml @@ -107,8 +107,9 @@ fields: - name: num_exts type: integer required: true - description: "Number of extensions" - + description: Number of extensions + constraints: + min_value: 0 output: format: json file_extension: ".json" diff --git a/src/evidenceforge/config/formats/zeek_ocsp.yaml b/src/evidenceforge/config/formats/zeek_ocsp.yaml index 4772b0685..e8030c695 100644 --- a/src/evidenceforge/config/formats/zeek_ocsp.yaml +++ b/src/evidenceforge/config/formats/zeek_ocsp.yaml @@ -85,3 +85,19 @@ output: "revoketime": {{ revoketime | tojson }}{% endif %}{% if revokereason is not none %}, "revokereason": {{ revokereason | tojson }}{% endif %} } + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: zeek_ocsp.interval + message: Validity interval is reversed + severity: warning + when: + - op: presence + field: thisUpdate + - op: presence + field: nextUpdate + checks: + - op: compare + field: thisUpdate + relation: le + other_field: nextUpdate diff --git a/src/evidenceforge/config/formats/zeek_pe.yaml b/src/evidenceforge/config/formats/zeek_pe.yaml index bd6308211..5ab9545f9 100644 --- a/src/evidenceforge/config/formats/zeek_pe.yaml +++ b/src/evidenceforge/config/formats/zeek_pe.yaml @@ -95,8 +95,8 @@ fields: - name: section_names type: list required: false - description: "PE section names (JSON array of strings)" - + description: PE section names (JSON array of strings) + item_type: string output: format: json file_extension: ".json" diff --git a/src/evidenceforge/config/formats/zeek_smb_files.yaml b/src/evidenceforge/config/formats/zeek_smb_files.yaml index 4c7da3ab3..594c6159e 100644 --- a/src/evidenceforge/config/formats/zeek_smb_files.yaml +++ b/src/evidenceforge/config/formats/zeek_smb_files.yaml @@ -13,7 +13,7 @@ fields: - {name: action, type: string, required: true} - {name: path, type: string, required: true} - {name: name, type: string, required: true} - - {name: size, type: integer, required: false} + - {name: size, type: integer, required: false, constraints: {min_value: 0}} - {name: prev_name, type: string, required: false} - {name: fuid, type: string, required: false} output: @@ -41,3 +41,18 @@ output: "fuid": {{ fuid | tojson }} {%- endif %} } + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: smb.rename-source + message: Rename requires previous name + severity: error + when: + - op: compare + field: action + relation: eq + value: SMB::FILE_RENAME + checks: + - op: length + field: prev_name + minimum: 1 diff --git a/src/evidenceforge/config/formats/zeek_smtp.yaml b/src/evidenceforge/config/formats/zeek_smtp.yaml index 8ffc1362d..512d07f80 100644 --- a/src/evidenceforge/config/formats/zeek_smtp.yaml +++ b/src/evidenceforge/config/formats/zeek_smtp.yaml @@ -47,7 +47,8 @@ fields: - name: rcptto type: list required: true - description: "Envelope RCPT TO values" + description: Envelope RCPT TO values + item_type: string - name: last_reply type: string required: true @@ -55,7 +56,8 @@ fields: - name: path type: list required: true - description: "Zeek SMTP path vector" + description: Zeek SMTP path vector + item_type: string - name: tls type: boolean required: true @@ -71,11 +73,13 @@ fields: - name: to type: list required: false - description: "Visible To header recipients when visible" + description: Visible To header recipients when visible + item_type: string - name: cc type: list required: false - description: "Visible Cc header recipients when visible" + description: Visible Cc header recipients when visible + item_type: string - name: msg_id type: string required: false @@ -91,8 +95,8 @@ fields: - name: fuids type: list required: false - description: "File UIDs for visible message parts/attachments" - + description: File UIDs for visible message parts/attachments + item_type: string output: format: json file_extension: ".json" diff --git a/src/evidenceforge/config/formats/zeek_ssl.yaml b/src/evidenceforge/config/formats/zeek_ssl.yaml index 9a9d0ed0b..1adc294d1 100644 --- a/src/evidenceforge/config/formats/zeek_ssl.yaml +++ b/src/evidenceforge/config/formats/zeek_ssl.yaml @@ -77,8 +77,8 @@ fields: - name: cert_chain_fuids type: list required: false - description: "Zeek file UIDs for certificates observed in the server certificate chain" - + description: Zeek file UIDs for certificates observed in the server certificate chain + item_type: string output: format: json file_extension: ".json" diff --git a/src/evidenceforge/config/formats/zeek_x509.yaml b/src/evidenceforge/config/formats/zeek_x509.yaml index 7a1389aff..78ce21546 100644 --- a/src/evidenceforge/config/formats/zeek_x509.yaml +++ b/src/evidenceforge/config/formats/zeek_x509.yaml @@ -87,8 +87,8 @@ fields: - name: san.dns type: list required: false - description: "DNS subject alternative names" - + description: DNS subject alternative names + item_type: string - name: basic_constraints.ca type: boolean required: false @@ -135,3 +135,19 @@ output: "host_cert": {{ host_cert | tojson }}, "client_cert": {{ client_cert | tojson }} } + +# Typed record contracts; evaluated after scalar validation. +validators: +- id: zeek_x509.interval + message: Validity interval is reversed + severity: warning + when: + - op: presence + field: certificate.not_valid_before + - op: presence + field: certificate.not_valid_after + checks: + - op: compare + field: certificate.not_valid_before + relation: le + other_field: certificate.not_valid_after diff --git a/src/evidenceforge/config/generation_behavior.yaml b/src/evidenceforge/config/generation_behavior.yaml index d057bcd02..d2406d75b 100644 --- a/src/evidenceforge/config/generation_behavior.yaml +++ b/src/evidenceforge/config/generation_behavior.yaml @@ -1,7 +1,7 @@ schema_version: "1.0" -current_revision: 89 +current_revision: 95 history_start_revision: 1 -behavior_surface_sha256: 120dd81053c2116d467a2637f2ccc52e0f155ce4b546a114acde26eee4e9705c +behavior_surface_sha256: 8257de43a05cc766305c694351e1159864335f1cd577028a556cc6f344b5ed5c changes: - revision: 1 id: initial-generation-behavior-contract @@ -798,3 +798,54 @@ changes: - host-filesystem formats: [] summary: Publish Windows checkpoint dependencies and recovery indexes through native write-through handles without changing POSIX operations or evidence semantics + - revision: 90 + id: typed-record-validation + impact: none + domains: + - record-validation + formats: [] + summary: Replace record validation contracts without changing rendered evidence. + - revision: 91 + id: evaluator-source-routing + impact: none + domains: + - validation-preflight + formats: [] + summary: Declares parser validation ownership and explicit evaluation failures without changing rendered evidence. + - revision: 92 + id: legacy-validation-snapshot-decoding + impact: none + domains: + - validation-preflight + formats: [] + summary: Decodes recognized legacy validation metadata for compatible checkpoint hydration without changing rendering definitions. + - revision: 93 + id: snare-canonical-field-preservation + impact: localized + domains: + - source-native-projection + formats: + - windows_event_security + - windows_event_sysmon + summary: Preserve canonical Windows fields and repair SOF-ELK Snare aliases; XML and non-Snare evidence are unchanged. + - revision: 94 + id: failed-logon-requester-identity + impact: localized + domains: + - authentication + - requester-identity + formats: + - ecar + - syslog + - windows_event_security + summary: Preserve failed-logon requester identity independently from the authentication target and domain controller. + - revision: 95 + id: canonical-host-text-newlines + impact: localized + domains: + - checkpoint-resume + - source-native-projection + formats: + - proxy_access + - web_access + summary: Use canonical LF framing for ordinary host text output so Windows checkpoint resume matches uninterrupted generation. diff --git a/src/evidenceforge/config/projections/windows_snare.yaml b/src/evidenceforge/config/projections/windows_snare.yaml new file mode 100644 index 000000000..44a48d72c --- /dev/null +++ b/src/evidenceforge/config/projections/windows_snare.yaml @@ -0,0 +1,414 @@ +# Developer-owned Snare projections; identity labels always share one scope. +version: 1 +events: +- source: windows_event_security + event_id: 4624 + variant: logon + aliases: + Process ID: ProcessId + SourceIp: IpAddress + SourcePort: IpPort + Image: ProcessName + Security ID: TargetUserSid + Account Name: TargetUserName + Account Domain: TargetDomainName + Logon ID: TargetLogonId + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4634 + variant: logoff + aliases: + Security ID: TargetUserSid + Account Name: TargetUserName + Account Domain: TargetDomainName + Logon ID: TargetLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4778 + variant: rdp_session_reconnect + aliases: + SourceIp: ClientAddress + SourcePort: ClientPort + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4779 + variant: rdp_session_disconnect + aliases: + SourceIp: ClientAddress + SourcePort: ClientPort + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4688 + variant: process_creation + aliases: + New Process ID: NewProcessId + New Process Name: NewProcessName + Creator Process ID: ProcessId + Creator Process Name: ParentProcessName + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4625 + variant: failed_logon + aliases: + Process ID: ProcessId + SourceIp: IpAddress + SourcePort: IpPort + Image: ProcessName + Security ID: TargetUserSid + Account Name: TargetUserName + Account Domain: TargetDomainName + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4672 + variant: special_privileges + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4800 + variant: workstation_locked + aliases: + Security ID: TargetUserSid + Account Name: TargetUserName + Account Domain: TargetDomainName + Logon ID: TargetLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4801 + variant: workstation_unlocked + aliases: + Security ID: TargetUserSid + Account Name: TargetUserName + Account Domain: TargetDomainName + Logon ID: TargetLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4689 + variant: process_termination + aliases: + Process ID: ProcessId + Exit Status: Status + Image: ProcessName + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4648 + variant: explicit_credentials + aliases: + Process ID: ProcessId + SourceIp: IpAddress + SourcePort: IpPort + Image: ProcessName + Account Name: TargetUserName + Account Domain: TargetDomainName + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4768 + variant: kerberos_tgt + aliases: + SourceIp: IpAddress + SourcePort: IpPort + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4769 + variant: kerberos_service_ticket + aliases: + SourceIp: IpAddress + SourcePort: IpPort + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4776 + variant: ntlm_validation + aliases: + Account Name: TargetUserName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 5156 + variant: wfp_connection + aliases: + SourceIp: SourceAddress + DestinationIp: DestAddress + DestinationPort: DestPort + ProcessId: ProcessID + Image: Application + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4771 + variant: kerberos_preauth_failed + aliases: + SourceIp: IpAddress + SourcePort: IpPort + Account Name: TargetUserName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 1102 + variant: log_cleared + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4697 + variant: service_installed + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4698 + variant: scheduled_task + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4728 + variant: group_membership_change + aliases: + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4720 + variant: account_created + aliases: + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4723 + variant: password_change + aliases: + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4724 + variant: password_reset + aliases: + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4726 + variant: account_deleted + aliases: + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4738 + variant: account_changed + aliases: + Account Name: TargetUserName + Account Domain: TargetDomainName + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4656 + variant: object_handle_requested + aliases: + Process ID: ProcessId + Image: ProcessName + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4658 + variant: object_handle_closed + aliases: + Process ID: ProcessId + Image: ProcessName + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4663 + variant: object_access + aliases: + Process ID: ProcessId + Image: ProcessName + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + decimal_aliases: + ProcessId: ProcessId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 5140 + variant: network_share_access + aliases: + SourceIp: IpAddress + SourcePort: IpPort + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 5145 + variant: network_share_access_check + aliases: + SourceIp: IpAddress + SourcePort: IpPort + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4699 + variant: scheduled_task_deleted + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4700 + variant: scheduled_task_enabled + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_security + event_id: 4701 + variant: scheduled_task_disabled + aliases: + Security ID: SubjectUserSid + Account Name: SubjectUserName + Account Domain: SubjectDomainName + Logon ID: SubjectLogonId + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 1 + variant: sysmon_process_create + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 5 + variant: sysmon_process_terminate + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 8 + variant: sysmon_create_remote_thread + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 10 + variant: sysmon_process_access + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 3 + variant: sysmon_network_connect + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 7 + variant: sysmon_image_loaded + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 11 + variant: sysmon_file_create + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 12 + variant: sysmon_registry_create_delete + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 13 + variant: sysmon_registry_set_value + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID +- source: windows_event_sysmon + event_id: 22 + variant: sysmon_dns_query + aliases: {} + fallback_aliases: + Process ID: ExecutionProcessID diff --git a/src/evidenceforge/config/provider.py b/src/evidenceforge/config/provider.py index 267d71336..669abde6b 100644 --- a/src/evidenceforge/config/provider.py +++ b/src/evidenceforge/config/provider.py @@ -135,6 +135,7 @@ def owned_by_current_thread(self) -> bool: ), ("evidenceforge.generation.storage_world", "_load_catalog_config"), ("evidenceforge.evaluation.thresholds", "load_thresholds"), + ("evidenceforge.formats.snare", "load_snare_projections"), ) _TIMING_PROFILE_MODULE_NAME = "evidenceforge.generation.activity.timing_profiles" _TIMING_PROFILE_CACHE_SLOT = "_CACHED_TIMING_PROFILES" @@ -258,7 +259,7 @@ def _make_derived_runtime_cache_registry() -> tuple[ Callable[[str, str, dict[str, Any], Any], None], Callable[[], tuple[_DerivedRuntimeCacheAnchor, ...]], ]: - """Build immutable per-owner identities for the three audited LRU caches.""" + """Build immutable per-owner identities for the audited LRU caches.""" registration_lock = threading.Lock() registered: dict[tuple[str, str], _DerivedRuntimeCacheAnchor] = {} diff --git a/src/evidenceforge/evaluation/context.py b/src/evidenceforge/evaluation/context.py index f37b32947..e8699b83b 100644 --- a/src/evidenceforge/evaluation/context.py +++ b/src/evidenceforge/evaluation/context.py @@ -5,7 +5,7 @@ from __future__ import annotations -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import TYPE_CHECKING from evidenceforge.events.ground_truth import GroundTruthDocument @@ -35,3 +35,6 @@ class EvaluationContext: # ARTIFACTS_MANIFEST.json. email_ground_truth: dict[str, dict] | None = None effective_config: EffectiveConfig | None = None + # Parseability owns this run-local exclusion set. Records remain in report + # counts and exact acceptance gates, but cannot enter typed cross-source indexes. + malformed_record_ids: set[int] = field(default_factory=set, compare=False) diff --git a/src/evidenceforge/evaluation/engine.py b/src/evidenceforge/evaluation/engine.py index 2fe7c04e6..6eb7c8844 100644 --- a/src/evidenceforge/evaluation/engine.py +++ b/src/evidenceforge/evaluation/engine.py @@ -50,7 +50,11 @@ from evidenceforge.evaluation.thresholds import EvalThresholds, load_thresholds from evidenceforge.events.ground_truth import load_ground_truth_document from evidenceforge.events.observation_manifest import load_observation_manifest -from evidenceforge.models.exceptions import EvaluationLimitError +from evidenceforge.models.exceptions import ( + EvaluationError, + EvaluationLimitError, + EvidenceForgeError, +) from evidenceforge.models.scenario import Scenario from evidenceforge.output_targets import read_output_target_marker @@ -422,10 +426,15 @@ def run(self) -> QualityReport: effective_config=self.effective_config, ) + from evidenceforge.evaluation.validation_routes import validate_route_inventory + + validate_route_inventory() + # 2. Run each available pillar scorer total_pillars = len(DIMENSION_SCORERS) self._progress("phase_start", {"phase": "scoring", "total_dimensions": total_pillars}) pillars: list[PillarScore] = [] + scoring_records = records for i, scorer in enumerate(DIMENSION_SCORERS, 1): self._progress( "dimension_start", @@ -440,21 +449,28 @@ def run(self) -> QualityReport: pillar_score: PillarScore try: pillar_score = scorer.score( - records, + scoring_records, self.scenario, context=context, progress=self._progress, ) + if isinstance(scorer, ParseabilityScorer) and context.malformed_record_ids: + scoring_records = { + source: [r for r in items if id(r) not in context.malformed_record_ids] + for source, items in records.items() + } pillars.append(pillar_score) - except Exception: - logger.exception(f"Pillar {scorer.number} scoring failed") - pillar_score = PillarScore( - number=scorer.number, - name=scorer.name, - weight=scorer.weight, - score=None, - ) - pillars.append(pillar_score) + except ( + OSError, + ValueError, + TypeError, + KeyError, + RuntimeError, + EvidenceForgeError, + ) as exc: + raise EvaluationError( + f"Pillar {scorer.number} ({scorer.name}) failed: {exc}" + ) from exc self._progress( "dimension_done", { diff --git a/src/evidenceforge/evaluation/models.py b/src/evidenceforge/evaluation/models.py index 59a1b07ad..9c5cc0724 100644 --- a/src/evidenceforge/evaluation/models.py +++ b/src/evidenceforge/evaluation/models.py @@ -11,6 +11,8 @@ from pydantic import BaseModel, Field +from evidenceforge.formats.rules import Finding + class SubScore(BaseModel): """A sub-score within a quality pillar.""" @@ -24,6 +26,9 @@ class SubScore(BaseModel): adjusted: bool = False """True when the score excludes expected observation-profile gaps.""" details: str = "" + sample_findings: list[Finding] = Field(default_factory=list) + unavailable_check_count: int = 0 + sample_unavailable_findings: list[Finding] = Field(default_factory=list) sample_failures: list[str] = Field(default_factory=list) failure_summary: dict[str, dict[str, int]] = Field(default_factory=dict) """Aggregated failure counts by format and category. diff --git a/src/evidenceforge/evaluation/parsers/__init__.py b/src/evidenceforge/evaluation/parsers/__init__.py index 7d18e049b..f50e45ef2 100644 --- a/src/evidenceforge/evaluation/parsers/__init__.py +++ b/src/evidenceforge/evaluation/parsers/__init__.py @@ -79,6 +79,8 @@ class ParsedRecord(BaseModel): line_number: int | None = None source_host: str | None = None source_instance: str | None = None + representation: str | None = None + source_fields: list[tuple[str, str]] = Field(default_factory=list) class LogParser(ABC): @@ -107,6 +109,8 @@ def can_parse(self, path: Path) -> bool: def register_parser(cls: type[LogParser]) -> type[LogParser]: """Decorator to register a parser class.""" + if cls.format_name in _PARSER_CLASSES: + raise ValueError(f"Duplicate parser registration: {cls.format_name}") _PARSER_CLASSES[cls.format_name] = cls return cls diff --git a/src/evidenceforge/evaluation/parsers/apache_json.py b/src/evidenceforge/evaluation/parsers/apache_json.py new file mode 100644 index 000000000..9ac094833 --- /dev/null +++ b/src/evidenceforge/evaluation/parsers/apache_json.py @@ -0,0 +1,91 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Normalize the supported Splunk Apache JSON projection without inventing HTTP facts.""" + +from datetime import datetime + +from . import ParsedRecord +from .json_record import decode_record + + +def parse_apache_json( + raw: str, line_number: int, source: str, hostname: str | None +) -> ParsedRecord: + """Parse one web/proxy JSON record, retaining malformed input for exact acceptance.""" + fields: dict = {} + errors: list[str] = [] + timestamp = None + try: + document = decode_record(raw) + for key in ("bytes_in", "bytes_out", "dest_port", "response_time_microseconds"): + if key not in document: + continue + value = document[key] + if isinstance(value, bool) or not isinstance(value, int) or value < 0: + errors.append(f"Apache JSON {key} must be a nonnegative integer") + elif key == "dest_port" and value > 65535: + errors.append("Apache JSON dest_port exceeds 65535") + aliases = { + "client": "client_ip", + "user": "username", + "http_method": "method", + "http_version": "protocol", + "status": "status_code", + "http_user_agent": "user_agent", + "http_referrer": "referrer" if source == "proxy_access" else "referer", + "bytes_out": "sc_bytes" if source == "proxy_access" else "bytes_sent", + } + if source == "proxy_access": + aliases.update(server="host", bytes_in="cs_bytes") + for key, value in document.items(): + canonical = aliases.get(key, key) + if canonical in fields and fields[canonical] != value: + errors.append(f"Conflicting JSON field: {canonical}") + fields[canonical] = value + # Apache's dash means no authenticated user, as in the text projections. + # Normalize after merging so conflicting aliases still remain parse failures. + if fields.get("username") == "-": + fields.pop("username") + ts = document.get("timestamp") + if not isinstance(ts, str): + errors.append("Apache JSON timestamp must be an ISO timestamp string") + else: + try: + timestamp = datetime.fromisoformat(ts.replace("Z", "+00:00")) + except ValueError: + errors.append("Invalid Apache JSON timestamp") + path = document.get("uri_path") + query = document.get("uri_query", "") + if not isinstance(path, str) or not isinstance(query, str): + errors.append("Apache JSON uri_path and uri_query must be strings") + else: + target = path + ("?" + query if query else "") + if source == "proxy_access" and fields.get("method") == "CONNECT": + host, port = fields.get("host"), document.get("dest_port") + if ( + not isinstance(host, str) + or isinstance(port, bool) + or not isinstance(port, int) + or not 0 <= port <= 65535 + ): + errors.append( + "CONNECT JSON requires a string server and integer destination port" + ) + else: + target = f"[{host}]:{port}" if ":" in host else f"{host}:{port}" + key = "url" if source == "proxy_access" else "path" + if key in fields and fields[key] != target: + errors.append(f"Conflicting JSON field: {key}") + fields[key] = target + except (ValueError, TypeError) as exc: + errors.append(f"Apache JSON parse error: {exc}") + return ParsedRecord( + source_format=source, + raw=raw, + fields=fields, + timestamp=timestamp, + parse_errors=errors, + line_number=line_number, + source_host=hostname, + ) diff --git a/src/evidenceforge/evaluation/parsers/bash_history.py b/src/evidenceforge/evaluation/parsers/bash_history.py index 287a9e397..f8452fec2 100644 --- a/src/evidenceforge/evaluation/parsers/bash_history.py +++ b/src/evidenceforge/evaluation/parsers/bash_history.py @@ -66,7 +66,7 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: line = raw_line.rstrip("\n") ts_match = TIMESTAMP_PATTERN.match(line) if ts_match: - epoch = int(ts_match.group(1)) + epoch: str | int = ts_match.group(1) command = "" try: _command_line_number, raw_command = next(lines) @@ -78,8 +78,9 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: timestamp = None errors: list[str] = [] try: + epoch = int(epoch) timestamp = datetime.fromtimestamp(epoch, tz=UTC) - except (ValueError, OSError): + except (ValueError, OSError, OverflowError): errors.append(f"Invalid epoch: {epoch}") raw = f"#{epoch}\n{command}" if command else f"#{epoch}" diff --git a/src/evidenceforge/evaluation/parsers/ecar.py b/src/evidenceforge/evaluation/parsers/ecar.py index 389c2572c..272bfe3b4 100644 --- a/src/evidenceforge/evaluation/parsers/ecar.py +++ b/src/evidenceforge/evaluation/parsers/ecar.py @@ -22,13 +22,13 @@ """Parser for eCAR (NDJSON) files.""" -import json from collections.abc import Iterator from datetime import UTC, datetime from pathlib import Path from typing import Any from . import LogParser, ParsedRecord, iter_bounded_text_lines, register_parser +from .json_record import decode_record @register_parser @@ -51,10 +51,15 @@ def _parse_line(self, raw: str, line_num: int) -> ParsedRecord: timestamp = None try: - data = json.loads(raw) + data = decode_record(raw) # Flatten properties into top-level fields properties = data.pop("properties", {}) + if not isinstance(properties, dict): + raise ValueError("Expected object for eCAR properties") + conflicts = data.keys() & properties.keys() + if conflicts: + raise ValueError(f"Duplicate eCAR properties: {sorted(conflicts)}") fields = {**data, **properties} # Normalize "-" sentinel to absent for IP fields @@ -67,10 +72,10 @@ def _parse_line(self, raw: str, line_num: int) -> ParsedRecord: if ts_ms is not None: try: timestamp = datetime.fromtimestamp(int(ts_ms) / 1000.0, tz=UTC) - except (ValueError, TypeError, OSError): + except (ValueError, TypeError, OSError, OverflowError): errors.append(f"Invalid timestamp_ms: {ts_ms}") - except json.JSONDecodeError as e: + except (ValueError, TypeError) as e: errors.append(f"JSON parse error: {e}") return ParsedRecord( diff --git a/src/evidenceforge/evaluation/parsers/email_artifacts.py b/src/evidenceforge/evaluation/parsers/email_artifacts.py index eafac36ac..688d8f3e0 100644 --- a/src/evidenceforge/evaluation/parsers/email_artifacts.py +++ b/src/evidenceforge/evaluation/parsers/email_artifacts.py @@ -34,7 +34,7 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: ) try: payload = json.loads(path.read_text(encoding="utf-8")) - except (OSError, json.JSONDecodeError) as exc: + except (OSError, UnicodeError, json.JSONDecodeError) as exc: yield ParsedRecord( source_format=self.format_name, raw="", @@ -42,6 +42,14 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: parse_errors=[str(exc)], ) return + if not isinstance(payload, dict): + yield ParsedRecord( + source_format=self.format_name, + raw=json.dumps(payload), + fields={}, + parse_errors=["Artifact manifest must be an object"], + ) + return email_section = payload.get("email", {}) if not isinstance(email_section, dict): yield ParsedRecord( @@ -71,13 +79,29 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: ) continue timestamp = _parse_email_artifact_date(message.get("date")) - yield ParsedRecord( + record = ParsedRecord( source_format=self.format_name, raw=json.dumps(message, sort_keys=True), fields=message, timestamp=timestamp, + parse_errors=( + ["Email artifact date must be a valid RFC email date"] + if message.get("date") not in (None, "") and timestamp is None + else [] + ), line_number=index, ) + from evidenceforge.evaluation.validation_routes import validate_email_artifact + + record.parse_errors.extend( + f"{'.'.join(finding.fields)}: {finding.message}" + for finding in validate_email_artifact(record) + ) + if record.parse_errors: + # Preserve the raw record and failure count, but do not feed malformed values + # into specialized cross-source indexes (for example an unhashable Message-ID). + record.fields = {} + yield record def _parse_email_artifact_date(value: object) -> datetime | None: diff --git a/src/evidenceforge/evaluation/parsers/json_record.py b/src/evidenceforge/evaluation/parsers/json_record.py new file mode 100644 index 000000000..989fd2c4d --- /dev/null +++ b/src/evidenceforge/evaluation/parsers/json_record.py @@ -0,0 +1,28 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Strict JSON object decoding shared by record parsers.""" + +import json +from typing import Any + + +def _object(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + for name, value in pairs: + if name in result: + raise ValueError(f"Duplicate JSON field: {name}") + result[name] = value + return result + + +def _constant(value: str) -> None: + raise ValueError(f"Nonfinite JSON number: {value}") + + +def decode_record(raw: str) -> dict[str, Any]: + """Decode a finite JSON object without silently replacing duplicate keys.""" + value = json.loads(raw, object_pairs_hook=_object, parse_constant=_constant) + if not isinstance(value, dict): + raise ValueError("Expected JSON object") + return value diff --git a/src/evidenceforge/evaluation/parsers/proxy.py b/src/evidenceforge/evaluation/parsers/proxy.py index 30a9ae845..fdf537117 100644 --- a/src/evidenceforge/evaluation/parsers/proxy.py +++ b/src/evidenceforge/evaluation/parsers/proxy.py @@ -114,6 +114,11 @@ def _source_host_from_path(path: Path) -> str | None: return parent.name def _parse_line(self, line: str, line_number: int, hostname: str | None = None) -> ParsedRecord: + if line.lstrip().startswith(("{", "[")): + from .apache_json import parse_apache_json + + return parse_apache_json(line, line_number, self.format_name, hostname) + fields: dict = {} errors: list[str] = [] timestamp = None diff --git a/src/evidenceforge/evaluation/parsers/web.py b/src/evidenceforge/evaluation/parsers/web.py index 8f20213ad..8abec8bf7 100644 --- a/src/evidenceforge/evaluation/parsers/web.py +++ b/src/evidenceforge/evaluation/parsers/web.py @@ -69,6 +69,11 @@ def _source_host_from_path(path: Path) -> str | None: return parent.name def _parse_line(self, raw: str, line_num: int, hostname: str | None = None) -> ParsedRecord: + if raw.lstrip().startswith(("{", "[")): + from .apache_json import parse_apache_json + + return parse_apache_json(raw, line_num, self.format_name, hostname) + fields: dict = {} errors: list[str] = [] timestamp = None diff --git a/src/evidenceforge/evaluation/parsers/windows.py b/src/evidenceforge/evaluation/parsers/windows.py index 67b5b5442..bf889fb6b 100644 --- a/src/evidenceforge/evaluation/parsers/windows.py +++ b/src/evidenceforge/evaluation/parsers/windows.py @@ -28,6 +28,10 @@ from datetime import UTC, datetime from pathlib import Path +from pydantic import ValidationError + +from evidenceforge.formats.loader import load_format +from evidenceforge.formats.snare import SnareEnvelope, load_snare_projections from evidenceforge.generation.emitters.windows_snare import ( WINDOWS_SECURITY_SNARE_FILENAME, WINDOWS_SYSMON_SNARE_FILENAME, @@ -66,6 +70,7 @@ class _WindowsXmlParser(LogParser): { "LogonType", "IpPort", + "ClientPort", "KeyLength", "PreAuthType", "NetworkPort", @@ -87,6 +92,7 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: in_event = False event_lines: list[str] = [] event_bytes = 0 + wrapper_open = False for _line_number, line in iter_bounded_text_lines(path): if not in_event and EVENT_START_PATTERN.search(line): @@ -101,6 +107,29 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: event_bytes = 0 continue + if not in_event: + text = line.strip() + if re.fullmatch(r"]*)?>", text) and not wrapper_open: + try: + ET.fromstring(text + "") + except ET.ParseError: + pass # Report the malformed wrapper below. + else: + wrapper_open = True + continue + if text == "" and wrapper_open: + wrapper_open = False + continue + if text and not re.fullmatch(r"(?:<\?xml[^>]*\?>|)", text): + event_index += 1 + yield ParsedRecord( + source_format=self.format_name, + representation="windows_xml", + raw=line, + parse_errors=["Unexpected content outside Windows Event"], + line_number=event_index, + ) + if in_event: event_bytes += len(line.encode("utf-8")) if event_bytes > MAX_EVALUATION_RECORD_BYTES: @@ -115,6 +144,23 @@ def parse_file(self, path: Path) -> Iterator[ParsedRecord]: event_lines = [] event_bytes = 0 + if in_event: + yield ParsedRecord( + source_format=self.format_name, + representation="windows_xml", + raw="".join(event_lines), + parse_errors=["Incomplete Windows Event at end of input"], + line_number=event_index + 1, + ) + elif wrapper_open: + yield ParsedRecord( + source_format=self.format_name, + representation="windows_xml", + raw="", + parse_errors=["Incomplete Windows Events wrapper at end of input"], + line_number=event_index + 1, + ) + def _parse_event(self, raw: str, index: int) -> ParsedRecord: fields: dict = {} errors: list[str] = [] @@ -174,6 +220,8 @@ def _parse_event(self, raw: str, index: int) -> ParsedRecord: name = data_el.get("Name", "") value = data_el.text or "" if name: + if name in fields: + raise ValueError(f"Duplicate Windows field: {name}") fields[name] = self._coerce_event_data_field(name, value) # UserData fields (1102 LogFileCleared and similar) @@ -186,13 +234,16 @@ def _parse_event(self, raw: str, index: int) -> ParsedRecord: # Strip namespace from tag name tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag if child.text: + if tag in fields: + raise ValueError(f"Duplicate Windows field: {tag}") fields[tag] = child.text - except ET.ParseError as e: + except (ET.ParseError, ValueError, OverflowError) as e: errors.append(f"XML parse error: {e}") return ParsedRecord( source_format=self.format_name, + representation="windows_xml", raw=raw, fields=fields, timestamp=timestamp, @@ -205,8 +256,10 @@ def _coerce_event_data_field(self, name: str, value: str) -> str | int: if name in self._INTEGER_EVENT_DATA_FIELDS: try: return int(value) - except ValueError: - return value + except ValueError as exc: + if name in {"IpPort", "NetworkPort"} and value == "-": + return value + raise ValueError(f"Invalid numeric Windows field {name}: {value!r}") from exc return value @@ -248,6 +301,7 @@ def _parse_snare_line( errors: list[str] = [] timestamp = None source_host = None + source_fields: list[tuple[str, str]] = [] match = SNARE_SYSLOG_PATTERN.match(raw) if match is None: @@ -309,7 +363,7 @@ def _parse_snare_line( } ) for key, value, converter in ( - ("EventRecordID", event_record_id, int), + ("SnareCounter", event_record_id, int), ("EventID", event_id, int), ("Criticality", criticality, int), ): @@ -318,12 +372,109 @@ def _parse_snare_line( except ValueError: fields[key] = value errors.append(f"Invalid integer field {key}: {value}") - fields.update( - { - name: self._coerce_event_data_field(name, value) - for name, value in _parse_expanded_snare_fields(full_data).items() - } + if computer != _computer_repeat or computer != source_host: + errors.append("Conflicting Snare computer names") + try: + native_time = datetime.strptime(snare_time, "%a %b %d %H:%M:%S %Y").replace( + tzinfo=UTC + ) + if native_time.strftime("%b %d %H:%M:%S").split() != groups["timestamp"].split(): + errors.append("Conflicting Snare timestamps") + timestamp = native_time + fields["TimeCreated"] = timestamp.isoformat() + except ValueError: + errors.append("Invalid Snare system timestamp") + if fields.get("Criticality") not in range(5): + errors.append("Snare criticality must be 0-4") + try: + SnareEnvelope( + event_id=fields.get("EventID"), + counter=fields.get("SnareCounter"), + criticality=fields.get("Criticality"), + computer=computer, + provider=provider, + channel=channel, + timestamp=timestamp, + logtype=logtype, + ) + except ValidationError as exc: + errors.extend( + f"Snare envelope {error['loc']}: {error['msg']}" for error in exc.errors() + ) + source_fields = _snare_field_occurrences(full_data) + modern = ("ProjectionVersion", "1") in source_fields + if any(name == "ProjectionVersion" and value != "1" for name, value in source_fields): + errors.append("Unsupported Snare ProjectionVersion") + projection = None + if isinstance(fields.get("EventID"), int): + projection = next( + ( + p + for p in load_snare_projections().events + if p.source == self.format_name and p.event_id == fields["EventID"] + ), + None, + ) + if projection is None: + errors.append(f"Unsupported Snare EventID: {fields['EventID']}") + aliases = { + _snare_field_name(label): name + for label, name in (projection.aliases.items() if projection and modern else []) + } + if modern and projection: + present = {name for name, _ in source_fields} + for label, fallback in projection.fallback_aliases.items(): + normalized_label = _snare_field_name(label) + primary = aliases.get(normalized_label) + if primary is None or primary not in present: + aliases[normalized_label] = fallback + if not modern and self.format_name == "windows_event_security": + aliases.update( + SourceIp="SourceAddress", + DestinationIp="DestAddress", + DestinationPort="DestPort", + ) + definitions = load_format(self.format_name).validation_fields( + projection.variant if projection else None ) + for name, value in source_fields: + if name == "ProjectionVersion": + fields[name] = value + continue + name = aliases.get(name, name) + if name not in definitions: + continue # Unscoped historical labels remain in source_fields. + try: + field_type = definitions[name].type.value + if ( + modern + and projection + and name in projection.decimal_aliases.values() + and not value.lower().startswith("0x") + ): + value = hex(int(value)) + + converted = self._coerce_event_data_field(name, value) + if field_type == "integer" and name not in self._INTEGER_EVENT_DATA_FIELDS: + converted = int(value) + + if name == "TimeCreated": + precise = datetime.fromisoformat(value.replace("Z", "+00:00")) + if precise.replace(microsecond=0) != timestamp: + raise ValueError("Conflicting Snare field: TimeCreated") + timestamp = precise + fields[name] = precise.isoformat() + continue + equivalent_hex = ( + field_type == "hex_string" + and name in fields + and int(fields[name], 16) == int(converted, 16) + ) + if name in fields and fields[name] != converted and not equivalent_hex: + raise ValueError(f"Conflicting Snare field: {name}") + fields[name] = converted + except ValueError as exc: + errors.append(str(exc)) return ParsedRecord( source_format=self.format_name, @@ -333,24 +484,29 @@ def _parse_snare_line( parse_errors=errors, line_number=line_num, source_host=source_host, + representation="windows_snare", + source_fields=source_fields, ) -def _parse_expanded_snare_fields(full_data: str) -> dict[str, str]: +def _snare_field_occurrences(full_data: str) -> list[tuple[str, str]]: """Extract flattened ``Name: value`` fields in one bounded linear pass.""" tail = full_data.split(": ", 1)[1] if ": " in full_data else full_data - parsed: dict[str, str] = {} + parsed: list[tuple[str, str]] = [] current_name = "" current_value: list[str] = [] def commit() -> None: value = " ".join(current_value).strip() - if current_name and value: - parsed[current_name] = value + if current_name: + parsed.append((current_name, value)) for segment in tail.split(" "): - raw_name, separator, raw_value = segment.partition(": ") + raw_name, separator, raw_value = segment.partition(":") + if raw_value and not raw_value.startswith(" "): + separator = "" + raw_value = raw_value.removeprefix(" ") candidate_name = _snare_field_name(raw_name.strip()) if separator else "" if separator and candidate_name: commit() @@ -362,10 +518,20 @@ def commit() -> None: return parsed +def _parse_expanded_snare_fields(full_data: str) -> dict[str, str]: + """Compatibility view; repeated labels are intentionally not collapsed.""" + occurrences = _snare_field_occurrences(full_data) + names = [name for name, _ in occurrences] + return {name: value for name, value in occurrences if names.count(name) == 1} + + def _snare_field_name(name: str) -> str: """Return a stable eval-friendly field name for a Snare expanded label.""" if not name: return "" + canonical = re.fullmatch(r"Canonical\[([A-Za-z][A-Za-z0-9_]*)\]", name) + if canonical: + return canonical[1] if re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", name): return name return re.sub(r"[^A-Za-z0-9]+", "_", name).strip("_") @@ -387,7 +553,9 @@ class SysmonEventParser(_WindowsSnareParser): format_name = "windows_event_sysmon" xml_filename = "windows_event_sysmon.xml" snare_filename = WINDOWS_SYSMON_SNARE_FILENAME - _INTEGER_EVENT_DATA_FIELDS = _WindowsXmlParser._INTEGER_EVENT_DATA_FIELDS | frozenset( + _INTEGER_EVENT_DATA_FIELDS = ( + _WindowsXmlParser._INTEGER_EVENT_DATA_FIELDS - {"Protocol"} + ) | frozenset( { "DestinationPort", "NewThreadId", diff --git a/src/evidenceforge/evaluation/parsers/zeek_base_parser.py b/src/evidenceforge/evaluation/parsers/zeek_base_parser.py index 8680ce39b..a51f5f333 100644 --- a/src/evidenceforge/evaluation/parsers/zeek_base_parser.py +++ b/src/evidenceforge/evaluation/parsers/zeek_base_parser.py @@ -22,13 +22,13 @@ """Base parser for all Zeek NDJSON log files.""" -import json from collections.abc import Iterator from datetime import UTC, datetime from pathlib import Path from typing import Any from . import LogParser, ParsedRecord, iter_bounded_text_lines +from .json_record import decode_record class ZeekNdjsonParser(LogParser): @@ -56,7 +56,7 @@ def _parse_line(self, raw: str, line_num: int) -> ParsedRecord: timestamp = None try: - data = json.loads(raw) + data = decode_record(raw) fields = data ts = data.get("ts") @@ -64,10 +64,10 @@ def _parse_line(self, raw: str, line_num: int) -> ParsedRecord: try: epoch = float(ts) timestamp = datetime.fromtimestamp(epoch, tz=UTC) - except (ValueError, TypeError, OSError): + except (ValueError, TypeError, OSError, OverflowError): errors.append(f"Invalid timestamp: {ts}") - except json.JSONDecodeError as e: + except (ValueError, TypeError) as e: errors.append(f"JSON parse error: {e}") return ParsedRecord( diff --git a/src/evidenceforge/evaluation/pillars/causality.py b/src/evidenceforge/evaluation/pillars/causality.py index 543b4f62b..956c0a102 100644 --- a/src/evidenceforge/evaluation/pillars/causality.py +++ b/src/evidenceforge/evaluation/pillars/causality.py @@ -494,6 +494,9 @@ def _build_host_time_index( normalized = CausalityScorer._normalize_index_value(ip_val) if normalized: index[f"{normalized}|{bucket}"][format_name].append(rec) + target_username = rec.fields.get("TargetUserName") + for alias in CausalityScorer._username_match_aliases(target_username): + index[f"{alias}|{bucket}"][format_name].append(rec) return dict(index) @classmethod @@ -722,6 +725,9 @@ def _search_for_event_indexed( lookup_keys.append(str(expected_hostname).lower()) if event_type == "smb_activity": lookup_keys.extend(host.casefold() for host in self._smb_expected_hosts(event)) + if event_type == "failed_logon": + for username in self._expected_usernames_for_event(event): + lookup_keys.extend(self._username_match_aliases(username)) seen: set[int] = set() for hostname_key in lookup_keys: @@ -923,11 +929,15 @@ def _record_matches( ) elif event_type == "failed_logon": if format_name == "windows_event_security": - return ( - f.get("EventID") == 4625 - and self._host_matches(f.get("Computer"), event.system) - and self._user_matches(f.get("TargetUserName"), event.actor) - ) + event_id = f.get("EventID") + if event_id == 4625: + return self._host_matches( + f.get("Computer"), event.system + ) and self._username_indicator_matches(f.get("TargetUserName"), event) + if event_id in {4771, 4776}: + return self._is_modeled_domain_controller( + f.get("Computer") + ) and self._username_indicator_matches(f.get("TargetUserName"), event) if format_name == "ecar": return ( f.get("object") == "USER_SESSION" @@ -1941,6 +1951,19 @@ def _username_indicator_matches(cls, record_user: Any, event: ResolvedEvent) -> for username in cls._expected_usernames_for_event(event) ) + def _is_modeled_domain_controller(self, record_host: Any) -> bool: + """Return whether a source-native record belongs to a modeled domain controller.""" + return any( + self._host_matches(record_host, hostname) for hostname in self._domain_controller_hosts + ) + + def _source_hostname_for_ip(self, source_ip: Any) -> str | None: + """Resolve an authored source address to its modeled hostname when available.""" + normalized = self._normalize_pivot_ip(source_ip) + if not normalized: + return None + return self._pivot_ip_hosts.get(normalized) + @classmethod def _user_matches(cls, record_user: Any, expected: str) -> bool: if record_user is None: @@ -2575,10 +2598,15 @@ def _check_indicators( user_ok = self._username_indicator_matches(f[uf], event) checks.append(("username", user_ok)) break + dc_validation_trace = trace.source_format == "windows_event_security" and f.get( + "EventID" + ) in {4771, 4776} if trace.source_format != "cisco_asa": for hf in ["Computer", "hostname"]: if hf in f and f[hf]: - if "smb_activity" in event.event_types: + if dc_validation_trace: + host_matches = self._is_modeled_domain_controller(f[hf]) + elif "smb_activity" in event.event_types: expected_hosts = self._smb_expected_hosts(event) host_matches = any( self._host_matches(f[hf], expected_host) @@ -2588,14 +2616,32 @@ def _check_indicators( host_matches = self._host_matches(f[hf], event.system) checks.append(("hostname", host_matches)) break + if "source_ip" in details and f.get("EventID") == 4776: + expected_workstation = self._source_hostname_for_ip(details["source_ip"]) + if expected_workstation is not None: + checks.append( + ( + "source_workstation", + self._host_matches(f.get("Workstation"), expected_workstation), + ) + ) if "source_ip" in details: + source_field_found = False for ipf in ["IpAddress", "id.orig_h", "src_ip"]: - if ipf in f and f[ipf] and f[ipf] != "-": - source_ok = self._ip_matches(f[ipf], details["source_ip"]) + if ipf in f: + source_field_found = True + source_value = f[ipf] + source_ok = ( + bool(source_value) + and source_value != "-" + and self._ip_matches(source_value, details["source_ip"]) + ) if not source_ok and self._is_explicit_proxy_egress_trace(f, details): source_ok = True checks.append(("source_ip", source_ok)) break + if not source_field_found and self._failed_logon_source_address_required(event, trace): + checks.append(("source_ip", False)) if "dst_ip" in details: for df in ["id.resp_h", "dst_ip"]: if df in f and f[df]: @@ -2606,6 +2652,24 @@ def _check_indicators( break return checks + @staticmethod + def _failed_logon_source_address_required( + event: ResolvedEvent, + trace: ParsedRecord, + ) -> bool: + """Return whether a matched failed-auth trace natively carries a client address.""" + + if "failed_logon" not in event.event_types: + return False + fields = trace.fields + if trace.source_format == "windows_event_security": + return fields.get("EventID") in {4625, 4771} + return ( + trace.source_format == "ecar" + and fields.get("object") == "USER_SESSION" + and fields.get("action") == "LOGIN" + ) + def _smb_expected_hosts(self, event: ResolvedEvent) -> set[str]: """Return legitimate client and server hosts for dual-view SMB evidence.""" return {event.system, *self._smb_server_hosts(event)} @@ -2775,8 +2839,11 @@ def _initialize_pivot_identity(self, scenario: Scenario) -> None: self._pivot_host_aliases: dict[str, str] = {} self._pivot_host_ips: dict[str, str] = {} self._pivot_ip_hosts: dict[str, str] = {} + self._domain_controller_hosts: set[str] = set() for system in scenario.environment.systems: canonical = system.hostname.lower().rstrip(".") + if system.type == "domain_controller": + self._domain_controller_hosts.add(canonical) aliases = {canonical, canonical.split(".", 1)[0]} for alias in aliases: self._pivot_host_aliases[alias] = canonical diff --git a/src/evidenceforge/evaluation/pillars/parseability.py b/src/evidenceforge/evaluation/pillars/parseability.py index c553b03be..911e5039a 100644 --- a/src/evidenceforge/evaluation/pillars/parseability.py +++ b/src/evidenceforge/evaluation/pillars/parseability.py @@ -39,68 +39,31 @@ ) from evidenceforge.evaluation.models import PillarScore, SubScore from evidenceforge.evaluation.parsers import ParsedRecord +from evidenceforge.evaluation.validation_routes import ( + ARTIFACT_VALIDATORS, + get_validation_route, + require_evaluated, +) from evidenceforge.formats.format_def import FormatDefinition from evidenceforge.formats.loader import load_format +from evidenceforge.formats.rules import Finding from evidenceforge.formats.validator import STRICT_FORMATS, validate_event, validate_strict from evidenceforge.models.scenario import Scenario logger = logging.getLogger(__name__) -# EventID → variant name mapping for Windows Event Security -WINDOWS_VARIANT_MAP = { - 1102: "log_cleared", - 4624: "logon", - 4625: "failed_logon", - 4634: "logoff", - 4648: "explicit_credentials", - 4656: "object_handle_requested", - 4658: "object_handle_closed", - 4663: "object_access", - 4672: "special_privileges", - 4688: "process_creation", - 4689: "process_termination", - 4697: "service_installed", - 4698: "scheduled_task", - 4800: "workstation_locked", - 4801: "workstation_unlocked", - 4720: "account_created", - 4723: "password_change", - 4724: "password_reset", - 4726: "account_deleted", - 4728: "group_membership_change", - 4729: "group_membership_change", - 4732: "group_membership_change", - 4733: "group_membership_change", - 4738: "account_changed", - 4756: "group_membership_change", - 4757: "group_membership_change", - 4768: "kerberos_tgt", - 4769: "kerberos_service_ticket", - 4770: "kerberos_service_ticket", - 4771: "kerberos_preauth_failed", - 4776: "ntlm_validation", - 5140: "network_share_access", - 5145: "network_share_access_check", - 5156: "wfp_connection", -} -# EventID -> variant name mapping for Windows Event Sysmon -SYSMON_VARIANT_MAP = { - 1: "sysmon_process_create", - 3: "sysmon_network_connect", - 5: "sysmon_process_terminate", - 7: "sysmon_image_loaded", - 8: "sysmon_create_remote_thread", - 10: "sysmon_process_access", - 11: "sysmon_file_create", - 12: "sysmon_registry_create_delete", - 13: "sysmon_registry_set_value", - 22: "sysmon_dns_query", -} +def _variant_map(format_name: str) -> dict[int, str]: + """Derive source event selectors from the packaged schema.""" + return { + event_id: variant.name + for variant in load_format(format_name).variants or [] + for event_id in variant.event_ids or ([int(variant.event_id)] if variant.event_id else []) + } + -# Error category constants -_SPEC_CATEGORIES = {"parse_error", "missing_field", "strict_validation"} -_CONSTRAINT_CATEGORIES = {"constraint_violation", "validation_error"} +WINDOWS_VARIANT_MAP = _variant_map("windows_event_security") +SYSMON_VARIANT_MAP = _variant_map("windows_event_sysmon") class ParseabilityScorer(DimensionScorer): @@ -116,11 +79,12 @@ def score( progress: ProgressCallback = _noop_callback, ) -> PillarScore: progress("sub_score_start", {"name": "Spec Conformance", "step": 1, "total": 2}) - spec = self._score_spec_conformance(records) + spec, constraints = self._score_both( + records, malformed_record_ids=context.malformed_record_ids if context else None + ) progress("sub_score_done", {"name": "Spec Conformance", "score": spec.score}) progress("sub_score_start", {"name": "Format Constraints", "step": 2, "total": 2}) - constraints = self._score_format_constraints(records) progress("sub_score_done", {"name": "Format Constraints", "score": constraints.score}) sub_scores = [spec, constraints] @@ -135,191 +99,144 @@ def score( ) def _score_spec_conformance(self, records: dict[str, list[ParsedRecord]]) -> SubScore: - """Spec conformance: parse errors + strict-mode validation failures. - - Counts records where the parser returned errors OR the strict validator - (RFC3164 syslog with legacy fallback, Zeek typed columns, eCAR schema, Windows XML) - rejected - the record. These failures indicate a downstream parser would reject the - record entirely. - """ - total = 0 - passing = 0 - failures: list[str] = [] - failure_counts: dict[str, dict[str, int]] = {} - - def _track(fmt: str, category: str, detail: str) -> None: - failure_counts.setdefault(fmt, {}) - failure_counts[fmt][category] = failure_counts[fmt].get(category, 0) + 1 - if len(failures) < 20: - failures.append(detail) + return self._score_both(records)[0] - for format_name, record_list in records.items(): - fmt_def = _load_format_def(format_name) - for record in record_list: - total += 1 + def _score_format_constraints(self, records: dict[str, list[ParsedRecord]]) -> SubScore: + return self._score_both(records)[1] + def _score_both( + self, + records: dict[str, list[ParsedRecord]], + *, + malformed_record_ids: set[int] | None = None, + ) -> tuple[SubScore, SubScore]: + """Validate each record once and aggregate bounded diagnostics by category.""" + totals = {"schema": 0, "constraint": 0} + unavailable_count = 0 + unavailable_findings: list[Finding] = [] + passing = {"schema": 0, "constraint": 0} + failures: dict[str, list[str]] = {"schema": [], "constraint": []} + counts: dict[str, dict[str, dict[str, int]]] = {"schema": {}, "constraint": {}} + findings: dict[str, list[Finding]] = {"schema": [], "constraint": []} + for name, items in records.items(): + route = get_validation_route(name) + definition = _load_format_def(route.validator) if route.kind == "native" else None + for record in items: + selected: dict[str, list[Finding]] = {"schema": [], "constraint": []} if record.parse_errors: - ctx = _build_event_context(format_name, record, None) - ctx_label = f" ({ctx})" if ctx else "" - line_info = f" (line {record.line_number})" if record.line_number else "" - for err in record.parse_errors: - _track( - format_name, - "parse_error", - f"[{format_name}{ctx_label}]{line_info} Parse error: {err}", + selected["schema"] = [ + Finding( + rule_id="parser.record", + format=name, + category="parse", + message=message, ) - continue - - if fmt_def is not None: - variant = _get_variant(format_name, record) - ctx = _build_event_context(format_name, record, variant) - ctx_label = f" ({ctx})" if ctx else "" - normalized = _normalize_for_validation( - format_name, record.fields, record.timestamp - ) - result = validate_event(fmt_def, normalized, variant, event_context=ctx) - - # Strict-mode: required field & type checks count as spec failures - spec_errors = ( - [ - e - for e in result.errors - if "required field missing" in e.lower() - or "invalid" in e.lower() - or "expected" in e.lower() - ] - if not result.valid - else [] - ) - - # Strict parser check (format-level byte validation) - strict_failed = False - if format_name in STRICT_FORMATS and record.raw: - strict_result = validate_strict(format_name, record.raw, record.fields) - if not strict_result.valid: - for err in strict_result.errors: - _track( - format_name, - "strict_validation", - f"[{format_name}{ctx_label}] Strict: {err}", - ) - strict_failed = True - - if spec_errors or strict_failed: - line_info = f" (line {record.line_number})" if record.line_number else "" - for err in spec_errors: - _track( - format_name, - _categorize_error(err), - f"[{format_name}{ctx_label}]{line_info} {err}", - ) - else: - passing += 1 + for message in record.parse_errors + ] + elif route.kind == "artifact": + selected["schema"] = ARTIFACT_VALIDATORS[route.validator](record) else: - passing += 1 - - score = 100.0 * passing / total if total > 0 else 0.0 - return SubScore( - name="Spec Conformance", - key="spec_conformance", - weight=0.55, - score=score, - details=f"{passing}/{total} records pass strict spec validation", - sample_failures=failures, - failure_summary=failure_counts, - ) - - def _score_format_constraints(self, records: dict[str, list[ParsedRecord]]) -> SubScore: - """Format constraints: per-field enum/range/regex violations. - - Counts records with constraint violations (enum out-of-range, regex mismatch, - invalid type coercion). These don't fail the strict parser but do violate - the format's declared field contracts. - """ - total = 0 - passing = 0 - failures: list[str] = [] - failure_counts: dict[str, dict[str, int]] = {} - - def _track(fmt: str, category: str, detail: str) -> None: - failure_counts.setdefault(fmt, {}) - failure_counts[fmt][category] = failure_counts[fmt].get(category, 0) + 1 - if len(failures) < 20: - failures.append(detail) - - for format_name, record_list in records.items(): - fmt_def = _load_format_def(format_name) - for record in record_list: - if record.parse_errors: - continue # Excluded from constraint scoring (already in spec_conformance) - - if fmt_def is not None: - variant = _get_variant(format_name, record) - ctx = _build_event_context(format_name, record, variant) - ctx_label = f" ({ctx})" if ctx else "" - normalized = _normalize_for_validation( - format_name, record.fields, record.timestamp - ) - result = validate_event(fmt_def, normalized, variant, event_context=ctx) - - # Only count constraint errors (not missing-field / strict errors) - constraint_errors = ( - [ - e - for e in result.errors - if "required field missing" not in e.lower() - and "invalid" not in e.lower() - and "expected" not in e.lower() - ] - if not result.valid - else [] + assert definition is not None + variant = _get_variant(name, record) + normalized = _normalize_for_validation(name, record.fields, record.timestamp) + unavailable = frozenset() + if record.representation == "windows_snare": + from evidenceforge.formats.snare import LEGACY_UNAVAILABLE_FIELDS + + if record.fields.get("ProjectionVersion") != "1": + unavailable = LEGACY_UNAVAILABLE_FIELDS + normalized = { + key: value + for key, value in normalized.items() + if key in definition.validation_fields(variant) + } + result = validate_event( + definition, + normalized, + variant, + include_diagnostics=False, + unavailable_fields=unavailable, ) - - # Also check strict parser for constraint-style issues - if format_name in STRICT_FORMATS and record.raw: - strict_result = validate_strict(format_name, record.raw, record.fields) - # Only strict non-spec errors (e.g. malformed value) - constraint_strict = [ - e for e in strict_result.errors if "required" not in e.lower() - ] - constraint_errors.extend(constraint_strict) - - total += 1 - if not constraint_errors: - passing += 1 - else: - line_info = f" (line {record.line_number})" if record.line_number else "" - for err in constraint_errors: - _track( - format_name, - "constraint_violation", - f"[{format_name}{ctx_label}]{line_info} {err}", + for finding in result.findings: + require_evaluated(finding) + if ( + finding.outcome == "not_applicable" + and set(finding.fields) & unavailable + ): + unavailable_count += 1 + if len(unavailable_findings) < 20: + unavailable_findings.append(finding) + if finding.severity != "error" or finding.outcome not in { + "fail", + "evaluation_error", + }: + continue + category = ( + "schema" if finding.category in {"schema", "parse"} else "constraint" + ) + selected[category].append(finding) + if ( + name in STRICT_FORMATS + and record.raw + and record.representation != "windows_snare" + ): + selected["schema"].extend( + Finding( + rule_id="parser.structure", + format=name, + variant=variant, + category="parse", + message=message, ) - else: - total += 1 - passing += 1 - - score = 100.0 * passing / total if total > 0 else 0.0 - return SubScore( - name="Format Constraints", - key="format_constraints", - weight=0.45, - score=score, - details=f"{passing}/{total} records pass format constraint checks", - sample_failures=failures, - failure_summary=failure_counts, - ) + for message in validate_strict(name, record.raw, record.fields).errors + ) + for group in selected.values(): + for finding in group: + require_evaluated(finding) + if selected["schema"] and malformed_record_ids is not None: + malformed_record_ids.add(id(record)) + for category in totals: + if record.parse_errors and category == "constraint": + continue + totals[category] += 1 + errors = selected[category] + if not errors: + passing[category] += 1 + continue + counts[category].setdefault(name, {}).setdefault(category, 0) + counts[category][name][category] += 1 + for finding in errors: + if len(failures[category]) < 20: + failures[category].append( + f"[{name}] line {record.line_number}: {finding.message}" + ) + findings[category].append(finding) + + def subscore(category: str) -> SubScore: + schema = category == "schema" + total = totals[category] + return SubScore( + name="Spec Conformance" if schema else "Format Constraints", + key="spec_conformance" if schema else "format_constraints", + weight=0.55 if schema else 0.45, + score=100.0 * passing[category] / total if total else 0.0, + details=f"{passing[category]}/{total} records pass {category} validation", + sample_failures=failures[category], + failure_summary=counts[category], + sample_findings=findings[category], + unavailable_check_count=unavailable_count if schema else 0, + sample_unavailable_findings=unavailable_findings if schema else [], + ) + + return subscore("schema"), subscore("constraint") # --- Module-level helpers --- -def _load_format_def(format_name: str) -> FormatDefinition | None: - try: - return load_format(format_name) - except Exception: - return None +def _load_format_def(format_name: str) -> FormatDefinition: + """A missing or broken schema is an evaluation error, never a passing record.""" + return load_format(format_name) def _get_variant(format_name: str, record: ParsedRecord) -> str | None: @@ -380,12 +297,3 @@ def _normalize_for_validation( if isinstance(restricted_sid_count, str) and restricted_sid_count.isdigit(): normalized["RestrictedSidCount"] = int(restricted_sid_count) return normalized - - -def _categorize_error(error_msg: str) -> str: - lower = error_msg.lower() - if "required field missing" in lower: - return "missing_field" - if "invalid" in lower or "expected" in lower: - return "constraint_violation" - return "validation_error" diff --git a/src/evidenceforge/evaluation/pillars/plausibility.py b/src/evidenceforge/evaluation/pillars/plausibility.py index e8b65e0b9..c535aaba9 100644 --- a/src/evidenceforge/evaluation/pillars/plausibility.py +++ b/src/evidenceforge/evaluation/pillars/plausibility.py @@ -40,7 +40,6 @@ from typing import Any from evidenceforge.evaluation._shared import ( - _condition_matches, _extract_hostname, _extract_username, _jensen_shannon_divergence, @@ -224,29 +223,57 @@ def _score_value_plausibility( # --- Sub-score 2: Co-occurrence Rules --- def _score_co_occurrence(self, records: dict[str, list[ParsedRecord]]) -> SubScore: - co_rules = load_rules_file("co_occurrence.yaml") + from evidenceforge.evaluation.pillars.parseability import ( + _get_variant, + _normalize_for_validation, + ) + from evidenceforge.evaluation.validation_routes import ( + get_validation_route, + require_evaluated, + ) + from evidenceforge.formats.loader import load_format + from evidenceforge.formats.rules import evaluate_rule, rule_fields + from evidenceforge.formats.validator import validate_field + total_applicable = 0 passing = 0 failures: list[str] = [] - max_sample = 2000 - for format_name, record_list in records.items(): - rules = co_rules.get(format_name, []) - if not rules: + route = get_validation_route(format_name) + if route.kind == "artifact": + continue # Structural checks run in parseability; email joins run below. + definition = load_format(route.validator) + diagnostic_rules = [r for r in definition.validators or [] if r.severity == "warning"] + if not diagnostic_rules: continue - valid = [r for r in record_list if not r.parse_errors] - if len(valid) > max_sample: - valid = _stable_records(valid, max_sample) - - for record in valid: - for rule in rules: - if _condition_matches(rule.get("condition", {}), record.fields): - total_applicable += 1 - checks = rule.get("checks", []) - if all(_check_passes(chk, record.fields) for chk in checks): - passing += 1 - elif len(failures) < 10: - failures.append(f"[{format_name}] Rule '{rule['name']}' failed") + diagnostic_fields = {name for rule in diagnostic_rules for name in rule_fields(rule)} + for record in record_list: + if record.parse_errors: + continue + normalized = _normalize_for_validation(format_name, record.fields, record.timestamp) + variant = _get_variant(format_name, record) + fields = definition.validation_fields(variant) or {} + invalid_fields = { + name + for name, field in fields.items() + if name in diagnostic_fields + and ( + (field.required and name not in normalized) + or ( + name in normalized and not validate_field(field, normalized[name]).valid + ) + ) + } + for rule in diagnostic_rules: + finding = evaluate_rule(rule, normalized, format_name, variant, invalid_fields) + require_evaluated(finding) + if finding.severity != "warning" or finding.outcome == "not_applicable": + continue + total_applicable += 1 + if finding.outcome == "pass": + passing += 1 + elif len(failures) < 10: + failures.append(f"[{format_name}] {finding.rule_id}: {finding.message}") if total_applicable == 0: return SubScore( @@ -671,36 +698,6 @@ def _check_os_plausibility(record: ParsedRecord, fmt: str) -> bool | None: return None -def _check_passes(check: dict[str, Any], fields: dict[str, Any]) -> bool: - field_name = check.get("field", "") - value = fields.get(field_name) - if "present" in check: - return value is not None - if "not_equal" in check: - return value is not None and value != check["not_equal"] - if "equals" in check: - return value == check["equals"] - if "min_length" in check: - return isinstance(value, str) and len(value) >= check["min_length"] - if "min_value" in check or "max_value" in check: - try: - v = int(value) if not isinstance(value, (int, float)) else value - if "min_value" in check and v < check["min_value"]: - return False - if "max_value" in check and v > check["max_value"]: - return False - return True - except (ValueError, TypeError): - return False - if "in" in check: - return value in check["in"] - if "matches" in check: - import re - - return bool(re.search(check["matches"], str(value or ""))) - return True - - def _coerce_key(value: Any, reference: dict) -> Any: sample_key = next(iter(reference), None) if sample_key is None: diff --git a/src/evidenceforge/evaluation/thresholds.py b/src/evidenceforge/evaluation/thresholds.py index ebdcd5aa3..9fcac28eb 100644 --- a/src/evidenceforge/evaluation/thresholds.py +++ b/src/evidenceforge/evaluation/thresholds.py @@ -11,35 +11,37 @@ from __future__ import annotations import logging -from dataclasses import dataclass, field from functools import lru_cache +from pydantic import BaseModel, ConfigDict, Field, ValidationError, model_validator + from evidenceforge.config.provider import _register_trusted_derived_cache from evidenceforge.evaluation.rules import load_rules_file +from evidenceforge.models.exceptions import ConfigurationError logger = logging.getLogger(__name__) _FILE = "thresholds.yaml" -@dataclass -class SubScoreThreshold: - minimum: float - aspirational: float - hard_gate: bool = False +class SubScoreThreshold(BaseModel): + model_config = ConfigDict(extra="forbid") + minimum: float = Field(ge=0, le=100) + aspirational: float = Field(ge=0, le=100) + hard_gate: bool = Field(default=False, strict=True) -@dataclass -class PillarThresholds: - weight: float - sub_scores: dict[str, SubScoreThreshold] = field(default_factory=dict) +class PillarThresholds(BaseModel): + model_config = ConfigDict(extra="forbid") + weight: float = Field(ge=0, le=1) + sub_scores: dict[str, SubScoreThreshold] = Field(default_factory=dict) -@dataclass -class EvalThresholds: +class EvalThresholds(BaseModel): + model_config = ConfigDict(extra="forbid") overall_minimum: float overall_aspirational: float - pillars: dict[str, PillarThresholds] = field(default_factory=dict) + pillars: dict[str, PillarThresholds] = Field(default_factory=dict) def sub_score(self, pillar: str, key: str) -> SubScoreThreshold | None: """Return threshold for a sub-score, or None if not configured.""" @@ -58,35 +60,49 @@ def hard_gates(self) -> list[tuple[str, str, SubScoreThreshold]]: return result +class OverallThresholds(BaseModel): + """Package-owned overall scoring thresholds.""" + + model_config = ConfigDict(extra="forbid") + minimum: float = Field(ge=0, le=100) + aspirational: float = Field(ge=0, le=100) + + +class ThresholdDocument(BaseModel): + """Strict on-disk scoring policy with mandatory exact source gates.""" + + model_config = ConfigDict(extra="forbid") + overall: OverallThresholds + pillars: dict[str, PillarThresholds] + + @model_validator(mode="after") + def validate_gates(self) -> ThresholdDocument: + """Prevent missing correctness gates from weakening acceptance.""" + for key in ("spec_conformance", "format_constraints"): + pillar = self.pillars.get("parseability") + threshold = pillar.sub_scores.get(key) if pillar else None + if threshold is None or not threshold.hard_gate or threshold.minimum != 100: + raise ValueError(f"parseability.{key} requires a 100% hard gate") + return self + + @lru_cache(maxsize=1) def load_thresholds() -> EvalThresholds: - """Load and cache thresholds from thresholds.yaml.""" - raw = load_rules_file(_FILE) - if not raw: - logger.warning("thresholds.yaml not found or empty; using built-in defaults") - return _defaults() - - overall = raw.get("overall", {}) - pillars_raw = raw.get("pillars", {}) - - pillars: dict[str, PillarThresholds] = {} - for pillar_name, pillar_data in pillars_raw.items(): - sub_scores: dict[str, SubScoreThreshold] = {} - for key, ss in (pillar_data.get("sub_scores") or {}).items(): - sub_scores[key] = SubScoreThreshold( - minimum=float(ss.get("minimum", 0.0)), - aspirational=float(ss.get("aspirational", 100.0)), - hard_gate=bool(ss.get("hard_gate", False)), - ) - pillars[pillar_name] = PillarThresholds( - weight=float(pillar_data.get("weight", 0.0)), - sub_scores=sub_scores, - ) + """Load validated package policy; missing policy is an explicit configuration error.""" + try: + from evidenceforge.config import get_config_directory + from evidenceforge.formats.snapshot_compatibility import decode_validation_snapshot + raw = decode_validation_snapshot( + get_config_directory() / "evaluation" / _FILE, load_rules_file(_FILE) + ) + document = ThresholdDocument.model_validate(raw) + except (ValidationError, OSError, ValueError) as exc: + raise ConfigurationError(f"Invalid packaged thresholds.yaml: {exc}") from exc return EvalThresholds( - overall_minimum=float(overall.get("minimum", 70.0)), - overall_aspirational=float(overall.get("aspirational", 85.0)), - pillars=pillars, + overall_minimum=document.overall.minimum, + overall_aspirational=document.overall.aspirational, + pillars=document.pillars, ) @@ -96,11 +112,3 @@ def load_thresholds() -> EvalThresholds: globals(), load_thresholds, ) - - -def _defaults() -> EvalThresholds: - """Minimal safe defaults when the YAML is absent.""" - return EvalThresholds( - overall_minimum=70.0, - overall_aspirational=85.0, - ) diff --git a/src/evidenceforge/evaluation/validation_routes.py b/src/evidenceforge/evaluation/validation_routes.py new file mode 100644 index 000000000..166197446 --- /dev/null +++ b/src/evidenceforge/evaluation/validation_routes.py @@ -0,0 +1,126 @@ +"""Explicit validation ownership for native logs and artifact parser sources.""" + +from typing import Literal + +from pydantic import BaseModel, ConfigDict, ValidationError + +from evidenceforge.evaluation.parsers import ParsedRecord +from evidenceforge.formats.loader import load_format +from evidenceforge.formats.rules import Finding +from evidenceforge.models.exceptions import ConfigurationError, EvaluationError + + +class ValidationRoute(BaseModel): + """Package-owned source validation contract.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + source: str + kind: Literal["native", "artifact"] + validator: str + + +_NATIVE_SOURCES = ( + "bash_history", + "cisco_asa", + "ecar", + "proxy_access", + "snort_alert", + "syslog", + "web_access", + "windows_event_security", + "windows_event_sysmon", + "zeek_conn", + "zeek_dhcp", + "zeek_dns", + "zeek_files", + "zeek_http", + "zeek_ntp", + "zeek_ocsp", + "zeek_packet_filter", + "zeek_pe", + "zeek_reporter", + "zeek_smb_files", + "zeek_smb_mapping", + "zeek_smtp", + "zeek_ssl", + "zeek_weird", + "zeek_x509", +) +VALIDATION_ROUTES = tuple( + ValidationRoute(source=name, kind="native", validator=name) for name in _NATIVE_SOURCES +) + (ValidationRoute(source="email_artifacts", kind="artifact", validator="email_manifest"),) + + +class EmailArtifact(BaseModel): + """Known optional manifest fields; existing extension metadata remains supported.""" + + # Artifact manifests have historically allowed extension metadata, unlike rule definitions. + model_config = ConfigDict(extra="ignore", strict=True) + message_id: str = "" + sender: str = "" + to: list[str] = [] + cc: list[str] = [] + bcc: list[str] = [] + subject: str = "" + date: str = "" + eml_path: str = "" + artifact_export_status: str = "" + artifact_export_reason: str = "" + + +def validate_email_artifact(record: ParsedRecord) -> list[Finding]: + """Validate native manifest field types without requiring optional metadata.""" + try: + EmailArtifact.model_validate(record.fields) + except ValidationError as exc: + return [ + Finding( + rule_id="artifact.email.structure", + format="email_artifacts", + category="schema", + fields=tuple(str(part) for part in error["loc"]), + message=error["msg"], + ) + for error in exc.errors(include_input=False) + ] + return [] + + +ARTIFACT_VALIDATORS = {"email_manifest": validate_email_artifact} + + +def get_validation_route(source: str) -> ValidationRoute: + """Reject unknown or ambiguous sources rather than silently omitting validation.""" + routes = [route for route in VALIDATION_ROUTES if route.source == source] + if len(routes) != 1: + raise ConfigurationError( + f"Expected exactly one validation route for {source}; got {len(routes)}" + ) + return routes[0] + + +def validate_route_inventory() -> None: + """Check registry completeness and resolve every validation owner.""" + from evidenceforge.evaluation.parsers import _PARSER_CLASSES + + sources = {route.source for route in VALIDATION_ROUTES} + if sources != set(_PARSER_CLASSES): + raise ConfigurationError( + f"Validation route/parser mismatch: {sorted(sources.symmetric_difference(_PARSER_CLASSES))}" + ) + for source in sorted(sources): + route = get_validation_route(source) + if route.kind == "native": + load_format(route.validator) + elif route.validator not in ARTIFACT_VALIDATORS: + raise ConfigurationError(f"Unknown artifact validator: {route.validator}") + + +def require_evaluated(finding: Finding) -> None: + """Separate broken validation execution from invalid observed evidence.""" + if finding.outcome == "evaluation_error": + raise EvaluationError( + f"Rule {finding.rule_id} failed for source={finding.format} " + f"variant={finding.variant or 'base'} fields={','.join(finding.fields)}: " + f"{finding.message}" + ) diff --git a/src/evidenceforge/external_parsers/compose_runtime.py b/src/evidenceforge/external_parsers/compose_runtime.py index 88435067c..a7e4e2779 100644 --- a/src/evidenceforge/external_parsers/compose_runtime.py +++ b/src/evidenceforge/external_parsers/compose_runtime.py @@ -427,6 +427,11 @@ def _prep_script( tmp="$file.tmp" awk ' {{ + # Staged inputs are uncompressed. Upstream compression auto requires + # fingerprint identity, which conflicts with this small-fixture adapter. + if ($0 ~ /^[[:space:]]*compression:[[:space:]]*auto[[:space:]]*$/) {{ + next + }} print if ($0 ~ /^[[:space:]]*-[[:space:]]*type:[[:space:]]*filestream[[:space:]]*$/) {{ indent = $0 diff --git a/src/evidenceforge/external_parsers/sof_elk.py b/src/evidenceforge/external_parsers/sof_elk.py index 36d69ee9c..77636a160 100644 --- a/src/evidenceforge/external_parsers/sof_elk.py +++ b/src/evidenceforge/external_parsers/sof_elk.py @@ -154,6 +154,7 @@ def run_sof_elk_parser( validators: tuple[str, ...], timeout_seconds: int = 120, runtime: str | None = None, + commit: str = SOF_ELK_COMMIT, progress_callback: ProgressCallback = _noop_progress, ) -> SofElkCombinedResult: """Run one Filebeat/Logstash pair for all selected SOF-ELK validators.""" @@ -178,7 +179,7 @@ def run_sof_elk_parser( filebeat_data_dir=filebeat_data_dir, logstash_data_dir=logstash_data_dir, repo_url=SOF_ELK_REPO_URL, - commit=SOF_ELK_COMMIT, + commit=commit, filebeat_image=FILEBEAT_IMAGE, logstash_image=LOGSTASH_IMAGE, runtime=runtime, diff --git a/src/evidenceforge/external_parsers/sof_elk_sources.py b/src/evidenceforge/external_parsers/sof_elk_sources.py index 9b7db5461..670ecd276 100644 --- a/src/evidenceforge/external_parsers/sof_elk_sources.py +++ b/src/evidenceforge/external_parsers/sof_elk_sources.py @@ -127,8 +127,8 @@ class SofElkSourceSpec: filter_files=( "1000-preprocess-all.conf", "6100-httpd.conf", - "8060-postprocess-useragent.conf", - "8110-postprocess-httpd.conf", + "8054-postprocess-useragent.conf", + "8004-postprocess-httpd.conf", "8999-postprocess-all.conf", ), output_label_type="httpdlog", diff --git a/src/evidenceforge/external_parsers/sof_elk_zeek.py b/src/evidenceforge/external_parsers/sof_elk_zeek.py index 0ae12dc8b..34fafe2a3 100644 --- a/src/evidenceforge/external_parsers/sof_elk_zeek.py +++ b/src/evidenceforge/external_parsers/sof_elk_zeek.py @@ -49,7 +49,7 @@ ) SOF_ELK_REPO_URL = "https://github.com/philhagen/sof-elk.git" -SOF_ELK_COMMIT = "517af9445574cc084cd5f4b80539fc244dab82b0" +SOF_ELK_COMMIT = "d9f9bdd113a606c7b3fa1b2eafaa2d4400a16668" FILEBEAT_IMAGE = "docker.elastic.co/beats/filebeat-oss:9.4.1" LOGSTASH_IMAGE = "docker.elastic.co/logstash/logstash-oss:9.4.1" HARNESS_CONTAINER_LABEL = "evidenceforge.external_parser=sof-elk-zeek" diff --git a/src/evidenceforge/external_parsers/splunk.py b/src/evidenceforge/external_parsers/splunk.py index 8d8c59d08..52675fedb 100644 --- a/src/evidenceforge/external_parsers/splunk.py +++ b/src/evidenceforge/external_parsers/splunk.py @@ -1169,7 +1169,11 @@ def _cim_required_field_names(expectation: SplunkCimExpectation) -> tuple[str, . def _search_result_rows(rows: list[JsonObject]) -> list[JsonObject]: - return [row for row in rows if isinstance(row.get("result"), dict)] + return [ + row + for row in rows + if row.get("preview") is not True and isinstance(row.get("result"), dict) + ] def _validation_sourcetype( diff --git a/src/evidenceforge/external_parsers/tag_policy.py b/src/evidenceforge/external_parsers/tag_policy.py index 411b4c4f2..edd08b425 100644 --- a/src/evidenceforge/external_parsers/tag_policy.py +++ b/src/evidenceforge/external_parsers/tag_policy.py @@ -25,6 +25,7 @@ from __future__ import annotations import json +import re from collections.abc import Callable, Mapping from dataclasses import dataclass from enum import StrEnum @@ -126,6 +127,27 @@ def _is_parsed_pam_auth_failure(event: JsonMapping) -> bool: ) or message.startswith("authentication failure; ") +def _is_parsed_generic_syslog_asa_probe_miss(event: JsonMapping) -> bool: + tags = event.get("tags", []) + if not isinstance(tags, list): + return False + tag_set = {str(tag) for tag in tags} + if "process_archive" not in tag_set or {"got_cisco", "parse_done"} & tag_set: + return False + if _get_path(event, "labels.type") != "syslog": + return False + if any( + _get_path(event, path) in (None, "") + for path in ("log.syslog.hostname", "log.syslog.appname", "event.original", "@timestamp") + ): + return False + process_name = _get_path(event, "process.name") + return not ( + isinstance(process_name, str) + and re.fullmatch(r"[0-9A-Fa-f]{12},.*", process_name) is not None + ) + + def _is_parsed_snare_windows_event(event: JsonMapping) -> bool: tags = event.get("tags", []) if not isinstance(tags, list): @@ -189,7 +211,7 @@ def _is_zeek_x509_post_2038_date_limitation(event: JsonMapping) -> bool: log_type="web_access", tag="_grokparsefail_8110-01", disposition=ParserTagDisposition.IGNORED_OPTIONAL_ENRICHMENT, - source="SOF-ELK configfiles/8110-postprocess-httpd.conf", + source="SOF-ELK configfiles/8004-postprocess-httpd.conf", reason=( "Optional page/not-page URL path classification after the HTTP access " "record has already been parsed." @@ -200,7 +222,7 @@ def _is_zeek_x509_post_2038_date_limitation(event: JsonMapping) -> bool: log_type="proxy_access", tag="_grokparsefail_8110-01", disposition=ParserTagDisposition.IGNORED_OPTIONAL_ENRICHMENT, - source="SOF-ELK configfiles/8110-postprocess-httpd.conf", + source="SOF-ELK configfiles/8004-postprocess-httpd.conf", reason=( "Optional page/not-page URL path classification after the HTTP access " "record has already been parsed." @@ -218,6 +240,18 @@ def _is_zeek_x509_post_2038_date_limitation(event: JsonMapping) -> bool: "record failed to parse." ), ), + ParserTagRule( + validator=SOF_ELK_SYSLOG_VALIDATOR, + log_type="syslog", + tag="_grokparsefailure", + disposition=ParserTagDisposition.IGNORED_OPTIONAL_ENRICHMENT, + source="SOF-ELK configfiles/6018-cisco_asa.conf at d9f9bdd", + reason=( + "The pinned SOF-ELK Cisco ASA filter uses Logstash's generic failure tag when its " + "opportunistic probe misses an otherwise-valid archived Linux syslog record." + ), + event_predicate=_is_parsed_generic_syslog_asa_probe_miss, + ), ParserTagRule( validator=SOF_ELK_SYSLOG_VALIDATOR, log_type="syslog", diff --git a/src/evidenceforge/formats/format_def.py b/src/evidenceforge/formats/format_def.py index d62599614..fdb7f3d1b 100644 --- a/src/evidenceforge/formats/format_def.py +++ b/src/evidenceforge/formats/format_def.py @@ -26,10 +26,25 @@ Format definitions describe field schemas, validation rules, and output templates. """ +import math +import re from enum import StrEnum from typing import Any -from pydantic import BaseModel, ConfigDict, Field, field_validator +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, field_validator, model_validator + +from .rules import ( + AddressFamily, + Bounds, + Combination, + Compare, + Length, + Membership, + Pattern, + RecordRule, + SameLength, + predicate_fields, +) class FieldType(StrEnum): @@ -48,6 +63,27 @@ class FieldType(StrEnum): LIST = "list" # JSON array (e.g., Zeek answers, TTLs) +def _literal_compatible(value: Any, field_type: FieldType) -> bool: + """Check predicate literal types without coercing developer-authored operands.""" + if value is None: + return True + if field_type in {FieldType.INTEGER, FieldType.FLOAT, FieldType.PORT, FieldType.TIMESTAMP}: + return ( + isinstance(value, (int, float)) and not isinstance(value, bool) and math.isfinite(value) + ) + if field_type == FieldType.BOOLEAN: + return isinstance(value, bool) + if field_type in { + FieldType.STRING, + FieldType.IP_ADDRESS, + FieldType.HEX_STRING, + FieldType.SID, + FieldType.ENUM, + }: + return isinstance(value, str) + return False + + class FieldConstraint(BaseModel): """Constraints for field validation. @@ -58,16 +94,31 @@ class FieldConstraint(BaseModel): min_length: Minimum string length max_length: Maximum string length allowed_values: List of allowed values (for enum type) - json_logic: JSON Logic rule for complex validation """ pattern: str | None = None - min_value: int | None = None - max_value: int | None = None + min_value: float | None = None + max_value: float | None = None min_length: int | None = None max_length: int | None = None allowed_values: list[str | int] | None = None - json_logic: dict[str, Any] | None = Field(None, description="JSON Logic rule for validation") + + @model_validator(mode="after") + def validate_constraints(self) -> "FieldConstraint": + """Reject malformed scalar constraints before processing records.""" + if self.pattern is not None: + try: + re.compile(self.pattern) + except re.error as exc: + raise ValueError(f"Invalid pattern: {exc}") from exc + for low, high in ((self.min_value, self.max_value), (self.min_length, self.max_length)): + if any(v is not None and not math.isfinite(v) for v in (low, high)): + raise ValueError("Constraint bounds must be finite") + if low is not None and high is not None and low > high: + raise ValueError("Minimum constraint must not exceed maximum") + if any(v is not None and v < 0 for v in (self.min_length, self.max_length)): + raise ValueError("Length constraints must be nonnegative") + return self model_config = ConfigDict(extra="forbid") @@ -90,6 +141,8 @@ class FieldDefinition(BaseModel): description: str = "" constraints: FieldConstraint | None = None default: Any = None + item_type: FieldType | None = None + nullable: bool = False @field_validator("name") @classmethod @@ -117,6 +170,7 @@ class EventVariant(BaseModel): name: str event_id: str | None = None + event_ids: list[int] = Field(default_factory=list) description: str = "" fields: list[FieldDefinition] = Field(default_factory=list) @@ -156,7 +210,7 @@ class FormatDefinition(BaseModel): fields: List of base fields (common to all variants) variants: Optional list of event variants output: Output template configuration - validators: Optional list of cross-field JSON Logic validators + validators: Optional list of typed record validators """ name: str = Field(..., pattern="^[a-z0-9_]+$") @@ -166,9 +220,128 @@ class FormatDefinition(BaseModel): fields: list[FieldDefinition] variants: list[EventVariant] | None = Field(default_factory=list) output: OutputTemplate - validators: list[dict[str, Any]] | None = Field( - None, description="Cross-field JSON Logic validators" - ) + validators: list[RecordRule] | None = Field(None, description="Typed record validators") + + _field_plans: dict[str | None, dict[str, FieldDefinition]] = PrivateAttr(default_factory=dict) + + def validation_fields(self, variant: str | None) -> dict[str, FieldDefinition] | None: + """Return the cached literal-key field plan for this definition and variant.""" + return self._field_plans.get(variant) + + @model_validator(mode="after") + def validate_contract(self) -> "FormatDefinition": + """Compile references and variant identities against declared fields.""" + fields = {f.name: f for f in self.fields} + variant_names: set[str] = set() + event_ids: set[int] = set() + for variant in self.variants or []: + if variant.name in variant_names: + raise ValueError(f"Duplicate variant {variant.name}") + variant_names.add(variant.name) + names = [f.name for f in variant.fields] + if len(names) != len(set(names)) or set(names).intersection( + f.name for f in self.fields + ): + raise ValueError(f"Duplicate fields in variant {variant.name}") + for event_id in variant.event_ids or ( + [int(variant.event_id)] if variant.event_id else [] + ): + if event_id in event_ids: + raise ValueError(f"Duplicate variant event ID {event_id}") + event_ids.add(event_id) + fields.update({f.name: f for f in variant.fields}) + self._field_plans = {None: {field.name: field for field in self.fields}} + for variant in self.variants or []: + self._field_plans[variant.name] = { + **self._field_plans[None], + **{field.name: field for field in variant.fields}, + } + ids: set[str] = set() + for rule in self.validators or []: + if rule.id in ids: + raise ValueError(f"Duplicate rule ID {rule.id}") + ids.add(rule.id) + for check in (*rule.when, *rule.exclude, *rule.checks): + for name in predicate_fields(check): + if name not in fields: + raise ValueError(f"Rule {rule.id} references unknown field {name}") + kind = fields[check.field].type + literals = [] + if isinstance(check, Compare) and check.other_field is None: + literals.append((check.value, kind)) + if isinstance(check, Membership): + literals.extend((value, kind) for value in check.values) + if isinstance(check, Combination): + for left, right in check.pairs: + literals.extend(((left, kind), (right, fields[check.other_field].type))) + if any( + not _literal_compatible(value, field_type) for value, field_type in literals + ): + raise ValueError(f"Rule {rule.id} has incompatible literal operand") + if isinstance(check, AddressFamily) and ( + kind not in {FieldType.IP_ADDRESS, FieldType.STRING} + or fields[check.other_field].type != FieldType.STRING + ): + raise ValueError( + f"Rule {rule.id} address_family requires address and string flag" + ) + if isinstance(check, Bounds) and kind not in { + FieldType.INTEGER, + FieldType.FLOAT, + FieldType.PORT, + }: + raise ValueError(f"Rule {rule.id} requires numeric field {check.field}") + if isinstance(check, (Length, SameLength)) and kind not in { + FieldType.STRING, + FieldType.LIST, + }: + raise ValueError(f"Rule {rule.id} requires string/list field {check.field}") + if isinstance(check, Pattern) and kind != FieldType.STRING: + raise ValueError(f"Rule {rule.id} requires string field {check.field}") + if isinstance(check, SameLength) and fields[check.other_field].type != kind: + raise ValueError(f"Rule {rule.id} has incompatible collection fields") + if isinstance(check, Compare) and check.other_field: + other_kind = fields[check.other_field].type + numeric_kinds = { + FieldType.INTEGER, + FieldType.FLOAT, + FieldType.PORT, + FieldType.TIMESTAMP, + } + text_kinds = { + FieldType.STRING, + FieldType.ENUM, + FieldType.IP_ADDRESS, + FieldType.HEX_STRING, + FieldType.SID, + } + if kind != other_kind and not ( + {kind, other_kind} <= numeric_kinds or {kind, other_kind} <= text_kinds + ): + raise ValueError(f"Rule {rule.id} has incompatible field operands") + if isinstance(check, Compare) and check.relation not in {"eq", "ne"}: + numeric = {FieldType.INTEGER, FieldType.FLOAT, FieldType.PORT} + if kind not in numeric: + raise ValueError(f"Rule {rule.id} ordering requires numeric operands") + if check.other_field and fields[check.other_field].type not in numeric: + raise ValueError(f"Rule {rule.id} has incompatible ordering operands") + if not check.other_field and ( + isinstance(check.value, bool) or not isinstance(check.value, (int, float)) + ): + raise ValueError(f"Rule {rule.id} ordering requires numeric literal") + return self + + @field_validator("validators", mode="before") + @classmethod + def reject_legacy_rules(cls, value: Any) -> Any: + """Explain how to migrate the former internal expression syntax.""" + if isinstance(value, list) and any( + isinstance(rule, dict) and "id" not in rule for rule in value + ): + raise ValueError( + "Legacy JSON Logic validators are unsupported; use typed rules with id, message, and checks" + ) + return value @field_validator("fields") @classmethod diff --git a/src/evidenceforge/formats/loader.py b/src/evidenceforge/formats/loader.py index 235016649..7c9700f5c 100644 --- a/src/evidenceforge/formats/loader.py +++ b/src/evidenceforge/formats/loader.py @@ -101,6 +101,9 @@ def load_format(name: str, force_reload: bool = False) -> FormatDefinition: try: # Load YAML data = load_yaml(format_file) + from evidenceforge.formats.snapshot_compatibility import decode_validation_snapshot + + data = decode_validation_snapshot(format_file, data) # Validate against Pydantic model format_def = FormatDefinition(**data) @@ -166,3 +169,17 @@ def clear_cache() -> None: global _format_cache _format_cache.clear() logger.debug("Cleared format definition cache") + + +def validate_packaged_contracts() -> None: + """Validate package-owned record and scoring contracts for command preflight.""" + load_all_formats() + from evidenceforge.evaluation.thresholds import load_thresholds + + load_thresholds() + from evidenceforge.evaluation.validation_routes import validate_route_inventory + + validate_route_inventory() + from evidenceforge.formats.snare import load_snare_projections + + load_snare_projections() diff --git a/src/evidenceforge/formats/rules.py b/src/evidenceforge/formats/rules.py new file mode 100644 index 000000000..ae9030b04 --- /dev/null +++ b/src/evidenceforge/formats/rules.py @@ -0,0 +1,297 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Bounded, typed predicates for developer-owned record contracts.""" + +from __future__ import annotations + +import ipaddress +import math +import re +from typing import Annotated, Any, Literal + +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, model_validator + +Scalar = str | int | float | bool | None + + +class Predicate(BaseModel): + """Common strict predicate configuration.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + field: str + + +class Presence(Predicate): + """Test non-null presence; empty strings and zero remain present.""" + + op: Literal["presence"] + present: bool = Field(default=True, strict=True) + + +class Compare(Predicate): + """Compare a field with one literal or another literal field name.""" + + op: Literal["compare"] + relation: Literal["eq", "ne", "lt", "le", "gt", "ge"] + value: Scalar = None + other_field: str | None = None + + @model_validator(mode="after") + def check_operand(self) -> Compare: + """Require exactly one explicit comparison operand.""" + if ("value" in self.model_fields_set) == (self.other_field is not None): + raise ValueError("compare requires exactly one of value or other_field") + return self + + +class Membership(Predicate): + """Test membership in a finite literal pool.""" + + op: Literal["membership"] + values: tuple[Scalar, ...] = Field(min_length=1) + + +class Bounds(Predicate): + """Require finite numeric bounds.""" + + op: Literal["bounds"] + minimum: float | None = Field(default=None, strict=True) + maximum: float | None = Field(default=None, strict=True) + + @model_validator(mode="after") + def check_bounds(self) -> Bounds: + """Reject empty, inverted, or nonfinite bounds.""" + if self.minimum is None and self.maximum is None: + raise ValueError("bounds requires minimum or maximum") + if any(v is not None and not math.isfinite(v) for v in (self.minimum, self.maximum)): + raise ValueError("bounds must be finite") + if self.minimum is not None and self.maximum is not None and self.minimum > self.maximum: + raise ValueError("minimum must not exceed maximum") + return self + + +class Length(Predicate): + """Require a string or list length.""" + + op: Literal["length"] + minimum: int = Field(default=0, ge=0, strict=True) + maximum: int | None = Field(default=None, ge=0, strict=True) + + @model_validator(mode="after") + def check_bounds(self) -> Length: + """Reject inverted length bounds.""" + if self.maximum is not None and self.minimum > self.maximum: + raise ValueError("minimum must not exceed maximum") + return self + + +class Pattern(Predicate): + """Require a compiled regular expression match.""" + + op: Literal["pattern"] + pattern: str + + @model_validator(mode="after") + def check_pattern(self) -> Pattern: + """Reject invalid expressions at definition load time.""" + try: + re.compile(self.pattern) + except re.error as exc: + raise ValueError(f"Invalid pattern: {exc}") from exc + return self + + +class SameLength(Predicate): + """Require equal lengths of two present lists.""" + + op: Literal["same_length"] + other_field: str + + +class Combination(Predicate): + """Require a supported pair of field values.""" + + op: Literal["combination"] + other_field: str + pairs: tuple[tuple[Scalar, Scalar], ...] = Field(min_length=1) + + +class AddressFamily(Predicate): + """Compare an IP address with a source-native IPv6 flag.""" + + op: Literal["address_family"] + other_field: str + + +Check = Annotated[ + Presence + | Compare + | Membership + | Bounds + | Length + | Pattern + | SameLength + | Combination + | AddressFamily, + Field(discriminator="op"), +] + + +class RecordRule(BaseModel): + """One conjunction of checks with explicit applicability and exclusions.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + id: str = Field(pattern=r"^[a-z0-9][a-z0-9_.-]*$") + message: str = Field(min_length=1) + severity: Literal["error", "warning"] = "error" + when: tuple[Check, ...] = () + exclude: tuple[Check, ...] = () + checks: tuple[Check, ...] = Field(min_length=1) + _references: tuple[str, ...] = PrivateAttr(default=()) + + @model_validator(mode="after") + def compile_references(self) -> RecordRule: + """Compile literal field references once when loading the rule.""" + self._references = tuple( + dict.fromkeys( + name + for check in (*self.when, *self.exclude, *self.checks) + for name in predicate_fields(check) + ) + ) + return self + + +class Finding(BaseModel): + """Machine-readable source validation outcome.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + rule_id: str + format: str = "" + variant: str | None = None + fields: tuple[str, ...] = () + category: Literal["schema", "constraint", "parse", "evaluation"] = "constraint" + severity: Literal["error", "warning"] = "error" + outcome: Literal["pass", "fail", "not_applicable", "evaluation_error"] = "fail" + message: str + + +def predicate_fields(check: Check) -> tuple[str, ...]: + """Return literal field references used by a predicate.""" + other = getattr(check, "other_field", None) + return (check.field, other) if other is not None else (check.field,) + + +def scalar_equal(value: Any, other: Any) -> bool: + """Compare numeric values without conflating booleans with numbers.""" + numeric = (int, float) + compatible = type(value) is type(other) or ( + isinstance(value, numeric) + and not isinstance(value, bool) + and isinstance(other, numeric) + and not isinstance(other, bool) + ) + return compatible and value == other + + +def predicate_passes(check: Check, fields: dict[str, Any]) -> bool: + """Execute one bounded predicate without coercing observed values.""" + value = fields.get(check.field) + if isinstance(check, Presence): + return (value is not None) == check.present + if value is None: + return ( + check.field in fields + and isinstance(check, Compare) + and check.other_field is None + and check.value is None + and check.relation == "eq" + ) + if isinstance(check, Compare): + other = fields.get(check.other_field) if check.other_field is not None else check.value + if check.relation == "eq": + return scalar_equal(value, other) + if check.relation == "ne": + return not (scalar_equal(value, other)) + if other is None: + return False + if check.relation == "lt": + return value < other + if check.relation == "le": + return value <= other + if check.relation == "gt": + return value > other + return value >= other + if isinstance(check, Membership): + return any(scalar_equal(value, item) for item in check.values) + if isinstance(check, Bounds): + return ( + isinstance(value, (int, float)) + and not isinstance(value, bool) + and math.isfinite(value) + and (check.minimum is None or value >= check.minimum) + and (check.maximum is None or value <= check.maximum) + ) + if isinstance(check, Length): + return ( + isinstance(value, (str, list)) + and len(value) >= check.minimum + and (check.maximum is None or len(value) <= check.maximum) + ) + if isinstance(check, Pattern): + return isinstance(value, str) and re.search(check.pattern, value) is not None + other = fields.get(check.other_field) + if isinstance(check, SameLength): + return ( + isinstance(value, (str, list)) + and type(value) is type(other) + and len(value) == len(other) + ) + if isinstance(check, Combination): + return any(scalar_equal(value, a) and scalar_equal(other, b) for a, b in check.pairs) + if isinstance(check, AddressFamily): + try: + version = ipaddress.ip_address(value).version + except ValueError: + return False + return other in ("true", "false") and (version == 6) == (other == "true") + raise TypeError(f"Unsupported predicate {type(check).__name__}") + + +def rule_fields(rule: RecordRule) -> tuple[str, ...]: + """Return the compiled literal references for an immutable predicate plan.""" + return rule._references + + +def evaluate_rule( + rule: RecordRule, + fields: dict[str, Any], + format_name: str, + variant: str | None, + invalid_fields: set[str] | None = None, +) -> Finding: + """Evaluate a rule, preserving non-applicability and execution failures.""" + references = rule_fields(rule) + outcome: Literal["pass", "fail", "not_applicable", "evaluation_error"] + try: + if invalid_fields and invalid_fields.intersection(references): + outcome = "not_applicable" + elif not all(predicate_passes(check, fields) for check in rule.when): + outcome = "not_applicable" + elif rule.exclude and all(predicate_passes(check, fields) for check in rule.exclude): + outcome = "not_applicable" + else: + outcome = "pass" if all(predicate_passes(c, fields) for c in rule.checks) else "fail" + except (TypeError, ValueError, OverflowError): + outcome = "evaluation_error" + return Finding( + rule_id=rule.id, + format=format_name, + variant=variant, + fields=references, + category="evaluation" if outcome == "evaluation_error" else "constraint", + severity="error" if outcome == "evaluation_error" else rule.severity, + outcome=outcome, + message=rule.message, + ) diff --git a/src/evidenceforge/formats/snapshot_compatibility.py b/src/evidenceforge/formats/snapshot_compatibility.py new file mode 100644 index 000000000..6fecde753 --- /dev/null +++ b/src/evidenceforge/formats/snapshot_compatibility.py @@ -0,0 +1,49 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Decode recognized pre-typed-rule snapshots without changing rendered formats.""" + +import hashlib +import json +from pathlib import Path +from typing import Any + +from evidenceforge.config.provider import packaged_default_document +from evidenceforge.models.exceptions import ConfigurationError +from evidenceforge.utils.yaml_loader import load_yaml_text + +# Exact legacy validator documents shipped at the immutable 2.1.0 baseline. +_LEGACY_RULE_DIGESTS = { + "windows_event_security": "3576125ad4f20b5f7c18c7e76ef2fd76b52053b35c16bc8071ac3d0c5f6ec437", + "zeek_conn": "23c4168a391e0c90fb4d0ba71fcf7c1ea66ffc29e4df503b42917b108ce76996", +} +_LEGACY_THRESHOLDS = "395316c618d24c83792baa5887a23b2e357f705887e4a38c9db9eb82bcb638f2" + + +def _digest(document: Any) -> str: + return hashlib.sha256( + json.dumps(document, sort_keys=True, separators=(",", ":")).encode() + ).hexdigest() + + +def decode_validation_snapshot(path: Path, document: dict[str, Any]) -> dict[str, Any]: + """Upgrade only recognized inlined validation metadata, never arbitrary old syntax. + + Render templates, scenario data, and the stored snapshot are untouched. + Recognized format metadata is promoted to the canonical runtime contract so + callback-free native renderer identity checks remain intact. + The runtime's typed rules and exact acceptance policy govern evaluation after upgrade. + """ + found, _ = packaged_default_document(path) + if not found: + return document + if path.stem in _LEGACY_RULE_DIGESTS and _digest(document) == _LEGACY_RULE_DIGESTS[path.stem]: + current = load_yaml_text(path.read_text(encoding="utf-8"), source=str(path)) + if current["output"] != document["output"]: + raise ConfigurationError( + "Legacy validation snapshot requires a rendering-compatible decoder" + ) + return current + if path.name == "thresholds.yaml" and _digest(document) == _LEGACY_THRESHOLDS: + return load_yaml_text(path.read_text(encoding="utf-8"), source=str(path)) + return document diff --git a/src/evidenceforge/formats/snare.py b/src/evidenceforge/formats/snare.py new file mode 100644 index 000000000..1a34ba25d --- /dev/null +++ b/src/evidenceforge/formats/snare.py @@ -0,0 +1,141 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Developer-owned, event-specific Snare projection contracts.""" + +import re +from datetime import datetime +from functools import lru_cache +from typing import Literal + +from pydantic import BaseModel, ConfigDict, Field, model_validator + +from evidenceforge.config import get_config_directory +from evidenceforge.config.provider import _register_trusted_derived_cache +from evidenceforge.models.exceptions import ConfigurationError +from evidenceforge.utils.files import load_yaml + +from .loader import load_format + +LEGACY_UNAVAILABLE_FIELDS = frozenset( + { + "Level", + "ExecutionProcessID", + "ExecutionThreadID", + "EventRecordID", + "SubjectUserSid", + "TargetUserSid", + "SubjectUserName", + "TargetUserName", + "SubjectDomainName", + "TargetDomainName", + "SubjectLogonId", + "TargetLogonId", + "NewProcessId", + "NewProcessName", + "ProcessId", + "ProcessName", + "Status", + } +) + + +class SnareEnvelope(BaseModel): + """Native envelope requirements, independent of XML system metadata.""" + + model_config = ConfigDict(extra="forbid", frozen=True, strict=True) + event_id: int = Field(gt=0, strict=True) + counter: int = Field(ge=0) + criticality: int = Field(ge=0, le=4) + computer: str = Field(min_length=1) + provider: str = Field(min_length=1) + channel: str = Field(min_length=1) + timestamp: datetime + logtype: Literal["Success Audit", "Failure Audit", "Error", "Information", "Warning"] + + +class SnareProjection(BaseModel): + """SOF-ELK display labels and their canonical event-field owners.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + source: Literal["windows_event_security", "windows_event_sysmon"] + event_id: int = Field(gt=0, strict=True) + variant: str + aliases: dict[str, str] + decimal_aliases: dict[str, str] = Field(default_factory=dict) + fallback_aliases: dict[str, str] = Field(default_factory=dict) + + +class SnareProjections(BaseModel): + """Exhaustive packaged projection inventory.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + version: Literal[1] + events: tuple[SnareProjection, ...] + + @model_validator(mode="after") + def check_inventory(self) -> "SnareProjections": + seen: set[tuple[str, int]] = set() + for event in self.events: + identity = (event.source, event.event_id) + if identity in seen: + raise ValueError(f"Duplicate Snare projection: {identity}") + seen.add(identity) + definition = load_format(event.source) + fields = definition.validation_fields(event.variant) + if not fields or any( + name not in fields + for name in ( + *event.aliases.values(), + *event.decimal_aliases.values(), + *event.fallback_aliases.values(), + ) + ): + raise ValueError(f"Invalid field reference in Snare projection: {identity}") + if any( + fields[name].type.value != "hex_string" for name in event.decimal_aliases.values() + ): + raise ValueError(f"Decimal Snare alias requires a hexadecimal owner: {identity}") + if any( + not re.fullmatch(r"[A-Za-z][A-Za-z0-9 ]*", label) + for label in (*event.aliases, *event.decimal_aliases, *event.fallback_aliases) + ): + raise ValueError(f"Invalid Snare display label: {identity}") + if event.fallback_aliases != {"Process ID": "ExecutionProcessID"}: + raise ValueError(f"Unsupported Snare execution-PID fallback: {identity}") + if event.aliases.keys() & event.decimal_aliases.keys(): + raise ValueError(f"Duplicate Snare display alias: {identity}") + if not any( + v.name == event.variant and int(v.event_id) == event.event_id + for v in definition.variants + ): + raise ValueError(f"Snare variant does not match EventID: {identity}") + expected = { + (source, int(variant.event_id)) + for source in ("windows_event_security", "windows_event_sysmon") + for variant in load_format(source).variants + } + if seen != expected: + raise ValueError(f"Incomplete Snare inventory: {seen ^ expected}") + return self + + +@lru_cache(maxsize=1) +def load_snare_projections() -> SnareProjections: + """Load and validate the package-owned projection definitions.""" + return SnareProjections.model_validate( + load_yaml(get_config_directory() / "projections" / "windows_snare.yaml") + ) + + +def snare_projection(source: str, event_id: int) -> SnareProjection: + """Select a declared projection; unknown variants are configuration failures.""" + for event in load_snare_projections().events: + if event.source == source and event.event_id == event_id: + return event + raise ConfigurationError(f"No Snare projection for {source} EventID {event_id}") + + +_register_trusted_derived_cache( + __name__, "load_snare_projections", globals(), load_snare_projections +) diff --git a/src/evidenceforge/formats/validator.py b/src/evidenceforge/formats/validator.py index e228d3538..9efbb9e13 100644 --- a/src/evidenceforge/formats/validator.py +++ b/src/evidenceforge/formats/validator.py @@ -23,20 +23,20 @@ """Format validation for EvidenceForge. This module provides validation functions for log fields based on format definitions. -Uses json-logic-py for complex validation rules. +Uses typed record predicates for cross-field validation. """ import ipaddress import json import logging +import math import re import xml.etree.ElementTree as ET from datetime import datetime from typing import Any -from json_logic import jsonLogic - from .format_def import FieldConstraint, FieldDefinition, FieldType, FormatDefinition +from .rules import Finding, evaluate_rule, rule_fields # Deduplicate unknown field warnings: only warn once per (format, field) pair _warned_unknown_fields: set[tuple[str, str]] = set() @@ -52,17 +52,22 @@ class ValidationResult: errors: List of error messages (field path + message) """ - def __init__(self): + def __init__(self) -> None: self.valid = True self.errors: list[str] = [] + self.findings: list[Finding] = [] - def add_error(self, field_path: str, message: str) -> None: + def add_error(self, field_path: str, message: str, category: str = "schema") -> None: """Add a validation error.""" self.valid = False self.errors.append(f"{field_path}: {message}") + self.findings.append( + Finding(rule_id=field_path, fields=(field_path,), category=category, message=message) + ) def merge(self, other: "ValidationResult") -> None: """Merge another validation result into this one.""" + self.findings.extend(other.findings) if not other.valid: self.valid = False self.errors.extend(other.errors) @@ -91,6 +96,12 @@ def validate_field_type( if not isinstance(field_value, int) or isinstance(field_value, bool): result.add_error(field_name, f"Expected integer, got {type(field_value).__name__}") + elif field_type == FieldType.FLOAT: + if isinstance(field_value, bool) or not isinstance(field_value, (int, float)): + result.add_error(field_name, "Expected finite number") + elif not math.isfinite(field_value): + result.add_error(field_name, "Expected finite number") + elif field_type == FieldType.BOOLEAN: if not isinstance(field_value, bool): result.add_error(field_name, f"Expected boolean, got {type(field_value).__name__}") @@ -98,7 +109,8 @@ def validate_field_type( elif field_type == FieldType.TIMESTAMP: # Accept datetime objects, ISO 8601 strings, or epoch floats/ints (Zeek) if isinstance(field_value, (int, float)) and not isinstance(field_value, bool): - pass # Epoch timestamp — valid + if not math.isfinite(field_value): + result.add_error(field_name, "Expected finite timestamp") elif isinstance(field_value, str): try: datetime.fromisoformat(field_value.replace("Z", "+00:00")) @@ -170,7 +182,7 @@ def validate_field_constraints( ) # Min/max value (for integers) - if isinstance(field_value, int) and not isinstance(field_value, bool): + if isinstance(field_value, (int, float)) and not isinstance(field_value, bool): if constraints.min_value is not None and field_value < constraints.min_value: result.add_error( field_name, @@ -203,18 +215,7 @@ def validate_field_constraints( f"Value must be one of {constraints.allowed_values}, got {field_value}", ) - # JSON Logic validation - if constraints.json_logic: - try: - # JSON Logic rule has access to the field value as {"value": ...} - data = {"value": field_value} - logic_result = jsonLogic(constraints.json_logic, data) - if not logic_result: - result.add_error( - field_name, f"Failed JSON Logic validation: {constraints.json_logic}" - ) - except Exception as e: - result.add_error(field_name, f"JSON Logic error: {e}") + result.findings = [f.model_copy(update={"category": "constraint"}) for f in result.findings] return result @@ -231,10 +232,21 @@ def validate_field(field_def: FieldDefinition, field_value: Any) -> ValidationRe """ result = ValidationResult() + if field_value is None and field_def.nullable: + return result + # Type validation type_result = validate_field_type(field_def.name, field_value, field_def.type) result.merge(type_result) + if not type_result.valid: + return result + if field_def.item_type and isinstance(field_value, list): + for index, item in enumerate(field_value): + result.merge( + validate_field_type(f"{field_def.name}[{index}]", item, field_def.item_type) + ) + # Constraint validation if field_def.constraints: constraint_result = validate_field_constraints( @@ -273,33 +285,6 @@ def validate_field(field_def: FieldDefinition, field_value: Any) -> ValidationRe _LEGACY_BSD_SYSLOG_RE = re.compile(r"^[A-Z][a-z]{2}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2}\s+\S+\s+\S+") _LEGACY_ISO_SYSLOG_RE = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\S*\s+\S+\s+\S+") -# eCAR valid object/action combos -_ECAR_VALID_OBJECTS = frozenset( - {"PROCESS", "FILE", "FLOW", "REGISTRY", "MODULE", "THREAD", "USER_SESSION", "SERVICE"} -) -_ECAR_VALID_ACTIONS = frozenset( - { - "CREATE", - "DELETE", - "MODIFY", - "READ", - "WRITE", - "OPEN", - "CLOSE", - "EXECUTE", - "TERMINATE", - "LOGIN", - "LOGOUT", - "START", - "STOP", - "LOAD", - "UNLOAD", - "CONNECT", - "DISCONNECT", - "REMOTE_CREATE", - } -) - # Formats that support strict-mode validation STRICT_FORMATS: frozenset[str] = frozenset( { @@ -457,12 +442,7 @@ def _validate_strict_ecar(raw: str, fields: dict[str, Any], result: ValidationRe if not isinstance(obj, dict): result.add_error("ecar_json", f"Expected JSON object, got {type(obj).__name__}") return - obj_type = obj.get("object") - action = obj.get("action") - if obj_type is not None and obj_type not in _ECAR_VALID_OBJECTS: - result.add_error("ecar_object", f"Unknown object type: {obj_type!r}") - if action is not None and action not in _ECAR_VALID_ACTIONS: - result.add_error("ecar_action", f"Unknown action: {action!r}") + # Field enums and object/action combinations have one owner: the format contract. def validate_event( @@ -470,6 +450,9 @@ def validate_event( event_data: dict[str, Any], variant_name: str | None = None, event_context: str | None = None, + *, + include_diagnostics: bool = True, + unavailable_fields: frozenset[str] = frozenset(), ) -> ValidationResult: """Validate an event against a format definition. @@ -486,25 +469,32 @@ def validate_event( result = ValidationResult() ctx_suffix = f" ({event_context})" if event_context else "" - # Build combined field list (base + variant) - fields = list(format_def.fields) - if variant_name and format_def.variants: - variant = next((v for v in format_def.variants if v.name == variant_name), None) - if variant: - fields.extend(variant.fields) - else: - result.add_error("_variant", f"Unknown variant: {variant_name}") - return result + fields = format_def.validation_fields(variant_name) + if fields is None: + result.add_error("_variant", f"Unknown variant: {variant_name}") + return result # Check required fields - for field_def in fields: + for field_def in fields.values(): if field_def.required and field_def.name not in event_data: - result.add_error(field_def.name, f"Required field missing{ctx_suffix}") + if field_def.name in unavailable_fields: + result.findings.append( + Finding( + rule_id=field_def.name, + fields=(field_def.name,), + category="schema", + severity="warning", + outcome="not_applicable", + message="Field unavailable in historical Snare representation", + ) + ) + else: + result.add_error(field_def.name, f"Required field missing{ctx_suffix}") # Validate present fields for field_name, field_value in event_data.items(): # Find field definition - field_def = next((f for f in fields if f.name == field_name), None) + field_def = fields.get(field_name) if not field_def: # Unknown field (warning, not error) — deduplicate per context key = (format_def.name, field_name, event_context or "") @@ -517,16 +507,31 @@ def validate_event( field_result = validate_field(field_def, field_value) result.merge(field_result) - # Cross-field validators (JSON Logic) - if format_def.validators: - for i, validator in enumerate(format_def.validators): - try: - logic_result = jsonLogic(validator, event_data) - if not logic_result: - result.add_error( - "_cross_field", f"Failed cross-field validation #{i}: {validator}" - ) - except Exception as e: - result.add_error("_cross_field", f"Cross-field validator error: {e}") - + invalid_fields = {f.fields[0].split("[", 1)[0] for f in result.findings if f.fields} + for rule in format_def.validators or []: + if not include_diagnostics and rule.severity == "warning": + continue + unavailable = set(rule_fields(rule)) & unavailable_fields - event_data.keys() + if unavailable: + result.findings.append( + Finding( + rule_id=rule.id, + fields=tuple(sorted(unavailable)), + severity="warning", + outcome="not_applicable", + message="Rule requires unavailable historical Snare fields", + ) + ) + continue + finding = evaluate_rule(rule, event_data, format_def.name, variant_name, invalid_fields) + result.findings.append(finding) + if finding.outcome == "evaluation_error" or ( + finding.outcome == "fail" and finding.severity == "error" + ): + result.valid = False + result.errors.append(f"_cross_field: {finding.rule_id}: {finding.message}") + result.findings = [ + finding.model_copy(update={"format": format_def.name, "variant": variant_name}) + for finding in result.findings + ] return result diff --git a/src/evidenceforge/generation/activity/generator.py b/src/evidenceforge/generation/activity/generator.py index 2e763cf4c..8ae6e1a4e 100644 --- a/src/evidenceforge/generation/activity/generator.py +++ b/src/evidenceforge/generation/activity/generator.py @@ -12687,7 +12687,7 @@ def generate_failed_logon( source_ip: Source IP for remote attempts. Local failed logons render with no source address in Windows Security. target_username: If set, the logon targets this user instead of the actor - dc_system: Domain controller to also emit 4625/4776 on (optional) + dc_system: Domain controller to also emit 4771/4776 on (optional) """ request = FailedLogonRequest( user=user, @@ -12710,10 +12710,7 @@ def _execute_failed_logon_bundle(self, request: FailedLogonRequest) -> None: source_ip = request.source_ip target_username = request.target_username - local_logon = logon_type in (2, 5, 7, 11) - if source_ip == system.ip: - source_ip = None - local_logon = True + local_logon = logon_type in (2, 4, 5, 7, 11) if source_ip is None: source_ip = "-" if local_logon else system.ip auth_source_ip = "-" if local_logon else source_ip @@ -13017,8 +13014,8 @@ def _execute_prepared_failed_logon_occurrence( remote_linux_source = ( _get_os_category(system.os) == "linux" - and source_ip not in (None, "-") - and source_ip != system.ip + and auth_source_ip not in (None, "-") + and auth_source_ip != system.ip ) is_windows_remote_auth = ( _get_os_category(system.os) == "windows" @@ -13138,7 +13135,7 @@ def _execute_prepared_failed_logon_occurrence( if remote_linux_source: pass - elif source_ip and source_ip != "-": + elif auth_source_ip and auth_source_ip != "-": ssh_source_port = linux_ssh_source_port or _ephemeral_port(_get_rng(), "linux") event.syslog = SyslogContext( app_name="sshd", @@ -13149,7 +13146,7 @@ def _execute_prepared_failed_logon_occurrence( facility=10, severity=4, message=( - f"Failed password for {effective_username} from {source_ip} " + f"Failed password for {effective_username} from {auth_source_ip} " f"port {ssh_source_port} ssh2" ), ) @@ -13200,7 +13197,7 @@ def _execute_prepared_failed_logon_occurrence( ntlm_delay_ms = rng.randint(3, _FAILED_LOGON_NTLM_VALIDATION_DELAY_MAX_MS) self.generate_ntlm_validation( username=effective_username, - workstation=system.hostname, + workstation=str(failed_profile["workstation_name"]), dc_hostname=dc_system.hostname, time=time + timedelta(milliseconds=ntlm_delay_ms), status=substatus, @@ -30032,7 +30029,11 @@ def _execute_kerberos_preauth_failure_bundle( reporting_pid = self._get_system_pid(dc_hostname, "lsass", 0x2E0) has_source_ip = source_ip not in {"", "-"} normalized_source_ip = ( - f"::ffff:{source_ip}" if has_source_ip and ":" not in source_ip else source_ip + f"::ffff:{source_ip}" + if has_source_ip and ":" not in source_ip + else source_ip + if has_source_ip + else "::1" ) source_port = ( self._reserve_kerberos_source_port(source_ip, dc_hostname, time, source_port) @@ -30080,7 +30081,7 @@ def _execute_kerberos_preauth_failure_bundle( ticket_options=failure_fields["ticket_options"], ticket_status=status, pre_auth_type=failure_fields["pre_auth_type"], - source_ip=normalized_source_ip or "-", + source_ip=normalized_source_ip, source_port=source_port, reporting_pid=reporting_pid, ), diff --git a/src/evidenceforge/generation/checkpoints/fingerprint.py b/src/evidenceforge/generation/checkpoints/fingerprint.py index 38fc1f56c..e6e4c3f39 100644 --- a/src/evidenceforge/generation/checkpoints/fingerprint.py +++ b/src/evidenceforge/generation/checkpoints/fingerprint.py @@ -25,7 +25,6 @@ _RUNTIME_DISTRIBUTIONS = ( "jinja2", - "json-logic-qubit", "pydantic", "pytz", "pyyaml", diff --git a/src/evidenceforge/generation/checkpoints/verify.py b/src/evidenceforge/generation/checkpoints/verify.py index 6d8286420..a7e8246f7 100644 --- a/src/evidenceforge/generation/checkpoints/verify.py +++ b/src/evidenceforge/generation/checkpoints/verify.py @@ -109,7 +109,9 @@ def verify_checkpoint_recovery( raise CheckpointCompatibilityError(detail) with tempfile.TemporaryDirectory(prefix="eforge-checkpoint-verify-") as temporary: - scratch_root = Path(temporary) / "bundle" + # macOS's default temp path can contain the /var -> /private/var alias. + # Canonicalize our owned scratch root before emitters verify its ancestry. + scratch_root = Path(temporary).resolve() / "bundle" scratch_store = IncrementalCheckpointStore(scratch_root) controller = IncrementalCheckpointController.for_recovery( store=scratch_store, diff --git a/src/evidenceforge/generation/emitters/host_base.py b/src/evidenceforge/generation/emitters/host_base.py index 9a82a8128..2ed0f3543 100644 --- a/src/evidenceforge/generation/emitters/host_base.py +++ b/src/evidenceforge/generation/emitters/host_base.py @@ -332,7 +332,7 @@ def _flush_unlocked(self) -> None: self.buffer.sort(key=self._sort_key) self._write_header_unlocked() self.output_path.parent.mkdir(parents=True, exist_ok=True) - with open(self.output_path, "a", encoding="utf-8") as f: + with open(self.output_path, "a", encoding="utf-8", newline="\n") as f: for entry in self.buffer: f.write(entry) if not entry.endswith("\n"): diff --git a/src/evidenceforge/generation/emitters/windows.py b/src/evidenceforge/generation/emitters/windows.py index e30641da2..747214e27 100644 --- a/src/evidenceforge/generation/emitters/windows.py +++ b/src/evidenceforge/generation/emitters/windows.py @@ -62,6 +62,18 @@ FormatDefinition, OutputTemplate, ) +from evidenceforge.formats.rules import ( + AddressFamily, + Bounds, + Combination, + Compare, + Length, + Membership, + Pattern, + Presence, + RecordRule, + SameLength, +) from evidenceforge.generation.activity.timing_profiles import windows_collision_spacing_config from evidenceforge.generation.activity.windows_auth_realism import min_unlock_gap_seconds from evidenceforge.generation.emitters import source_journal @@ -153,6 +165,16 @@ (EventVariant, "event_variant"), (OutputTemplate, "output_template"), (FormatDefinition, "format_definition"), + (RecordRule, "record_rule"), + (Presence, "presence"), + (Compare, "compare"), + (Membership, "membership"), + (Bounds, "bounds"), + (Length, "length"), + (Pattern, "pattern"), + (SameLength, "same_length"), + (Combination, "combination"), + (AddressFamily, "address_family"), ) _EXACT_FORMAT_SNAPSHOT_MAX_DEPTH = 64 _EXACT_FORMAT_SNAPSHOT_MAX_NODES = 100_000 @@ -2262,8 +2284,8 @@ def _render_kerberos_preauth_failed(self, event: CanonicalOccurrence) -> None: rng = self._event_rng(event) krb = event.kerberos host = self._get_host(event) - source_ip = krb.source_ip or "-" - source_port = krb.source_port if source_ip not in {"", "-"} else 0 + source_ip = krb.source_ip if krb.source_ip not in {"", "-"} else "::1" + source_port = krb.source_port if source_ip != "::1" else 0 event_data = { "EventID": 4771, diff --git a/src/evidenceforge/generation/emitters/windows_snare.py b/src/evidenceforge/generation/emitters/windows_snare.py index 3f3ef5e28..286378e69 100644 --- a/src/evidenceforge/generation/emitters/windows_snare.py +++ b/src/evidenceforge/generation/emitters/windows_snare.py @@ -28,6 +28,7 @@ from datetime import datetime from typing import Any +from evidenceforge.formats.snare import snare_projection from evidenceforge.generation.emitters.syslog_family import ( render_rfc3164_syslog, syslog_priority, @@ -109,39 +110,7 @@ 22: "Dns query", } -_SECURITY_FIELD_LABELS: dict[str, str] = { - "SubjectUserSid": "Security ID", - "TargetUserSid": "Security ID", - "SubjectUserName": "Account Name", - "TargetUserName": "Account Name", - "SubjectDomainName": "Account Domain", - "TargetDomainName": "Account Domain", - "SubjectLogonId": "Logon ID", - "TargetLogonId": "Logon ID", - "NewProcessId": "Process ID", - "ProcessId": "Process ID", - "NewProcessName": "Process Name", - "ProcessName": "Process Name", - "Status": "Exit Status", - "SourcePort": "SourcePort", - "DestinationPort": "DestinationPort", - "SourceAddress": "SourceIp", - "DestAddress": "DestinationIp", -} -_INTERNAL_FIELDS = frozenset({"_storyline_origin"}) -_COMMON_SYSTEM_FIELDS = frozenset( - { - "EventID", - "TimeCreated", - "Computer", - "Channel", - "Level", - "EventRecordID", - "ExecutionProcessID", - "ExecutionThreadID", - "Provider", - } -) +_COMMON_SYSTEM_FIELDS = frozenset({"EventID", "Computer", "Channel", "Provider"}) def render_windows_security_snare_syslog(event_data: dict[str, Any]) -> str: @@ -160,7 +129,7 @@ def render_windows_security_snare_syslog(event_data: dict[str, Any]) -> str: category=_SECURITY_TASKS.get(event_id, "Audit"), summary=_SECURITY_SUMMARIES.get(event_id, f"Windows Security event {event_id}."), timestamp=timestamp, - field_labels=_SECURITY_FIELD_LABELS, + field_labels=snare_projection("windows_event_security", event_id).aliases, ) severity = 5 if event_id in _SECURITY_FAILURE_EVENTS else 6 return render_rfc3164_syslog( @@ -179,8 +148,10 @@ def render_windows_sysmon_snare_syslog(event_data: dict[str, Any]) -> str: timestamp = _timestamp(event_data) computer = _clean_field(event_data.get("Computer") or "windows-host") summary = _SYSMON_TASKS.get(event_id, f"Sysmon event {event_id}.") + projected_data = dict(event_data) + projected_data.setdefault("UtcTime", _sysmon_utc_time(timestamp)) payload = _snare_payload( - event_data={**event_data, "UtcTime": _sysmon_utc_time(timestamp)}, + event_data=projected_data, computer=computer, channel="Microsoft-Windows-Sysmon/Operational", provider=_SYSMON_PROVIDER, @@ -189,7 +160,7 @@ def render_windows_sysmon_snare_syslog(event_data: dict[str, Any]) -> str: category=summary, summary=summary, timestamp=timestamp, - field_labels={}, + field_labels=snare_projection("windows_event_sysmon", event_id).aliases, ) return render_rfc3164_syslog( pri=syslog_priority(1, 6), @@ -214,7 +185,11 @@ def _snare_payload( timestamp: datetime, field_labels: dict[str, str], ) -> str: - expanded = _expanded_event_data(event_data, field_labels) + source = "windows_event_security" if channel == "Security" else "windows_event_sysmon" + projection = snare_projection(source, _event_id(event_data)) + expanded = _expanded_event_data( + event_data, field_labels, projection.decimal_aliases, projection.fallback_aliases + ) full_data = f"{summary}: {expanded}" if expanded else summary columns = ( computer, @@ -235,16 +210,39 @@ def _snare_payload( return "\t".join(_clean_field(value) for value in columns) -def _expanded_event_data(event_data: dict[str, Any], field_labels: dict[str, str]) -> str: - pieces: list[str] = [] +def _expanded_event_data( + event_data: dict[str, Any], + field_labels: dict[str, str], + decimal_aliases: dict[str, str], + fallback_aliases: dict[str, str], +) -> str: + pieces: list[str] = ["ProjectionVersion: 1"] + for label, key in field_labels.items(): + value = event_data.get(key) + if value not in (None, ""): + pieces.append(f"{label}: {_clean_field(value)}") + for label, key in decimal_aliases.items(): + value = event_data.get(key) + if value not in (None, ""): + pieces.append(f"{label}: {int(value, 16)}") + if not any(piece.startswith(("Process ID: ", "New Process ID: ")) for piece in pieces): + for label, key in fallback_aliases.items(): + if event_data.get(key) is not None: + pieces.append(f"{label}: {_clean_field(event_data[key])}") for key, value in event_data.items(): - if key in _COMMON_SYSTEM_FIELDS or key in _INTERNAL_FIELDS or value in (None, ""): + if key in _COMMON_SYSTEM_FIELDS or key.startswith("_") or value is None: continue - label = field_labels.get(key, key) + if isinstance(value, datetime): + value = ensure_utc(value).isoformat() + # Upstream's unanchored LogonId pattern otherwise captures a scoped identity. + label = ( + f"Canonical[{key}]" + if key + in {"SubjectLogonId", "TargetLogonId", "TargetLinkedLogonId", *decimal_aliases.values()} + else key + ) pieces.append(f"{label}: {_clean_field(value)}") - if not pieces: - return "" - return " ".join(pieces) + " " + return " ".join([*pieces, "ProjectionEnd: 1"]) + " " def _event_id(event_data: dict[str, Any]) -> int: diff --git a/src/evidenceforge/models/exceptions.py b/src/evidenceforge/models/exceptions.py index b5f47d88e..e3bf3742f 100644 --- a/src/evidenceforge/models/exceptions.py +++ b/src/evidenceforge/models/exceptions.py @@ -191,3 +191,7 @@ class InsufficientDiskSpaceError(GenerationError): Raised when the output directory lacks the required disk space for the estimated log dataset size. """ + + +class EvaluationError(EvidenceForgeError): + """An evaluation component failed; no completed quality report is available.""" diff --git a/src/evidenceforge/validation/configuration.py b/src/evidenceforge/validation/configuration.py index 416476740..c6d7146f3 100644 --- a/src/evidenceforge/validation/configuration.py +++ b/src/evidenceforge/validation/configuration.py @@ -647,6 +647,14 @@ def validate_config( """Validate raw overlays before activating an optional effective provider.""" directories = _configuration_directories() result = ValidationResult() + from evidenceforge.formats.loader import validate_packaged_contracts + from evidenceforge.models.exceptions import ConfigurationError + + try: + validate_packaged_contracts() + except ConfigurationError as exc: + result.issues.append(Issue("ERROR", "packaged record contracts", str(exc))) + return result overlay_yaml_files, blocked = _validate_raw_overlays(result) if blocked: return result diff --git a/tests/external_parser/test_snare_projection_matrix.py b/tests/external_parser/test_snare_projection_matrix.py new file mode 100644 index 000000000..00fc651fb --- /dev/null +++ b/tests/external_parser/test_snare_projection_matrix.py @@ -0,0 +1,213 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Field-level Snare compatibility with both supported upstream revisions.""" + +import json +from datetime import datetime +from pathlib import Path + +import pytest + +from evidenceforge.external_parsers.sof_elk import run_sof_elk_parser +from evidenceforge.external_parsers.tag_policy import ( + SOF_ELK_WINDOWS_SECURITY_SNARE_VALIDATOR, + SOF_ELK_WINDOWS_SYSMON_SNARE_VALIDATOR, +) +from evidenceforge.formats.snare import snare_projection +from evidenceforge.generation.emitters.windows_snare import ( + render_windows_security_snare_syslog, + render_windows_sysmon_snare_syslog, +) + +pytestmark = pytest.mark.external_parser +REVISIONS = ["517af9445574cc084cd5f4b80539fc244dab82b0", "d9f9bdd113a606c7b3fa1b2eafaa2d4400a16668"] +CASES = json.loads( + (Path(__file__).parents[1] / "fixtures/record_validation/snare_full_variants.json").read_text() +) + +network = next(c for c in CASES if c["format"].endswith("sysmon") and c["fields"]["EventID"] == 3) +process = next(c for c in CASES if c["format"].endswith("sysmon") and c["fields"]["EventID"] == 1) +CASES += [ + network + | { + "stress": True, + "fields": network["fields"] + | { + "SourceIp": "2001:db8::1", + "DestinationIp": "2001:db8::2", + "SourceIsIpv6": "true", + "DestinationIsIpv6": "true", + "SourcePort": 0, + "DestinationPort": 0, + }, + }, + process + | { + "stress": True, + "fields": process["fields"] + | { + "Image": r"C:\工具\程序.exe", + "CommandLine": r'"C:\工具\程序.exe" /c echo "x:y" && echo café' + "\ta\nb || echo done", + }, + }, +] + + +def nested(event: dict, path: str) -> object: + value = event + for key in path.split("."): + value = value.get(key, {}) if isinstance(value, dict) else None + return value + + +@pytest.mark.parametrize("revision", REVISIONS) +def test_all_snare_variants_extract_expected_fields(tmp_path: Path, revision: str) -> None: + data = tmp_path / "data" + data.mkdir() + expected = {} + for index, case in enumerate(CASES, 1): + fields = dict(case["fields"]) + fields.update(EventRecordID=index, Computer="WIN-01.example.test") + fields["TimeCreated"] = datetime.fromisoformat(fields["TimeCreated"].replace("Z", "+00:00")) + for key in ("SubjectUserName", "TargetUserName"): + if key in fields: + fields[key] = "subject-user" if key.startswith("Subject") else "target-user" + for key in ("SourceAddress", "SourceIp", "IpAddress", "ClientAddress"): + if key in fields and not case.get("stress"): + fields[key] = "192.0.2.10" + for key in ("DestAddress", "DestinationIp"): + if key in fields and not case.get("stress"): + fields[key] = "198.51.100.20" + source = case["format"] + if source.endswith("sysmon"): + fields["UtcTime"] = "2026-09-15 11:59:59.987" + renderer = ( + render_windows_security_snare_syslog + if source.endswith("security") + else render_windows_sysmon_snare_syslog + ) + with (data / (source + "_snare.log")).open("a") as stream: + stream.write(renderer(fields) + "\n") + expected[index] = (source, fields) + result = run_sof_elk_parser( + data, + tmp_path / "runtime", + commit=revision, + timeout_seconds=180, + validators=( + SOF_ELK_WINDOWS_SECURITY_SNARE_VALIDATOR, + SOF_ELK_WINDOWS_SYSMON_SNARE_VALIDATOR, + ), + ) + records = [r for rows in result.events_by_type.values() for r in rows] + assert len(records) == len(expected) + for record in records: + source, fields = expected[nested(record, "winlog.snare.counter")] + assert nested(record, "winlog.event_id") == fields["EventID"] + assert nested(record, "winlog.computer_name") == fields["Computer"] + aliases = snare_projection(source, fields["EventID"]).aliases + for label, destination in { + "Account Name": "winlog.user.name", + "Security ID": "winlog.user.identifier", + "Account Domain": "user.domain", + "SourceIp": "source.ip", + "SourcePort": "source.port", + "DestinationIp": "destination.ip", + "DestinationPort": "destination.port", + }.items(): + if label in aliases and fields.get(aliases[label]) not in (None, "", "-"): + assert str(nested(record, destination)) == str(fields[aliases[label]]), ( + fields["EventID"], + destination, + record, + ) + if "SubjectLogonId" in fields: + assert not nested(record, "winlog.event_data.LogonId"), record + projection = snare_projection(source, fields["EventID"]) + owner = next( + ( + projection.aliases[label] + for label in ("New Process ID", "Process ID") + if label in projection.aliases and fields.get(projection.aliases[label]) is not None + ), + "ExecutionProcessID", + ) + value = fields.get(owner) + if value is not None: + expected_pid = ( + int(value, 16) if isinstance(value, str) and value.startswith("0x") else str(value) + ) + assert nested(record, "winlog.process.pid") == expected_pid, (fields["EventID"], record) + image_owner = projection.aliases.get( + "New Process Name", projection.aliases.get("Image", "Image") + ) + if fields.get(image_owner): + assert nested(record, "process.executable") == fields[image_owner].replace("\\", "/"), ( + record + ) + if source.endswith("sysmon") and fields.get("ProcessId", 0) > 0: + assert nested(record, "process.pid") == str(fields["ProcessId"]), record + + if source.endswith("sysmon"): + assert datetime.fromisoformat(record["@timestamp"].replace("Z", "+00:00")).replace( + tzinfo=None + ) == datetime.fromisoformat(fields["UtcTime"]) + for field, destination in { + "Company": "winlog.event_data.Company", + "Description": "winlog.event_data.Description", + "DestinationHostname": "destination.domain", + "FileVersion": "process.pe.file_version", + "IntegrityLevel": "winlog.event_data.IntegrityLevel", + "OriginalFileName": "process.pe.original_file_name", + "ParentCommandLine": "process.parent.command_line", + "ParentProcessGuid": "process.parent.entity_id", + "ParentProcessId": "process.parent.pid", + "ParentUser": "winlog.event_data.ParentUser", + "ProcessGuid": "process.entity_id", + "Product": "winlog.event_data.Product", + "QueryName": "dns.question.name", + "Signature": "winlog.event_data.Signature", + "SignatureStatus": "winlog.event_data.SignatureStatus", + "SourceHostname": "source.domain", + "SourceImage": "winlog.event_data.SourceImage", + "StartAddress": "winlog.event_data.StartAddress", + "StartFunction": "winlog.event_data.StartFunction", + "StartModule": "winlog.event_data.StartModule", + "TargetFilename": "winlog.event_data.TargetFilename", + "TargetImage": "winlog.event_data.TargetImage", + "TargetObject": "winlog.event_data.TargetObject", + "TerminalSessionId": "winlog.event_data.TerminalSessionId", + }.items(): + if fields.get(field) not in (None, ""): + assert nested(record, destination) == str(fields[field]).replace("\\", "/"), ( + field, + record, + ) + if fields.get("RuleName"): + assert nested(record, "rule.name") == [fields["RuleName"]] + # Both frozen revisions replace backslashes before applying these + # backslash-dependent patterns. Preserve raw facts without claiming indexing. + for field, destination in { + "CurrentDirectory": "process.working_directory", + "ParentImage": "process.parent.executable", + }.items(): + if fields.get(field): + assert f"{field}: {fields[field]} " in nested(record, "event.original") + assert not nested(record, destination) + for field, destination in { + "SourceIp": "source.ip", + "DestinationIp": "destination.ip", + "SourcePort": "source.port", + "DestinationPort": "destination.port", + }.items(): + if field in fields: + value = fields[field] + if value == 0: + assert not nested(record, destination), record + else: + assert str(nested(record, destination)) == str(value), record + if fields.get("CommandLine"): + assert nested(record, "process.command_line") == fields["CommandLine"].replace( + "\\", "/" + ).replace("\t", " ").replace("\n", " ").replace("||", "|"), record diff --git a/tests/fixtures/record_validation/README.md b/tests/fixtures/record_validation/README.md new file mode 100644 index 000000000..d0a713ce4 --- /dev/null +++ b/tests/fixtures/record_validation/README.md @@ -0,0 +1,41 @@ +# Record validation witnesses + +`rule_cases.json` contains explicit passing/failing field dictionaries for every bundled rule. +They isolate the rule under test; they are not complete log records. + +`formats.json` contains positive schema-level records for every format without variants, including +representative generated fields and minimal standalone source-health records. `windows_variants.json` +contains minimal schema-level witnesses for every Security/Sysmon variant. Tests also remove each +required field and verify variant selection. These fixtures test contracts, not dataset realism. + +Native parser fixtures remain under `tests/fixtures/eval/good`. DNS parser mutation tests serialize +complete records before parsing; malformed NDJSON/XML tests exercise native input boundaries. +No test in `test_record_contracts.py` requires local `sample_data`. + +The native mutation suite covers all 66 format/variant witnesses. JSON and XML required-field +mutations exercise missing values, illegal empties, wrong types, and nonnullable JSON nulls. All +JSON fields also exercise null/empty/dash/object values, declared numeric boundaries, nonfinite +numbers, and typed list members. Rule witnesses pass through native parsing and shared scoring; +required-field/type failures can make the corresponding rule not applicable without losing the +scalar failure. A mixed malformed-native CLI test exercises all pillars and counted acceptance. + +Inapplicable combinations are deliberate: XML has text rather than object/null values, unconstrained +strings and lists may be empty, and an empty Bash username cannot be represented by the nonempty +filename from which the parser derives it. Fixed-position text sources use native malformed +headers/timestamps and rule-specific wire examples. Existing positive fixtures preserve optional +fields, observation gaps, source-native conversions, and unusual evidence. + +`legacy/` contains the exact two format documents and threshold document from immutable baseline +`787fd733`. Routine decoder tests use these committed fixtures; the historical slow checkpoint gate +also accepts `EFORGE_VALIDATION_BASELINE_PYTHON` pointing to that baseline's isolated interpreter. +No essential decoder test requires a local historical checkout or sample directory. + +`targets/` holds compact Splunk web/proxy JSON examples and a SOF-ELK Snare projection witness from +the iteration scenario. The Splunk fixtures exercise aliases, malformed types/shapes, and conflicts +through the complete CLI. The historical Snare witness retains ambiguous identity labels and omitted +XML metadata; tests require explicit unavailable-check findings rather than invented values. + +`snare_full_variants.json` adds synthetic optional-field witnesses for all 43 variants and all 826 +declared field slots. These are test values, not new generator defaults. Internal tests compare +canonical fields after rendering/parsing; external tests verify downstream extraction against both +frozen parser revisions. `targets/snare_v1/` contains compact generated projection-version-1 rows. diff --git a/tests/fixtures/record_validation/email/ARTIFACTS_MANIFEST.json b/tests/fixtures/record_validation/email/ARTIFACTS_MANIFEST.json new file mode 100644 index 000000000..7c1fb35c6 --- /dev/null +++ b/tests/fixtures/record_validation/email/ARTIFACTS_MANIFEST.json @@ -0,0 +1,16 @@ +{ + "schema_version": "1.0", + "email": { + "messages": [ + { + "message_id": "", + "subject": "Validation fixture", + "to": [ + "reader@example.test" + ], + "date": "Mon, 18 Mar 2024 12:00:00 +0000", + "artifact_export_status": "metadata_only" + } + ] + } +} diff --git a/tests/fixtures/record_validation/email/conn.json b/tests/fixtures/record_validation/email/conn.json new file mode 100644 index 000000000..5842ebc9a --- /dev/null +++ b/tests/fixtures/record_validation/email/conn.json @@ -0,0 +1 @@ +{"ts": 1705312829.008139, "uid": "CEmailValidation001", "id.orig_h": "10.0.0.10", "id.orig_p": 56946, "id.resp_h": "10.0.0.20", "id.resp_p": 80, "proto": "tcp", "service": "http", "duration": 5.654289, "orig_bytes": 1716, "resp_bytes": 340091, "conn_state": "SF", "local_orig": true, "local_resp": true, "missed_bytes": 0, "history": "ShADadTtFf", "orig_pkts": 117, "orig_ip_bytes": 7824, "resp_pkts": 238, "resp_ip_bytes": 352475, "ip_proto": 6} diff --git a/tests/fixtures/record_validation/email/smtp.json b/tests/fixtures/record_validation/email/smtp.json new file mode 100644 index 000000000..ff79042d4 --- /dev/null +++ b/tests/fixtures/record_validation/email/smtp.json @@ -0,0 +1 @@ +{"ts": 1705314127.446219, "uid": "CEmailValidation001", "id.orig_h": "10.0.0.10", "id.orig_p": 54702, "id.resp_h": "10.0.0.20", "id.resp_p": 587, "trans_depth": 1, "helo": "WIN-01.example.test", "mailfrom": "", "rcptto": [], "last_reply": "220 2.0.0 STARTTLS accepted", "path": [], "tls": true, "date": "", "from": "", "to": [], "cc": [], "msg_id": "", "subject": "Validation fixture", "user_agent": "", "fuids": []} diff --git a/tests/fixtures/record_validation/formats.json b/tests/fixtures/record_validation/formats.json new file mode 100644 index 000000000..0a4a4d5a9 --- /dev/null +++ b/tests/fixtures/record_validation/formats.json @@ -0,0 +1,430 @@ +[ + { + "format": "ecar", + "fields": { + "timestamp_ms": 1705312829104, + "id": "95883492-1cad-4997-b60a-b965a6d47372", + "hostname": "LINUX-01", + "object": "FLOW", + "action": "CONNECT", + "objectID": "2e7e2825-e704-4d88-a2bb-e9a46ec0280a", + "src_ip": "10.0.0.10", + "src_port": "56946", + "dst_ip": "10.0.0.20", + "dst_port": "80", + "protocol": "tcp", + "direction": "INBOUND" + } + }, + { + "format": "zeek_ntp", + "fields": { + "ts": 1705314043.39248, + "uid": "CPjSUGEohYBd3aBKmOr", + "id.orig_h": "10.0.0.10", + "id.orig_p": 52113, + "id.resp_h": "216.239.35.0", + "id.resp_p": 123, + "version": 4, + "mode": 4, + "stratum": 2, + "poll": 2048.0, + "precision": 1e-06, + "root_delay": 0.036214, + "root_disp": 0.004971, + "ref_id": ".GOOG.", + "ref_time": 1705314007.231922, + "org_time": 1705314043.249566, + "rec_time": 1705314043.252494, + "xmt_time": 1705314043.253117, + "num_exts": 0 + } + }, + { + "format": "zeek_smb_files", + "fields": { + "ts": 1705312965.666419, + "uid": "CgWAHx2h1prikju2jy", + "id.orig_h": "10.20.0.10", + "id.orig_p": 62071, + "id.resp_h": "10.20.0.20", + "id.resp_p": 445, + "action": "SMB::FILE_OPEN", + "path": "\\\\FS-01\\Team", + "name": "Templates\\onboarding.pptx" + } + }, + { + "format": "zeek_http", + "fields": { + "ts": 1705312829.027139, + "uid": "Cf81BjEAVdnNeJYq7q", + "id.orig_h": "10.0.0.10", + "id.orig_p": 56946, + "id.resp_h": "10.0.0.20", + "id.resp_p": 80, + "trans_depth": 1, + "method": "GET", + "host": "LINUX-01", + "uri": "/products", + "version": "1.1", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36", + "request_body_len": 0, + "response_body_len": 41529, + "status_code": 200, + "status_msg": "OK", + "resp_fuids": [ + "FdWSqWPbUgtoEdn14FS" + ], + "resp_mime_types": [ + "text/html" + ] + } + }, + { + "format": "zeek_ssl", + "fields": { + "ts": 1705312995.741929, + "uid": "CLjGH8rfpjWDMbTeLI", + "id.orig_h": "10.0.0.20", + "id.orig_p": 60067, + "id.resp_h": "151.101.64.223", + "id.resp_p": 443, + "version": "TLSv13", + "cipher": "TLS_AES_128_GCM_SHA256", + "server_name": "pypi.org", + "resumed": true, + "established": true, + "ssl_history": "CSD" + } + }, + { + "format": "zeek_smb_mapping", + "fields": { + "ts": 1705312965.088117, + "uid": "CgWAHx2h1prikju2jy", + "id.orig_h": "10.20.0.10", + "id.orig_p": 62071, + "id.resp_h": "10.20.0.20", + "id.resp_p": 445, + "path": "\\\\FS-01\\Team", + "service": "Team", + "native_file_system": "NTFS", + "share_type": "DISK" + } + }, + { + "format": "zeek_smtp", + "fields": { + "ts": 1705314127.446219, + "uid": "CEfV6GINSXMbTL22tO", + "id.orig_h": "10.0.0.10", + "id.orig_p": 54702, + "id.resp_h": "10.0.0.20", + "id.resp_p": 587, + "trans_depth": 1, + "helo": "WIN-01.example.test", + "mailfrom": "", + "rcptto": [], + "last_reply": "220 2.0.0 STARTTLS accepted", + "path": [], + "tls": true, + "date": "", + "from": "", + "to": [], + "cc": [], + "msg_id": "", + "subject": "", + "user_agent": "", + "fuids": [] + } + }, + { + "format": "zeek_reporter", + "fields": { + "ts": 1750000000.0, + "level": "example", + "message": "example", + "location": "example" + } + }, + { + "format": "syslog", + "fields": { + "pri": 30, + "version": 1, + "hostname": "LINUX-01", + "app_name": "irqbalance", + "procid": "7694", + "msgid": "-", + "structured_data": "-", + "message": "IRQ 16 affinity hint keeps vector on CPU 0 (ahci)", + "facility": 3, + "severity": 6, + "syslog_protocol": "rfc5424_legacy", + "timestamp": "2024-01-15 10:00:26.077416+00:00", + "pid": 7694 + } + }, + { + "format": "zeek_files", + "fields": { + "ts": 1705312829.05692, + "fuid": "FdWSqWPbUgtoEdn14FS", + "tx_hosts": [ + "10.0.0.20" + ], + "rx_hosts": [ + "10.0.0.10" + ], + "conn_uids": [ + "Cf81BjEAVdnNeJYq7q" + ], + "source": "HTTP", + "depth": 0, + "mime_type": "text/html", + "duration": 0.006243, + "local_orig": true, + "is_orig": false, + "seen_bytes": 41529, + "total_bytes": 41529, + "missing_bytes": 0, + "overflow_bytes": 0, + "timedout": false + } + }, + { + "format": "zeek_dhcp", + "fields": { + "ts": 1705312830.038327, + "uids": [ + "CditFQPCIZAElClCi5" + ], + "client_addr": "10.0.0.10", + "server_addr": "10.0.0.11", + "assigned_addr": "10.0.0.10", + "mac": "3c:97:0e:06:09:d4", + "host_name": "WIN-01", + "domain": "example.test", + "msg_types": [ + "REQUEST", + "ACK" + ], + "lease_time": 3600.0, + "duration": 0.491998 + } + }, + { + "format": "zeek_ocsp", + "fields": { + "ts": 1705313860.338609, + "id": "FYrdbFui90F4vTEazm", + "hashAlgorithm": "sha1", + "issuerNameHash": "14dcb315ede798d6239ad75e2196634149e19286", + "issuerKeyHash": "82cab9f7aea444c2a0bd066ac3020a56d7e01a77", + "serialNumber": "7B15FE4D9F95E1F67CA400723012082C", + "certStatus": "good", + "thisUpdate": 1705302477.0, + "nextUpdate": 1705704581.0 + } + }, + { + "format": "zeek_x509", + "fields": { + "ts": 1705313113.259, + "id": "F9wRMQ6OkX33AyFGBFO", + "fingerprint": "7debabe84debeb802b9b1e3569031a6cf1a17b20", + "certificate.version": 3, + "certificate.serial": "2AA21D65A52955D4F7A5B89B7B674C71CE62", + "certificate.subject": "CN=example.com", + "certificate.issuer": "CN=Amazon RSA 2048 M01, O=Amazon, C=US", + "certificate.not_valid_before": 1676875314, + "certificate.not_valid_after": 1710744114, + "certificate.key_alg": "rsaEncryption", + "certificate.sig_alg": "sha256WithRSAEncryption", + "certificate.key_type": "rsa", + "certificate.key_length": 2048, + "certificate.exponent": "65537", + "san.dns": [ + "example.com" + ], + "basic_constraints.ca": false, + "host_cert": true, + "client_cert": false + } + }, + { + "format": "zeek_packet_filter", + "fields": { + "ts": 1750000000.0, + "node": "example", + "filter": "example", + "init": false, + "success": false + } + }, + { + "format": "zeek_weird", + "fields": { + "ts": 1750000000.0, + "name": "example", + "notice": false, + "peer": "example" + } + }, + { + "format": "snort_alert", + "fields": { + "timestamp": 1750000000.0, + "sid": 1, + "classification": "example", + "priority": 1, + "protocol": "TCP", + "src_ip": "10.0.0.1", + "dst_ip": "10.0.0.1", + "message": "example" + } + }, + { + "format": "cisco_asa", + "fields": { + "timestamp": "2026-01-15T10:01:21", + "pri": 166, + "hostname": "edge-fw", + "severity": 6, + "msg_id": 302015, + "message": "Built outbound UDP connection 1067932 for workstations:10.0.0.21/51409 (10.0.0.21/51409) to outside:1.1.1.1/53 (1.1.1.1/53)", + "connection_id": 1067932, + "src_interface": "workstations", + "src_ip": "10.0.0.21", + "src_port": 51409, + "mapped_src_ip": "10.0.0.21", + "mapped_src_port": 51409, + "dst_interface": "outside", + "dst_ip": "1.1.1.1", + "dst_port": 53, + "mapped_dst_ip": "1.1.1.1", + "mapped_dst_port": 53 + } + }, + { + "format": "proxy_access", + "fields": { + "timestamp": 1750000000.0, + "client_ip": "10.0.0.1", + "method": "example", + "url": "example", + "status_code": 200, + "host": "example" + } + }, + { + "format": "zeek_pe", + "fields": { + "ts": 1705317648.5865, + "id": "FS9HB7aeWi6wL5ZS3X", + "machine": "AMD64", + "compile_ts": 1557962473, + "os": "WINDOWS_NT", + "subsystem": "WINDOWS_GUI", + "is_exe": true, + "is_64bit": true, + "uses_aslr": true, + "uses_dep": true, + "uses_code_integrity": false, + "uses_seh": true, + "has_import_table": true, + "has_export_table": false, + "has_cert_table": false, + "has_debug_data": true, + "section_names": [ + ".text", + ".idata", + ".data", + ".rsrc", + ".reloc" + ] + } + }, + { + "format": "bash_history", + "fields": { + "timestamp": 1705313110, + "username": "bob", + "hostname": "LINUX-01.example.test", + "command": "curl https://example.com/health > ~/health.txt" + } + }, + { + "format": "zeek_conn", + "fields": { + "ts": 1705312829.008139, + "uid": "Cf81BjEAVdnNeJYq7q", + "id.orig_h": "10.0.0.10", + "id.orig_p": 56946, + "id.resp_h": "10.0.0.20", + "id.resp_p": 80, + "proto": "tcp", + "service": "http", + "duration": 5.654289, + "orig_bytes": 1716, + "resp_bytes": 340091, + "conn_state": "SF", + "local_orig": true, + "local_resp": true, + "missed_bytes": 0, + "history": "ShADadTtFf", + "orig_pkts": 117, + "orig_ip_bytes": 7824, + "resp_pkts": 238, + "resp_ip_bytes": 352475, + "ip_proto": 6 + } + }, + { + "format": "zeek_dns", + "fields": { + "ts": 1705313110.405053, + "uid": "C6WjME1LmRHTLFFfcr", + "id.orig_h": "10.0.0.20", + "id.orig_p": 39802, + "id.resp_h": "208.67.222.222", + "id.resp_p": 53, + "proto": "udp", + "trans_id": 61076, + "rtt": 0.012416, + "query": "example.com", + "qclass": 1, + "qclass_name": "C_INTERNET", + "qtype": 1, + "qtype_name": "A", + "rcode": 0, + "rcode_name": "NOERROR", + "AA": false, + "TC": false, + "RD": true, + "RA": true, + "Z": 0, + "answers": [ + "54.230.166.120" + ], + "TTLs": [ + 201.0 + ], + "rejected": false, + "opcode": 0, + "opcode_name": "query" + } + }, + { + "format": "web_access", + "fields": { + "timestamp": 1750000000.0, + "client_ip": "10.0.0.1", + "method": "GET", + "path": "example", + "protocol": "example", + "status_code": 200 + } + } +] diff --git a/tests/fixtures/record_validation/legacy/thresholds.yaml b/tests/fixtures/record_validation/legacy/thresholds.yaml new file mode 100644 index 000000000..af6362059 --- /dev/null +++ b/tests/fixtures/record_validation/legacy/thresholds.yaml @@ -0,0 +1,148 @@ +# EvidenceForge evaluation thresholds +# +# Each pillar has a weight (0–1, must sum to 1.0) and each sub-score has: +# minimum: hard gate — dataset FAILS if the sub-score falls below this +# aspirational: informational target — shown as a % of aspirational scores met +# +# Rationale for initial values is documented in docs/design/data-quality-prd.md. +# Adjust these values after running a calibration pass against known-good datasets. + +overall: + minimum: 70 + aspirational: 85 + +pillars: + # Pillar 1 — Parseability + # Goal: generated records parse cleanly under the same rules as real downstream parsers. + parseability: + weight: 0.30 + sub_scores: + spec_conformance: + minimum: 95 + aspirational: 99 + hard_gate: true + # Real SIEMs tolerate ~5% parse failures; 98 was aspirational, not achievable. + format_constraints: + minimum: 90 + aspirational: 98 + hard_gate: true + # Constraint violations are authoring errors; more forgiving floor. + + # Pillar 2 — Plausibility + # Goal: no impossible or highly-improbable field values, combinations, or + # population characteristics. + plausibility: + weight: 0.25 + sub_scores: + value_plausibility: + minimum: 95 + aspirational: 99 + hard_gate: true + # OS cross-contamination and impossible field combos should be near zero. + co_occurrence: + minimum: 85 + aspirational: 95 + hard_gate: false + # Rules are incomplete; tighten as co_occurrence.yaml coverage grows. + distribution_fit: + minimum: 70 + aspirational: 85 + hard_gate: false + # JSD is noisy; per-field tolerance already built in. + field_agreement: + minimum: 85 + aspirational: 97 + hard_gate: true + # Conservative floor for the new pivot-key join implementation. + user_diversity: + minimum: 60 + aspirational: 85 + hard_gate: false + # Small user pools make cosine similarity noisy. + anomaly_rate: + minimum: 70 + aspirational: 95 + hard_gate: false + # 1–5 % goldilocks band; validate bands against calibration data. + ids_integrity: + minimum: 100 + aspirational: 100 + hard_gate: true + # Exact rendered-output contract; any contradiction is a generator defect. + + # Pillar 3 — Causality + # Goal: before/after relationships are correct in background noise and + # along the storyline. + causality: + weight: 0.25 + sub_scores: + causal_ordering: + minimum: 90 + aspirational: 99 + hard_gate: true + # 99 was too tight due to grace-period edge cases; 90 is realistic. + event_presence: + minimum: 85 + aspirational: 95 + hard_gate: true + # Lowered from 90 to accommodate visibility-gap scenarios. + intent_reconciliation: + minimum: 100 + aspirational: 100 + hard_gate: true + # Every authored typed event must remain accounted for independently of generation. + effect_reconciliation: + minimum: 100 + aspirational: 100 + hard_gate: true + # Generated bundles must report zero missing, duplicate, or cardinality-invalid effects. + indicator_accuracy: + minimum: 85 + aspirational: 95 + hard_gate: true + pivot_linkability: + minimum: 80 + aspirational: 95 + hard_gate: true + temporal_integrity: + minimum: 85 + aspirational: 95 + hard_gate: true + storyline_trace_coverage: + minimum: 80 + aspirational: 95 + hard_gate: true + + # Pillar 4 — Timing + # Goal: both per-actor inter-event cadence and macro time-of-day / day-of-week + # patterns are plausible. + timing: + weight: 0.20 + sub_scores: + attack_chain_timing: + minimum: 85 + aspirational: 95 + hard_gate: false + # Conservative floor for new check. + burstiness: + minimum: 60 + aspirational: 85 + hard_gate: false + # CV is highly variable with small N. + system_regularity: + minimum: 60 + aspirational: 85 + hard_gate: false + diurnal_pattern: + minimum: 70 + aspirational: 90 + hard_gate: false + volume_adequacy: + minimum: 70 + aspirational: 90 + hard_gate: false + rate_plausibility: + minimum: 95 + aspirational: 100 + hard_gate: false + # Impossible rates indicate a generator bug; should be near-perfect. diff --git a/tests/fixtures/record_validation/legacy/windows_event_security.yaml b/tests/fixtures/record_validation/legacy/windows_event_security.yaml new file mode 100644 index 000000000..7c73f564c --- /dev/null +++ b/tests/fixtures/record_validation/legacy/windows_event_security.yaml @@ -0,0 +1,1700 @@ +# windows_event_security format definition — Windows Security Event Log format (XML output) +# +# Category: host +# Standalone: yes (no cross-file dependencies) +# Note: Field names may be referenced by evaluation rules in config/evaluation/ +# +# Full schema: see commands/eforge/references/config-formats.md + +name: windows_event_security +version: "1.0" +description: "Windows Security Event Log format (XML output)" +category: host + +# Base fields common to all Windows Event Log entries +fields: + - name: EventID + type: integer + required: true + description: "Windows Event ID" + constraints: + allowed_values: [1102, 4624, 4625, 4634, 4648, 4656, 4658, 4663, 4672, 4688, 4689, 4697, 4698, 4699, 4700, 4701, 4720, 4723, 4724, 4726, 4728, 4729, 4732, 4733, 4738, 4756, 4757, 4768, 4769, 4770, 4771, 4776, 4778, 4779, 4800, 4801, 5140, 5145, 5156] + + - name: TimeCreated + type: timestamp + required: true + description: "Event creation timestamp" + + - name: Computer + type: string + required: true + description: "Computer name where event was generated" + + - name: Channel + type: string + required: true + description: "Event log channel" + default: "Security" + + - name: Level + type: integer + required: true + description: "Event level (0=LogAlways, 4=Information)" + constraints: + allowed_values: [0, 1, 2, 3, 4] + + - name: EventRecordID + type: integer + required: true + description: "Sequential event record ID" + constraints: + min_value: 1 + + - name: ExecutionProcessID + type: integer + required: true + description: "Process ID of event logging service" + + - name: ExecutionThreadID + type: integer + required: true + description: "Thread ID of event logging service" + +# Event variants for different EventIDs +variants: + # EventID 4624: An account was successfully logged on + - name: logon + event_id: "4624" + description: "User logon event" + fields: + - name: SubjectUserSid + type: sid + required: true + description: "SID of account that reported the logon" + + - name: SubjectUserName + type: string + required: true + description: "Account name that reported the logon" + + - name: SubjectDomainName + type: string + required: true + description: "Domain of account that reported the logon" + + - name: SubjectLogonId + type: hex_string + required: true + description: "Logon ID of the account that reported the logon" + + - name: TargetUserSid + type: sid + required: true + description: "SID of the account that was logged on" + + - name: TargetUserName + type: string + required: true + description: "Account name that was logged on" + + - name: TargetDomainName + type: string + required: true + description: "Domain of the account that was logged on" + + - name: TargetLogonId + type: hex_string + required: true + description: "Logon ID of the new logon session" + + - name: LogonType + type: integer + required: true + description: "Type of logon (2=Interactive, 3=Network, 10=RemoteInteractive)" + constraints: + allowed_values: [2, 3, 4, 5, 7, 8, 9, 10, 11] + + - name: LogonProcessName + type: string + required: false + description: "Name of the logon process" + + - name: AuthenticationPackageName + type: string + required: false + description: "Authentication package used" + + - name: WorkstationName + type: string + required: true + description: "Source workstation name" + + - name: LogonGuid + type: string + required: false + description: "GUID to correlate with RADIUS/802.1x events" + + - name: TransmittedServices + type: string + required: false + description: "List of transmitted services" + + - name: LmPackageName + type: string + required: false + description: "LAN Manager package name" + + - name: KeyLength + type: integer + required: false + description: "Length of NTLM session security key" + + - name: ProcessId + type: hex_string + required: true + description: "Process ID of the logon process" + + - name: ProcessName + type: string + required: true + description: "Full path of the logon process executable" + + - name: IpAddress + type: string + required: true + description: "Source IP address (use '-' for local logons)" + + - name: IpPort + type: integer + required: true + description: "Source port number (use 0 for local logons)" + constraints: + min_value: 0 + max_value: 65535 + + - name: ImpersonationLevel + type: string + required: false + description: "Impersonation level" + + - name: RestrictedAdminMode + type: string + required: false + description: "Restricted Admin mode indicator" + + - name: TargetOutboundUserName + type: string + required: false + description: "Outbound account name" + + - name: TargetOutboundDomainName + type: string + required: false + description: "Outbound domain name" + + - name: VirtualAccount + type: string + required: false + description: "Virtual account indicator" + + - name: TargetLinkedLogonId + type: hex_string + required: false + description: "Linked logon ID for split-token logons" + + - name: ElevatedToken + type: string + required: false + description: "Elevated token indicator (Yes/No)" + + - name: RemoteUserID + type: sid + required: false + description: "SID of the remote user" + + - name: RemoteMachineID + type: sid + required: false + description: "SID of the remote machine" + + # EventID 4634: An account was logged off + - name: logoff + event_id: "4634" + description: "User logoff event" + fields: + - name: TargetUserSid + type: sid + required: true + description: "SID of the account that was logged off" + + - name: TargetUserName + type: string + required: true + description: "Account name that was logged off" + + - name: TargetDomainName + type: string + required: true + description: "Domain of the account that was logged off" + + - name: TargetLogonId + type: hex_string + required: true + description: "Logon ID of the session that was logged off" + + - name: LogonType + type: integer + required: true + description: "Type of logon that was ended" + constraints: + allowed_values: [2, 3, 4, 5, 7, 8, 9, 10, 11] + + # EventID 4688: A new process has been created + - name: rdp_session_reconnect + event_id: "4778" + description: "RDP session reconnected" + fields: &rdp_transition_fields + - name: AccountName + type: string + required: true + description: "Account that owns the RDP session" + - name: AccountDomain + type: string + required: true + description: "Account domain" + - name: LogonID + type: hex_string + required: true + description: "Preserved RDP logon identifier" + - name: SessionName + type: string + required: true + description: "Windows terminal-services session name" + - name: ClientName + type: string + required: true + description: "Remote client name" + - name: ClientAddress + type: string + required: true + description: "Remote client address" + - name: ClientPort + type: integer + required: true + description: "Remote client source port" + constraints: + min_value: 0 + max_value: 65535 + + - name: rdp_session_disconnect + event_id: "4779" + description: "RDP session disconnected" + fields: *rdp_transition_fields + + # EventID 4688: A new process has been created + - name: process_creation + event_id: "4688" + description: "Process creation event" + fields: + - name: SubjectUserSid + type: sid + required: true + description: "SID of account that created the process" + + - name: SubjectUserName + type: string + required: true + description: "Account name that created the process" + + - name: SubjectDomainName + type: string + required: true + description: "Domain of account that created the process" + + - name: SubjectLogonId + type: hex_string + required: true + description: "Logon ID of the account that created the process" + + - name: NewProcessId + type: hex_string + required: true + description: "Process ID of the newly created process" + + - name: NewProcessName + type: string + required: true + description: "Full path of the newly created process" + + - name: TokenElevationType + type: string + required: true + description: "Token elevation type (%%1936=Type1, %%1937=Type2, %%1938=Type3)" + + - name: ProcessId + type: hex_string + required: true + description: "Process ID of the creator process" + + - name: CommandLine + type: string + required: false + description: "Command line of the new process" + + - name: TargetUserSid + type: sid + required: false + description: "SID of target user for new process" + + - name: TargetUserName + type: string + required: false + description: "Target user name for new process" + + - name: TargetDomainName + type: string + required: false + description: "Target domain for new process" + + - name: TargetLogonId + type: hex_string + required: false + description: "Target logon ID for new process" + + - name: ParentProcessName + type: string + required: false + description: "Full path of the parent process" + + - name: MandatoryLabel + type: string + required: false + description: "Mandatory integrity label" + + # EventID 4625: An account failed to log on + - name: failed_logon + event_id: "4625" + description: "Failed logon event" + fields: + - name: SubjectUserSid + type: sid + required: true + description: "SID of account reporting the failure" + + - name: SubjectUserName + type: string + required: true + description: "Account name reporting the failure" + + - name: SubjectDomainName + type: string + required: true + description: "Domain of account reporting the failure" + + - name: SubjectLogonId + type: hex_string + required: true + description: "Logon ID of the reporting account" + + - name: TargetUserSid + type: sid + required: true + description: "SID of the account that failed to log on" + + - name: TargetUserName + type: string + required: true + description: "Account name that failed to log on" + + - name: TargetDomainName + type: string + required: true + description: "Domain of the account that failed to log on" + + - name: Status + type: hex_string + required: true + description: "Failure status code (e.g., 0xC000006D)" + + - name: SubStatus + type: hex_string + required: true + description: "Sub-status code for failure reason" + + - name: FailureReason + type: string + required: true + description: "Human-readable failure reason" + + - name: LogonType + type: integer + required: true + description: "Type of logon attempted" + constraints: + allowed_values: [2, 3, 4, 5, 7, 8, 9, 10, 11] + + - name: LogonProcessName + type: string + required: false + description: "Logon process name" + + - name: AuthenticationPackageName + type: string + required: false + description: "Authentication package used" + + - name: WorkstationName + type: string + required: false + description: "Source workstation name" + + - name: IpAddress + type: string + required: true + description: "Source IP address" + + - name: IpPort + type: integer + required: false + description: "Source port number" + constraints: + min_value: 0 + max_value: 65535 + + - name: TransmittedServices + type: string + required: false + description: "List of transmitted services" + + - name: LmPackageName + type: string + required: false + description: "LAN Manager package name" + + - name: KeyLength + type: integer + required: false + description: "Length of NTLM session security key" + + - name: ProcessId + type: hex_string + required: false + description: "Process ID of the logon process" + + - name: ProcessName + type: string + required: false + description: "Full path of the logon process executable" + + - name: RemoteUserID + type: sid + required: false + description: "SID of the remote user" + + - name: RemoteMachineID + type: sid + required: false + description: "SID of the remote machine" + + # EventID 4672: Special privileges assigned to new logon + - name: special_privileges + event_id: "4672" + description: "Special privileges assigned to new logon" + fields: + - name: SubjectUserSid + type: sid + required: true + description: "SID of the privileged account" + + - name: SubjectUserName + type: string + required: true + description: "Account name with special privileges" + + - name: SubjectDomainName + type: string + required: true + description: "Domain of the privileged account" + + - name: SubjectLogonId + type: hex_string + required: true + description: "Logon ID of the privileged session" + + - name: PrivilegeList + type: string + required: true + description: "List of assigned special privileges" + + # EventID 4800: The workstation was locked + - name: workstation_locked + event_id: "4800" + description: "Workstation locked" + fields: + - name: TargetUserSid + type: sid + required: true + description: "SID of the user who locked the workstation" + + - name: TargetUserName + type: string + required: true + description: "Account name of the user" + + - name: TargetDomainName + type: string + required: true + description: "Domain of the user" + + - name: TargetLogonId + type: hex_string + required: true + description: "Logon ID of the locked session" + + - name: SessionId + type: integer + required: true + description: "Terminal Services session ID" + + # EventID 4801: The workstation was unlocked + - name: workstation_unlocked + event_id: "4801" + description: "Workstation unlocked" + fields: + - name: TargetUserSid + type: sid + required: true + description: "SID of the user who unlocked the workstation" + + - name: TargetUserName + type: string + required: true + description: "Account name of the user" + + - name: TargetDomainName + type: string + required: true + description: "Domain of the user" + + - name: TargetLogonId + type: hex_string + required: true + description: "Logon ID of the unlocked session" + + - name: SessionId + type: integer + required: true + description: "Terminal Services session ID" + + # EventID 4689: A process has exited + - name: process_termination + event_id: "4689" + description: "Process termination event" + fields: + - name: SubjectUserSid + type: sid + required: true + description: "SID of account under which process ran" + + - name: SubjectUserName + type: string + required: true + description: "Account name under which process ran" + + - name: SubjectDomainName + type: string + required: true + description: "Domain of account under which process ran" + + - name: SubjectLogonId + type: hex_string + required: true + description: "Logon ID of the session" + + - name: Status + type: hex_string + required: true + description: "Process exit status code" + + - name: ProcessId + type: hex_string + required: true + description: "Process ID of the exited process" + + - name: ProcessName + type: string + required: true + description: "Full path of the exited process" + + # EventID 4648: A logon was attempted using explicit credentials + - name: explicit_credentials + event_id: "4648" + description: "Explicit credentials logon (RunAs, scheduled tasks)" + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: LogonGuid + type: string + required: false + description: "GUID to correlate with Kerberos authentication" + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetLogonGuid + type: string + required: false + description: "GUID for target logon correlation" + - name: TargetServerName + type: string + required: true + - name: TargetInfo + type: string + required: false + - name: ProcessId + type: hex_string + required: true + - name: ProcessName + type: string + required: true + - name: IpAddress + type: string + required: false + - name: IpPort + type: integer + required: false + + # EventID 4768: A Kerberos authentication ticket (TGT) was requested + - name: kerberos_tgt + event_id: "4768" + description: "Kerberos TGT request" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: ServiceName + type: string + required: true + description: "Always krbtgt for TGT requests" + - name: ServiceSid + type: sid + required: true + - name: TicketOptions + type: hex_string + required: true + - name: Status + type: hex_string + required: true + - name: TicketEncryptionType + type: hex_string + required: true + - name: PreAuthType + type: integer + required: false + - name: IpAddress + type: string + required: true + - name: IpPort + type: integer + required: false + - name: CertIssuerName + type: string + required: false + - name: CertSerialNumber + type: string + required: false + - name: CertThumbprint + type: string + required: false + + # EventID 4769: A Kerberos service ticket was requested + - name: kerberos_service_ticket + event_id: "4769" + description: "Kerberos service ticket request" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: ServiceName + type: string + required: true + - name: ServiceSid + type: sid + required: true + - name: TicketOptions + type: hex_string + required: true + - name: TicketEncryptionType + type: hex_string + required: true + - name: IpAddress + type: string + required: true + - name: IpPort + type: integer + required: false + - name: Status + type: hex_string + required: true + - name: LogonGuid + type: string + required: false + - name: TransmittedServices + type: string + required: false + + # EventID 4776: The computer attempted to validate the credentials + - name: ntlm_validation + event_id: "4776" + description: "NTLM credential validation" + fields: + - name: PackageName + type: string + required: true + description: "Always MICROSOFT_AUTHENTICATION_PACKAGE_V1_0" + - name: TargetUserName + type: string + required: true + - name: Workstation + type: string + required: true + - name: Status + type: hex_string + required: true + + # EventID 5156: Windows Filtering Platform has permitted a connection + - name: wfp_connection + event_id: "5156" + description: "WFP connection allowed" + fields: + - name: ProcessID + type: integer + required: true + - name: Application + type: string + required: true + - name: Direction + type: string + required: true + description: "%%14592=Inbound, %%14593=Outbound" + - name: SourceAddress + type: string + required: true + - name: SourcePort + type: integer + required: true + - name: DestAddress + type: string + required: true + - name: DestPort + type: integer + required: true + - name: Protocol + type: integer + required: true + description: "6=TCP, 17=UDP" + - name: FilterRTID + type: integer + required: false + - name: LayerName + type: string + required: false + - name: LayerRTID + type: integer + required: false + - name: RemoteUserID + type: sid + required: false + - name: RemoteMachineID + type: sid + required: false + + # EventID 4771: Kerberos pre-authentication failed + - name: kerberos_preauth_failed + event_id: "4771" + description: "Kerberos pre-authentication failed" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: ServiceName + type: string + required: true + - name: TicketOptions + type: hex_string + required: true + - name: Status + type: hex_string + required: true + - name: PreAuthType + type: integer + required: false + - name: IpAddress + type: string + required: true + - name: IpPort + type: integer + required: false + - name: CertIssuerName + type: string + required: false + - name: CertSerialNumber + type: string + required: false + - name: CertThumbprint + type: string + required: false + + # EventID 1102: Security log cleared + - name: log_cleared + event_id: "1102" + description: "Security audit log was cleared" + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + + # EventID 4697: A service was installed in the system + - name: service_installed + event_id: "4697" + description: "Service installed in the system" + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: ServiceName + type: string + required: true + - name: ServiceFileName + type: string + required: true + - name: ServiceType + type: string + required: false + - name: ServiceStartType + type: string + required: false + - name: ServiceAccount + type: string + required: false + + # EventID 4698/4699/4700/4701: Scheduled task events + - name: scheduled_task + event_id: "4698" + description: "Scheduled task created/deleted/enabled/disabled" + fields: + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: TaskName + type: string + required: true + - name: TaskContent + type: string + required: false + + # EventID 4728/4729/4732/4733/4756/4757: Group membership changes + - name: group_membership_change + event_id: "4728" + description: "Member added/removed from security group" + fields: + - name: MemberName + type: string + required: false + - name: MemberSid + type: sid + required: true + - name: TargetUserName + type: string + required: true + description: "Group name" + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: PrivilegeList + type: string + required: false + + # EventID 4720: User account created + - name: account_created + event_id: "4720" + description: "A user account was created" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: SamAccountName + type: string + required: false + - name: DisplayName + type: string + required: false + - name: UserPrincipalName + type: string + required: false + - name: HomeDirectory + type: string + required: false + - name: HomePath + type: string + required: false + - name: ScriptPath + type: string + required: false + - name: ProfilePath + type: string + required: false + - name: UserWorkstations + type: string + required: false + - name: PasswordLastSet + type: string + required: false + - name: AccountExpires + type: string + required: false + - name: PrimaryGroupId + type: string + required: false + - name: AllowedToDelegateTo + type: string + required: false + - name: OldUacValue + type: string + required: false + - name: NewUacValue + type: string + required: false + - name: UserAccountControl + type: string + required: false + - name: UserParameters + type: string + required: false + - name: SidHistory + type: string + required: false + - name: LogonHours + type: string + required: false + - name: PrivilegeList + type: string + required: false + + # EventID 4723: Password change attempt + - name: password_change + event_id: "4723" + description: "An attempt was made to change an account password" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + + # EventID 4724: Password reset attempt + - name: password_reset + event_id: "4724" + description: "An attempt was made to reset an account password" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + + # EventID 4726: User account deleted + - name: account_deleted + event_id: "4726" + description: "A user account was deleted" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: PrivilegeList + type: string + required: false + + # EventID 4738: User account changed + - name: account_changed + event_id: "4738" + description: "A user account was changed" + fields: + - name: TargetUserName + type: string + required: true + - name: TargetDomainName + type: string + required: true + - name: TargetSid + type: sid + required: true + - name: SubjectUserSid + type: sid + required: true + - name: SubjectUserName + type: string + required: true + - name: SubjectDomainName + type: string + required: true + - name: SubjectLogonId + type: hex_string + required: true + - name: SamAccountName + type: string + required: false + - name: DisplayName + type: string + required: false + - name: UserPrincipalName + type: string + required: false + - name: HomeDirectory + type: string + required: false + - name: HomePath + type: string + required: false + - name: ScriptPath + type: string + required: false + - name: ProfilePath + type: string + required: false + - name: UserWorkstations + type: string + required: false + - name: PasswordLastSet + type: string + required: false + - name: AccountExpires + type: string + required: false + - name: PrimaryGroupId + type: string + required: false + - name: AllowedToDelegateTo + type: string + required: false + - name: OldUacValue + type: string + required: false + - name: NewUacValue + type: string + required: false + - name: UserAccountControl + type: string + required: false + - name: UserParameters + type: string + required: false + - name: SidHistory + type: string + required: false + - name: LogonHours + type: string + required: false + - name: PrivilegeList + type: string + required: false + + - name: object_handle_requested + event_id: "4656" + description: "A handle to an object was requested" + fields: + - {name: SubjectUserSid, type: sid, required: true} + - {name: SubjectUserName, type: string, required: true} + - {name: SubjectDomainName, type: string, required: true} + - {name: SubjectLogonId, type: hex_string, required: true} + - {name: ObjectServer, type: string, required: true} + - {name: ObjectType, type: string, required: true} + - {name: ObjectName, type: string, required: true} + - {name: HandleId, type: hex_string, required: true} + - {name: TransactionId, type: string, required: true} + - {name: AccessList, type: string, required: true} + - {name: AccessReason, type: string, required: true} + - {name: AccessMask, type: hex_string, required: true} + - {name: PrivilegeList, type: string, required: true} + - {name: RestrictedSidCount, type: integer, required: true} + - {name: ProcessId, type: hex_string, required: true} + - {name: ProcessName, type: string, required: true} + - {name: ResourceAttributes, type: string, required: true} + + - name: object_handle_closed + event_id: "4658" + description: "A handle to an object was closed" + fields: + - {name: SubjectUserSid, type: sid, required: true} + - {name: SubjectUserName, type: string, required: true} + - {name: SubjectDomainName, type: string, required: true} + - {name: SubjectLogonId, type: hex_string, required: true} + - {name: ObjectServer, type: string, required: true} + - {name: HandleId, type: hex_string, required: true} + - {name: ProcessId, type: hex_string, required: true} + - {name: ProcessName, type: string, required: true} + + - name: object_access + event_id: "4663" + description: "An attempt was made to access an object" + fields: + - {name: SubjectUserSid, type: sid, required: true} + - {name: SubjectUserName, type: string, required: true} + - {name: SubjectDomainName, type: string, required: true} + - {name: SubjectLogonId, type: hex_string, required: true} + - {name: ObjectServer, type: string, required: true} + - {name: ObjectType, type: string, required: true} + - {name: ObjectName, type: string, required: true} + - {name: HandleId, type: hex_string, required: true} + - {name: AccessList, type: string, required: true} + - {name: AccessMask, type: hex_string, required: true} + - {name: ProcessId, type: hex_string, required: true} + - {name: ProcessName, type: string, required: true} + - {name: ResourceAttributes, type: string, required: true} + + - name: network_share_access + event_id: "5140" + description: "A network share object was accessed" + fields: + - {name: SubjectUserSid, type: sid, required: true} + - {name: SubjectUserName, type: string, required: true} + - {name: SubjectDomainName, type: string, required: true} + - {name: SubjectLogonId, type: hex_string, required: true} + - {name: ObjectType, type: string, required: true} + - {name: IpAddress, type: ip_address, required: true} + - {name: IpPort, type: integer, required: true} + - {name: ShareName, type: string, required: true} + - {name: ShareLocalPath, type: string, required: true} + - {name: AccessMask, type: hex_string, required: true} + - {name: AccessList, type: string, required: true} + + - name: network_share_access_check + event_id: "5145" + description: "Network share access was checked" + fields: + - {name: SubjectUserSid, type: sid, required: true} + - {name: SubjectUserName, type: string, required: true} + - {name: SubjectDomainName, type: string, required: true} + - {name: SubjectLogonId, type: hex_string, required: true} + - {name: ObjectType, type: string, required: true} + - {name: IpAddress, type: ip_address, required: true} + - {name: IpPort, type: integer, required: true} + - {name: ShareName, type: string, required: true} + - {name: ShareLocalPath, type: string, required: true} + - {name: RelativeTargetName, type: string, required: true} + - {name: AccessMask, type: hex_string, required: true} + - {name: AccessList, type: string, required: true} + - {name: AccessReason, type: string, required: true} + +# Output template in Windows Event Log XML format +output: + format: xml + file_extension: ".xml" + encoding: "utf-8" + header_template: | + + + footer_template: "" + # Template formatting: Jinja2 conditionals ({% if %}, {% elif %}, {% endif %}) are on + # separate lines for readability. This doesn't affect XML output whitespace. + template: | + + + {% if EventID == 1102 %} + + {% else %} + + {% endif %} + {{ EventID }} + {{ 2 if EventID in [4688, 4624] else 1 if EventID in [4656, 4663, 5156] else 0 }} + {{ Level }} + {{ {1102: 104, 4624: 12544, 4625: 12544, 4634: 12545, 4648: 12544, 4656: 12800, 4658: 12800, 4663: 12800, 4672: 12548, 4688: 13312, 4689: 13313, 4697: 12289, 4698: 12804, 4699: 12804, 4700: 12804, 4701: 12804, 4720: 13824, 4723: 13824, 4724: 13824, 4726: 13824, 4728: 13826, 4729: 13826, 4732: 13826, 4733: 13826, 4738: 13824, 4756: 13826, 4757: 13826, 4768: 14339, 4769: 14337, 4770: 14339, 4771: 14339, 4776: 14336, 4778: 12551, 4779: 12551, 4800: 12551, 4801: 12551, 5140: 12808, 5145: 12811, 5156: 12810}.get(EventID, 0) }} + 0 + {{ Keywords | default('0x8020000000000000') }} + + {{ EventRecordID }} + + + {{ Channel }} + {{ Computer }} + {% if EventID == 1102 %} + + {% else %} + + {% endif %} + + {% if EventID == 1102 %} + + + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + + + {% else %} + + {% if EventID == 4624 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ TargetUserSid }} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetLogonId }} + {{ LogonType }} + {{ LogonGuid | default('{00000000-0000-0000-0000-000000000000}') }} + {{ LogonProcessName | default('-') }} + {{ AuthenticationPackageName | default('-') }} + {{ WorkstationName }} + {{ TransmittedServices | default('-') }} + {{ LmPackageName | default('-') }} + {{ KeyLength | default(0) }} + {{ ProcessId | default('0x0') }} + {{ ProcessName | default('-') }} + {{ IpAddress }} + {{ '-' if IpAddress == '-' else (IpPort | default(0)) }} + {{ ImpersonationLevel | default('%%1833') }} + {{ RestrictedAdminMode | default('-') }} + {{ TargetOutboundUserName | default('-') }} + {{ TargetOutboundDomainName | default('-') }} + {{ VirtualAccount | default('%%1843') }} + {{ TargetLinkedLogonId | default('0x0') }} + {{ ElevatedToken | default('%%1842') }} + {% elif EventID == 4634 %} + {{ TargetUserSid }} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetLogonId }} + {{ LogonType }} + {% elif EventID in [4778, 4779] %} + {{ AccountName }} + {{ AccountDomain }} + {{ LogonID }} + {{ SessionName }} + {{ ClientName }} + {{ ClientAddress }} + {{ ClientPort }} + {% elif EventID == 4688 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId | default('0x0') }} + {{ NewProcessId | default('0x0') }} + {{ NewProcessName }} + {{ TokenElevationType }} + {{ ProcessId | default('0x0') }} + {{ CommandLine | default('') }} + {{ TargetUserSid | default('-') }} + {{ TargetUserName | default('-') }} + {{ TargetDomainName | default('-') }} + {{ TargetLogonId | default('0x0') }} + {{ ParentProcessName | default('-') }} + {{ MandatoryLabel | default('S-1-16-8192') }} + {% elif EventID == 4625 %} + {{ SubjectUserSid }} + {{ SubjectUserName | default('-') }} + {{ SubjectDomainName | default('-') }} + {{ SubjectLogonId | default('0x0') }} + {{ TargetUserSid }} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ Status }} + {{ FailureReason }} + {{ SubStatus }} + {{ LogonType }} + {{ LogonProcessName | default('NtLmSsp') }} + {{ AuthenticationPackageName | default('NTLM') }} + {{ WorkstationName | default('-') }} + {{ TransmittedServices | default('-') }} + {{ LmPackageName | default('-') }} + {{ KeyLength | default(0) }} + {{ ProcessId | default('0x0') }} + {{ ProcessName | default('-') }} + {{ IpAddress }} + {{ '-' if IpAddress == '-' else (IpPort | default(0)) }} + {% elif EventID == 4672 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId | default('0x0') }} + {{ PrivilegeList }} + {% elif EventID == 4689 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId | default('0x0') }} + {{ Status | default('0x0') }} + {{ ProcessId | default('0x0') }} + {{ ProcessName }} + {% elif EventID == 4648 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ LogonGuid | default('{00000000-0000-0000-0000-000000000000}') }} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetLogonGuid | default('{00000000-0000-0000-0000-000000000000}') }} + {{ TargetServerName }} + {{ TargetInfo | default('-') }} + {{ ProcessId }} + {{ ProcessName }} + {{ IpAddress | default('-') }} + {{ '-' if (IpAddress | default('-')) == '-' else (IpPort | default(0)) }} + {% elif EventID == 4768 %} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetSid }} + {{ ServiceName }} + {{ ServiceSid }} + {{ TicketOptions }} + {{ Status }} + {{ TicketEncryptionType }} + {{ PreAuthType | default(2) }} + {{ IpAddress }} + {{ '-' if IpAddress == '-' else (IpPort | default(0)) }} + {{ CertIssuerName | default('') }} + {{ CertSerialNumber | default('') }} + {{ CertThumbprint | default('') }} + {% elif EventID == 4769 %} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ ServiceName }} + {{ ServiceSid }} + {{ TicketOptions }} + {{ TicketEncryptionType }} + {{ IpAddress }} + {{ '-' if IpAddress == '-' else (IpPort | default(0)) }} + {{ Status }} + {{ LogonGuid | default('{00000000-0000-0000-0000-000000000000}') }} + {{ TransmittedServices | default('-') }} + {% elif EventID == 4770 %} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ ServiceName }} + {{ ServiceSid }} + {{ TicketOptions }} + {{ TicketEncryptionType }} + {{ IpAddress }} + {{ '-' if IpAddress == '-' else (IpPort | default(0)) }} + {{ Status | default('0x0') }} + {% elif EventID == 4776 %} + {{ PackageName }} + {{ TargetUserName }} + {{ Workstation }} + {{ Status }} + {% elif EventID == 4771 %} + {{ TargetUserName }} + {{ TargetSid }} + {{ ServiceName }} + {{ TicketOptions }} + {{ Status }} + {{ PreAuthType | default(0) }} + {{ IpAddress }} + {{ '-' if IpAddress == '-' else (IpPort | default(0)) }} + {{ CertIssuerName | default('') }} + {{ CertSerialNumber | default('') }} + {{ CertThumbprint | default('') }} + {% elif EventID == 4697 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ ServiceName }} + {{ ServiceFileName }} + {{ ServiceType | default('0x10') }} + {{ ServiceStartType | default('3') }} + {{ ServiceAccount | default('LocalSystem') }} + {% elif EventID in [4698, 4699, 4700, 4701] %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ TaskName }} + {{ TaskContent | default('') }} + {% elif EventID in [4728, 4729, 4732, 4733, 4756, 4757] %} + {{ MemberName | default('-') }} + {{ MemberSid }} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetSid }} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ PrivilegeList | default('-') }} + {% elif EventID in [4720, 4738] %} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetSid }} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ PrivilegeList | default('-') }} + {{ SamAccountName | default('-') }} + {{ DisplayName | default('-') }} + {{ UserPrincipalName | default('-') }} + {{ HomeDirectory | default('-') }} + {{ HomePath | default('-') }} + {{ ScriptPath | default('-') }} + {{ ProfilePath | default('-') }} + {{ UserWorkstations | default('-') }} + {{ PasswordLastSet | default('-') }} + {{ AccountExpires | default('-') }} + {{ PrimaryGroupId | default('513') }} + {{ AllowedToDelegateTo | default('-') }} + {{ OldUacValue | default('0x0') }} + {{ NewUacValue | default('0x15') }} + {{ UserAccountControl | default('-') }} + {{ UserParameters | default('-') }} + {{ SidHistory | default('-') }} + {{ LogonHours | default('-') }} + {% elif EventID in [4723, 4724, 4726] %} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetSid }} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {% if EventID in [4723, 4726] %} + {{ PrivilegeList | default('-') }} + {% endif %} + {% elif EventID in [4800, 4801] %} + {{ TargetUserSid }} + {{ TargetUserName }} + {{ TargetDomainName }} + {{ TargetLogonId }} + {{ SessionId }} + {% elif EventID == 4656 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ ObjectServer }} + {{ ObjectType }} + {{ ObjectName }} + {{ HandleId }} + {{ TransactionId }} + {{ AccessList }} + {{ AccessReason }} + {{ AccessMask }} + {{ PrivilegeList }} + {{ RestrictedSidCount }} + {{ ProcessId }} + {{ ProcessName }} + {{ ResourceAttributes }} + {% elif EventID == 4658 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ ObjectServer }} + {{ HandleId }} + {{ ProcessId }} + {{ ProcessName }} + {% elif EventID == 4663 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ ObjectServer }} + {{ ObjectType }} + {{ ObjectName }} + {{ HandleId }} + {{ AccessList }} + {{ AccessMask }} + {{ ProcessId }} + {{ ProcessName }} + {{ ResourceAttributes }} + {% elif EventID == 5140 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ ObjectType }} + {{ IpAddress }} + {{ IpPort }} + {{ ShareName }} + {{ ShareLocalPath }} + {{ AccessMask }} + {{ AccessList }} + {% elif EventID == 5145 %} + {{ SubjectUserSid }} + {{ SubjectUserName }} + {{ SubjectDomainName }} + {{ SubjectLogonId }} + {{ ObjectType }} + {{ IpAddress }} + {{ IpPort }} + {{ ShareName }} + {{ ShareLocalPath }} + {{ RelativeTargetName }} + {{ AccessMask }} + {{ AccessList }} + {{ AccessReason }} + {% elif EventID == 5156 %} + {{ ProcessID }} + {{ Application }} + {{ Direction }} + {{ SourceAddress }} + {{ SourcePort }} + {{ DestAddress }} + {{ DestPort }} + {{ Protocol }} + {{ FilterRTID | default(0) }} + {{ LayerName | default('%%14610' if Direction == '%%14592' else '%%14611') }} + {{ LayerRTID | default(44 if Direction == '%%14592' else 48) }} + {{ RemoteUserID | default('S-1-0-0') }} + {{ RemoteMachineID | default('S-1-0-0') }} + {% endif %} + + {% endif %} + + +# Cross-field validators using JSON Logic +validators: + # Network logons (type 3) should have valid IP address (not "-") + - if: + - and: + - "==": [{"var": "EventID"}, 4624] + - "==": [{"var": "LogonType"}, 3] + then: + "!=": [{"var": "IpAddress"}, "-"] diff --git a/tests/fixtures/record_validation/legacy/zeek_conn.yaml b/tests/fixtures/record_validation/legacy/zeek_conn.yaml new file mode 100644 index 000000000..506d1709e --- /dev/null +++ b/tests/fixtures/record_validation/legacy/zeek_conn.yaml @@ -0,0 +1,233 @@ +# zeek_conn format definition — Zeek conn.log format (JSON output) +# +# Category: network +# Standalone: yes (no cross-file dependencies) +# Note: Field names may be referenced by evaluation rules in config/evaluation/ +# +# Full schema: see commands/eforge/references/config-formats.md + +name: zeek_conn +version: "1.0" +description: "Zeek conn.log format (JSON output)" +category: network + +# All Zeek conn.log fields +fields: + - name: ts + type: timestamp + required: true + description: "Timestamp of connection start" + + - name: uid + type: string + required: true + description: "Unique connection identifier" + constraints: + pattern: "^[A-Za-z0-9]{17,19}$" + + - name: id.orig_h + type: ip_address + required: true + description: "Originator IP address" + + - name: id.orig_p + type: port + required: true + description: "Originator port" + + - name: id.resp_h + type: ip_address + required: true + description: "Responder IP address" + + - name: id.resp_p + type: port + required: true + description: "Responder port" + + - name: proto + type: enum + required: true + description: "Transport protocol" + constraints: + allowed_values: ["tcp", "udp", "icmp"] + + - name: service + type: string + required: false + description: "Application protocol (http, ssh, dns, etc.)" + + - name: duration + type: float + required: false + description: "Connection duration in seconds (unset if not ended)" + + - name: orig_bytes + type: integer + required: false + description: "Bytes sent by originator" + constraints: + min_value: 0 + + - name: resp_bytes + type: integer + required: false + description: "Bytes sent by responder" + constraints: + min_value: 0 + + - name: conn_state + type: enum + required: true + description: "Connection state" + constraints: + allowed_values: ["S0", "S1", "SF", "REJ", "S2", "S3", "RSTO", "RSTR", "RSTOS0", "RSTRH", "SH", "SHR", "OTH"] + + - name: local_orig + type: boolean + required: false + description: "Connection originated locally" + + - name: local_resp + type: boolean + required: false + description: "Connection responded to locally" + + - name: missed_bytes + type: integer + required: false + description: "Bytes missed in content gaps" + constraints: + min_value: 0 + + - name: history + type: string + required: false + description: "Connection state history (flags)" + + - name: orig_pkts + type: integer + required: false + description: "Packets sent by originator" + constraints: + min_value: 0 + + - name: orig_ip_bytes + type: integer + required: false + description: "IP-level bytes sent by originator" + constraints: + min_value: 0 + + - name: resp_pkts + type: integer + required: false + description: "Packets sent by responder" + constraints: + min_value: 0 + + - name: resp_ip_bytes + type: integer + required: false + description: "IP-level bytes sent by responder" + constraints: + min_value: 0 + + - name: ip_proto + type: integer + required: false + description: "IP protocol number (6=TCP, 17=UDP, 1=ICMP)" + + - name: tunnel_parents + type: string + required: false + description: "Tunnel UIDs if connection was tunneled" + +# Output template in Zeek JSON format +output: + format: json + file_extension: ".json" + encoding: "utf-8" + + # JSON template (no header needed - JSON is self-describing) + # Note: For fields with dots, emitter should pass data as 'data' context variable + # + # Template formatting: Uses {%- and -%} for whitespace control to keep conditionals + # readable without affecting JSON output. The '-' strips whitespace, allowing each + # conditional to be on its own line while commas stay correctly positioned in output. + template: | + { + "ts": {{ ts | tojson }}, + "uid": {{ uid | tojson }}, + "id.orig_h": {{ data['id.orig_h'] | tojson }}, + "id.orig_p": {{ data['id.orig_p'] | tojson }}, + "id.resp_h": {{ data['id.resp_h'] | tojson }}, + "id.resp_p": {{ data['id.resp_p'] | tojson }}, + "proto": {{ proto | tojson }} + {%- if service %}, + "service": {{ service | tojson }} + {%- endif %} + {%- if duration %}, + "duration": {{ duration | tojson }} + {%- endif %} + {%- if orig_bytes is not none %}, + "orig_bytes": {{ orig_bytes | tojson }} + {%- endif %} + {%- if resp_bytes is not none %}, + "resp_bytes": {{ resp_bytes | tojson }} + {%- endif %}, + "conn_state": {{ conn_state | tojson }} + {%- if local_orig is not none %}, + "local_orig": {{ local_orig | tojson }} + {%- endif %} + {%- if local_resp is not none %}, + "local_resp": {{ local_resp | tojson }} + {%- endif %} + {%- if missed_bytes is not none %}, + "missed_bytes": {{ missed_bytes | tojson }} + {%- endif %} + {%- if history %}, + "history": {{ history | tojson }} + {%- endif %} + {%- if orig_pkts is not none %}, + "orig_pkts": {{ orig_pkts | tojson }} + {%- endif %} + {%- if orig_ip_bytes is not none %}, + "orig_ip_bytes": {{ orig_ip_bytes | tojson }} + {%- endif %} + {%- if resp_pkts is not none %}, + "resp_pkts": {{ resp_pkts | tojson }} + {%- endif %} + {%- if resp_ip_bytes is not none %}, + "resp_ip_bytes": {{ resp_ip_bytes | tojson }} + {%- endif %} + {%- if ip_proto is not none %}, + "ip_proto": {{ ip_proto | tojson }} + {%- endif %} + {%- if tunnel_parents %}, + "tunnel_parents": {{ tunnel_parents | tojson }} + {%- endif %} + } + +# Cross-field validators +validators: + # If duration is set, it should be non-negative + - if: + - "!=": [{"var": "duration"}, null] + then: + ">=": [{"var": "duration"}, 0] + + # If service is set, duration should also be set (established connection) + - if: + - "!=": [{"var": "service"}, null] + then: + "!=": [{"var": "duration"}, null] + + # SF state (normal connection) should have duration and bytes + - if: + - "==": [{"var": "conn_state"}, "SF"] + then: + and: + - "!=": [{"var": "duration"}, null] + - "!=": [{"var": "orig_bytes"}, null] + - "!=": [{"var": "resp_bytes"}, null] diff --git a/tests/fixtures/record_validation/native/packet_filter.json b/tests/fixtures/record_validation/native/packet_filter.json new file mode 100644 index 000000000..e5e83c828 --- /dev/null +++ b/tests/fixtures/record_validation/native/packet_filter.json @@ -0,0 +1 @@ +{"ts": 1750000000.0, "node": "example", "filter": "example", "init": false, "success": false} diff --git a/tests/fixtures/record_validation/native/reporter.json b/tests/fixtures/record_validation/native/reporter.json new file mode 100644 index 000000000..2b86fb5d8 --- /dev/null +++ b/tests/fixtures/record_validation/native/reporter.json @@ -0,0 +1 @@ +{"ts": 1750000000.0, "level": "example", "message": "example", "location": "example"} diff --git a/tests/fixtures/record_validation/native/weird.json b/tests/fixtures/record_validation/native/weird.json new file mode 100644 index 000000000..2925895c0 --- /dev/null +++ b/tests/fixtures/record_validation/native/weird.json @@ -0,0 +1 @@ +{"ts": 1750000000.0, "name": "example", "notice": false, "peer": "example"} diff --git a/tests/fixtures/record_validation/rule_cases.json b/tests/fixtures/record_validation/rule_cases.json new file mode 100644 index 000000000..aa29e5aa6 --- /dev/null +++ b/tests/fixtures/record_validation/rule_cases.json @@ -0,0 +1,569 @@ +[ + { + "rule": "ecar.legacy-1", + "pass": { + "object": "PROCESS", + "pid": 123 + }, + "fail": { + "object": "PROCESS" + } + }, + { + "rule": "ecar.legacy-2", + "pass": { + "object": "PROCESS", + "action": "CREATE", + "tid": 123 + }, + "fail": { + "object": "PROCESS", + "action": "CREATE" + } + }, + { + "rule": "ecar.legacy-3", + "pass": { + "object": "PROCESS", + "action": "TERMINATE", + "tid": 123 + }, + "fail": { + "object": "PROCESS", + "action": "TERMINATE" + } + }, + { + "rule": "ecar.legacy-4", + "pass": { + "objectID": "abc" + }, + "fail": {} + }, + { + "rule": "ecar.legacy-5", + "pass": { + "object": "PROCESS", + "action": "CREATE", + "image_path": "/usr/bin/bash" + }, + "fail": { + "object": "PROCESS", + "action": "CREATE" + } + }, + { + "rule": "ecar.legacy-6", + "pass": { + "object": "PROCESS", + "action": "CREATE", + "ppid": 1 + }, + "fail": { + "object": "PROCESS", + "action": "CREATE" + } + }, + { + "rule": "ecar.legacy-7", + "pass": { + "object": "PROCESS", + "action": "CREATE", + "command_line": "bash" + }, + "fail": { + "object": "PROCESS", + "action": "CREATE" + } + }, + { + "rule": "ecar.legacy-8", + "pass": { + "object": "THREAD", + "action": "REMOTE_CREATE", + "target_pid": 2, + "image_path": "app.exe" + }, + "fail": { + "object": "THREAD", + "action": "REMOTE_CREATE", + "image_path": "app.exe" + } + }, + { + "rule": "ecar.legacy-9", + "pass": { + "object": "PROCESS", + "action": "OPEN", + "image_path": "app.exe" + }, + "fail": { + "object": "PROCESS", + "action": "OPEN" + } + }, + { + "rule": "ecar.legacy-10", + "pass": { + "object": "FLOW", + "src_ip": "10.0.0.1", + "dst_ip": "10.0.0.2" + }, + "fail": { + "object": "FLOW", + "dst_ip": "10.0.0.2" + } + }, + { + "rule": "ecar.legacy-11", + "pass": { + "object": "SERVICE", + "action": "CREATE", + "service_name": "sshd" + }, + "fail": { + "object": "SERVICE", + "action": "CREATE" + } + }, + { + "rule": "ecar.legacy-12", + "pass": { + "object": "USER_SESSION", + "action": "LOGIN", + "principal": "alice" + }, + "fail": { + "object": "USER_SESSION", + "action": "LOGIN" + } + }, + { + "rule": "windows_event_security.legacy-1", + "pass": { + "EventID": 4624, + "LogonType": 3, + "TargetUserName": "alice", + "IpAddress": "10.0.0.1" + }, + "fail": { + "EventID": 4624, + "LogonType": 3, + "TargetUserName": "alice" + } + }, + { + "rule": "windows_event_security.legacy-2", + "pass": { + "EventID": 4624, + "LogonType": 2, + "WorkstationName": "WS01" + }, + "fail": { + "EventID": 4624, + "LogonType": 2 + } + }, + { + "rule": "windows_event_security.legacy-3", + "pass": { + "EventID": 4688, + "NewProcessName": "C:\\Windows\\app.exe" + }, + "fail": { + "EventID": 4688 + } + }, + { + "rule": "windows_event_security.legacy-4", + "pass": { + "EventID": 4634, + "LogonType": 3 + }, + "fail": { + "EventID": 4634 + } + }, + { + "rule": "windows_event_security.legacy-5", + "pass": { + "EventID": 4624, + "TargetUserSid": "S-1-5-18" + }, + "fail": { + "EventID": 4624 + } + }, + { + "rule": "windows_event_security.legacy-6", + "pass": { + "EventID": 4625, + "Status": "0xc000006d", + "TargetUserName": "alice" + }, + "fail": { + "EventID": 4625, + "TargetUserName": "alice" + } + }, + { + "rule": "windows_event_security.legacy-7", + "pass": { + "EventID": 4672, + "PrivilegeList": "SeDebugPrivilege" + }, + "fail": { + "EventID": 4672 + } + }, + { + "rule": "windows_event_security.legacy-8", + "pass": { + "EventID": 4689, + "ProcessName": "C:\\Windows\\app.exe", + "ProcessId": "0x120" + }, + "fail": { + "EventID": 4689, + "ProcessId": "0x120" + } + }, + { + "rule": "windows_event_security.legacy-9", + "pass": { + "EventID": 4768, + "ServiceName": "krbtgt", + "IpAddress": "10.0.0.1" + }, + "fail": { + "EventID": 4768, + "IpAddress": "10.0.0.1" + } + }, + { + "rule": "windows_event_security.legacy-10", + "pass": { + "EventID": 4769, + "ServiceName": "HOST/ws01", + "IpAddress": "10.0.0.1" + }, + "fail": { + "EventID": 4769, + "IpAddress": "10.0.0.1" + } + }, + { + "rule": "windows_event_security.legacy-11", + "pass": { + "EventID": 4776, + "Workstation": "WS01", + "TargetUserName": "alice" + }, + "fail": { + "EventID": 4776, + "TargetUserName": "alice" + } + }, + { + "rule": "windows_event_security.legacy-12", + "pass": { + "EventID": 4771, + "Status": "0x18", + "TargetUserName": "alice" + }, + "fail": { + "EventID": 4771, + "TargetUserName": "alice" + } + }, + { + "rule": "windows_event_security.legacy-13", + "pass": { + "EventID": 5156, + "Direction": "%%14592", + "SourceAddress": "10.0.0.1", + "DestAddress": "10.0.0.2" + }, + "fail": { + "EventID": 5156, + "SourceAddress": "10.0.0.1", + "DestAddress": "10.0.0.2" + } + }, + { + "rule": "windows_event_security.legacy-14", + "pass": { + "EventID": 4648, + "TargetServerName": "WS01", + "TargetUserName": "alice" + }, + "fail": { + "EventID": 4648, + "TargetUserName": "alice" + } + }, + { + "rule": "zeek_conn.legacy-1", + "pass": { + "conn_state": "SF", + "duration": 1.25 + }, + "fail": { + "conn_state": "SF" + } + }, + { + "rule": "zeek_conn.legacy-2", + "pass": { + "conn_state": "SF", + "orig_bytes": 0, + "resp_bytes": 0 + }, + "fail": { + "conn_state": "SF", + "resp_bytes": 0 + } + }, + { + "rule": "zeek_conn.legacy-3", + "pass": { + "proto": "icmp" + }, + "fail": { + "proto": "smtp" + } + }, + { + "rule": "zeek_conn.legacy-4", + "pass": { + "conn_state": "SF", + "proto": "tcp", + "duration": 0.001 + }, + "fail": { + "conn_state": "SF", + "proto": "tcp", + "duration": 0.0 + } + }, + { + "rule": "zeek_http.legacy-1", + "pass": { + "method": "CONNECT", + "status_code": 200, + "response_body_len": 0 + }, + "fail": { + "method": "CONNECT", + "status_code": 200, + "response_body_len": 10 + } + }, + { + "rule": "zeek_http.legacy-2", + "pass": { + "method": "TRACE" + }, + "fail": { + "method": "INVALID" + } + }, + { + "rule": "web_access.legacy-2", + "pass": { + "method": "TRACE" + }, + "fail": { + "method": "INVALID" + } + }, + { + "rule": "syslog.legacy-1", + "pass": { + "message": "sshd: accepted" + }, + "fail": { + "message": "" + } + }, + { + "rule": "syslog.legacy-2", + "pass": { + "hostname": "ws01" + }, + "fail": { + "hostname": "" + } + }, + { + "rule": "snort_alert.legacy-1", + "pass": { + "priority": 1 + }, + "fail": { + "priority": 100 + } + }, + { + "rule": "snort_alert.legacy-2", + "pass": { + "src_ip": "10.0.0.1", + "dst_ip": "10.0.0.2" + }, + "fail": { + "dst_ip": "10.0.0.2" + } + }, + { + "rule": "bash_history.legacy-1", + "pass": { + "command": "ls -la" + }, + "fail": { + "command": "" + } + }, + { + "rule": "bash_history.legacy-2", + "pass": { + "username": "alice" + }, + "fail": { + "username": "" + } + }, + { + "rule": "zeek_dns.legacy-1", + "pass": { + "query": "example.com" + }, + "fail": { + "query": "" + } + }, + { + "rule": "zeek_dns.legacy-2", + "pass": { + "rcode_name": "NOERROR" + }, + "fail": {} + }, + { + "rule": "web_access.legacy-1", + "pass": { + "status_code": 200 + }, + "fail": { + "status_code": 99 + } + }, + { + "rule": "ecar.object-action", + "pass": { + "object": "FILE", + "action": "RENAME" + }, + "fail": { + "object": "FILE", + "action": "LOGIN" + } + }, + { + "rule": "smb.rename-source", + "pass": { + "action": "SMB::FILE_RENAME", + "prev_name": "old.txt" + }, + "fail": { + "action": "SMB::FILE_RENAME", + "prev_name": "" + } + }, + { + "rule": "zeek_ocsp.interval", + "pass": { + "thisUpdate": 1, + "nextUpdate": 2 + }, + "fail": { + "thisUpdate": 3, + "nextUpdate": 2 + } + }, + { + "rule": "zeek_x509.interval", + "pass": { + "certificate.not_valid_before": 1, + "certificate.not_valid_after": 2 + }, + "fail": { + "certificate.not_valid_before": 3, + "certificate.not_valid_after": 2 + } + }, + { + "rule": "sysmon.source-family", + "pass": { + "EventID": 3, + "SourceIp": "2001:db8::1", + "SourceIsIpv6": "true" + }, + "fail": { + "EventID": 3, + "SourceIp": "2001:db8::1", + "SourceIsIpv6": "false" + } + }, + { + "rule": "sysmon.destination-family", + "pass": { + "EventID": 3, + "DestinationIp": "2001:db8::1", + "DestinationIsIpv6": "true" + }, + "fail": { + "EventID": 3, + "DestinationIp": "2001:db8::1", + "DestinationIsIpv6": "false" + } + }, + { + "rule": "dns.qtype-name", + "pass": { + "qtype": 1, + "qtype_name": "A" + }, + "fail": { + "qtype": 1, + "qtype_name": "AAAA" + } + }, + { + "rule": "dns.rcode-name", + "pass": { + "rcode": 0, + "rcode_name": "NOERROR" + }, + "fail": { + "rcode": 0, + "rcode_name": "NXDOMAIN" + } + }, + { + "rule": "dns.answer-ttls", + "pass": { + "answers": [ + "10.0.0.1" + ], + "TTLs": [ + 60.0 + ] + }, + "fail": { + "answers": [ + "10.0.0.1" + ], + "TTLs": [] + } + } +] diff --git a/tests/fixtures/record_validation/snare_full_variants.json b/tests/fixtures/record_validation/snare_full_variants.json new file mode 100644 index 000000000..6bb0288b4 --- /dev/null +++ b/tests/fixtures/record_validation/snare_full_variants.json @@ -0,0 +1,1086 @@ +[ + { + "format": "windows_event_security", + "variant": "logon", + "fields": { + "EventID": 4624, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "LogonType": 2, + "WorkstationName": "example", + "ProcessId": "0x1", + "ProcessName": "example", + "IpAddress": "example", + "IpPort": 1, + "LogonProcessName": "witness", + "AuthenticationPackageName": "witness", + "LogonGuid": "{11111111-1111-1111-1111-111111111111}", + "TransmittedServices": "witness", + "LmPackageName": "witness", + "KeyLength": 42, + "ImpersonationLevel": "witness", + "RestrictedAdminMode": "witness", + "TargetOutboundUserName": "witness", + "TargetOutboundDomainName": "witness", + "VirtualAccount": "witness", + "TargetLinkedLogonId": "0x12", + "ElevatedToken": "witness", + "RemoteUserID": "S-1-5-21-1-2-3-1001", + "RemoteMachineID": "S-1-5-21-1-2-3-1001" + } + }, + { + "format": "windows_event_security", + "variant": "logoff", + "fields": { + "EventID": 4634, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "LogonType": 2 + } + }, + { + "format": "windows_event_security", + "variant": "rdp_session_reconnect", + "fields": { + "EventID": 4778, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "AccountName": "example", + "AccountDomain": "example", + "LogonID": "0x1", + "SessionName": "example", + "ClientName": "example", + "ClientAddress": "example", + "ClientPort": 1 + } + }, + { + "format": "windows_event_security", + "variant": "rdp_session_disconnect", + "fields": { + "EventID": 4779, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "AccountName": "example", + "AccountDomain": "example", + "LogonID": "0x1", + "SessionName": "example", + "ClientName": "example", + "ClientAddress": "example", + "ClientPort": 1 + } + }, + { + "format": "windows_event_security", + "variant": "process_creation", + "fields": { + "EventID": 4688, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "NewProcessId": "0x1", + "NewProcessName": "example", + "TokenElevationType": "example", + "ProcessId": "0x1", + "CommandLine": "cmd.exe /c echo witness", + "TargetUserSid": "S-1-5-21-1-2-3-1001", + "TargetUserName": "witness", + "TargetDomainName": "witness", + "TargetLogonId": "0x12", + "ParentProcessName": "witness", + "MandatoryLabel": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "failed_logon", + "fields": { + "EventID": 4625, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "Status": "0x1", + "SubStatus": "0x1", + "FailureReason": "example", + "LogonType": 2, + "IpAddress": "example", + "LogonProcessName": "witness", + "AuthenticationPackageName": "witness", + "WorkstationName": "witness", + "IpPort": 42, + "TransmittedServices": "witness", + "LmPackageName": "witness", + "KeyLength": 42, + "ProcessId": "0x12", + "ProcessName": "C:\\Windows\\System32\\winlogon.exe", + "RemoteUserID": "S-1-5-21-1-2-3-1001", + "RemoteMachineID": "S-1-5-21-1-2-3-1001" + } + }, + { + "format": "windows_event_security", + "variant": "special_privileges", + "fields": { + "EventID": 4672, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "PrivilegeList": "example" + } + }, + { + "format": "windows_event_security", + "variant": "workstation_locked", + "fields": { + "EventID": 4800, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "SessionId": 1 + } + }, + { + "format": "windows_event_security", + "variant": "workstation_unlocked", + "fields": { + "EventID": 4801, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "SessionId": 1 + } + }, + { + "format": "windows_event_security", + "variant": "process_termination", + "fields": { + "EventID": 4689, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "Status": "0x1", + "ProcessId": "0x1", + "ProcessName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "explicit_credentials", + "fields": { + "EventID": 4648, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetServerName": "example", + "ProcessId": "0x1", + "ProcessName": "example", + "LogonGuid": "{11111111-1111-1111-1111-111111111111}", + "TargetLogonGuid": "{33333333-3333-3333-3333-333333333333}", + "TargetInfo": "witness", + "IpAddress": "192.0.2.10", + "IpPort": 42 + } + }, + { + "format": "windows_event_security", + "variant": "kerberos_tgt", + "fields": { + "EventID": 4768, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "ServiceName": "example", + "ServiceSid": "S-1-5-18", + "TicketOptions": "0x1", + "Status": "0x1", + "TicketEncryptionType": "0x1", + "IpAddress": "example", + "PreAuthType": 42, + "IpPort": 42, + "CertIssuerName": "witness", + "CertSerialNumber": "witness", + "CertThumbprint": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "kerberos_service_ticket", + "fields": { + "EventID": 4769, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "ServiceName": "example", + "ServiceSid": "S-1-5-18", + "TicketOptions": "0x1", + "TicketEncryptionType": "0x1", + "IpAddress": "example", + "Status": "0x1", + "IpPort": 42, + "LogonGuid": "{11111111-1111-1111-1111-111111111111}", + "TransmittedServices": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "ntlm_validation", + "fields": { + "EventID": 4776, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "PackageName": "example", + "TargetUserName": "example", + "Workstation": "example", + "Status": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "wfp_connection", + "fields": { + "EventID": 5156, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "ProcessID": 1, + "Application": "example", + "Direction": "example", + "SourceAddress": "example", + "SourcePort": 1, + "DestAddress": "example", + "DestPort": 1, + "Protocol": 1, + "FilterRTID": 42, + "LayerName": "witness", + "LayerRTID": 42, + "RemoteUserID": "S-1-5-21-1-2-3-1001", + "RemoteMachineID": "S-1-5-21-1-2-3-1001" + } + }, + { + "format": "windows_event_security", + "variant": "kerberos_preauth_failed", + "fields": { + "EventID": 4771, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetSid": "S-1-5-18", + "ServiceName": "example", + "TicketOptions": "0x1", + "Status": "0x1", + "IpAddress": "::ffff:10.10.1.99", + "PreAuthType": 42, + "IpPort": 42, + "CertIssuerName": "witness", + "CertSerialNumber": "witness", + "CertThumbprint": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "log_cleared", + "fields": { + "EventID": 1102, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "service_installed", + "fields": { + "EventID": 4697, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ServiceName": "example", + "ServiceFileName": "example", + "ServiceType": "witness", + "ServiceStartType": "witness", + "ServiceAccount": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task", + "fields": { + "EventID": 4698, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example", + "TaskContent": "" + } + }, + { + "format": "windows_event_security", + "variant": "group_membership_change", + "fields": { + "EventID": 4728, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "MemberSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "MemberName": "witness", + "PrivilegeList": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "account_created", + "fields": { + "EventID": 4720, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "SamAccountName": "witness", + "DisplayName": "witness", + "UserPrincipalName": "witness", + "HomeDirectory": "witness", + "HomePath": "witness", + "ScriptPath": "witness", + "ProfilePath": "witness", + "UserWorkstations": "witness", + "PasswordLastSet": "witness", + "AccountExpires": "witness", + "PrimaryGroupId": "witness", + "AllowedToDelegateTo": "witness", + "OldUacValue": "witness", + "NewUacValue": "witness", + "UserAccountControl": "witness", + "UserParameters": "witness", + "SidHistory": "witness", + "LogonHours": "witness", + "PrivilegeList": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "password_change", + "fields": { + "EventID": 4723, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "password_reset", + "fields": { + "EventID": 4724, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "account_deleted", + "fields": { + "EventID": 4726, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "PrivilegeList": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "account_changed", + "fields": { + "EventID": 4738, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "SamAccountName": "witness", + "DisplayName": "witness", + "UserPrincipalName": "witness", + "HomeDirectory": "witness", + "HomePath": "witness", + "ScriptPath": "witness", + "ProfilePath": "witness", + "UserWorkstations": "witness", + "PasswordLastSet": "witness", + "AccountExpires": "witness", + "PrimaryGroupId": "witness", + "AllowedToDelegateTo": "witness", + "OldUacValue": "witness", + "NewUacValue": "witness", + "UserAccountControl": "witness", + "UserParameters": "witness", + "SidHistory": "witness", + "LogonHours": "witness", + "PrivilegeList": "witness" + } + }, + { + "format": "windows_event_security", + "variant": "object_handle_requested", + "fields": { + "EventID": 4656, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectServer": "example", + "ObjectType": "example", + "ObjectName": "example", + "HandleId": "0x1", + "TransactionId": "example", + "AccessList": "example", + "AccessReason": "example", + "AccessMask": "0x1", + "PrivilegeList": "example", + "RestrictedSidCount": 1, + "ProcessId": "0x1", + "ProcessName": "example", + "ResourceAttributes": "example" + } + }, + { + "format": "windows_event_security", + "variant": "object_handle_closed", + "fields": { + "EventID": 4658, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectServer": "example", + "HandleId": "0x1", + "ProcessId": "0x1", + "ProcessName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "object_access", + "fields": { + "EventID": 4663, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectServer": "example", + "ObjectType": "example", + "ObjectName": "example", + "HandleId": "0x1", + "AccessList": "example", + "AccessMask": "0x1", + "ProcessId": "0x1", + "ProcessName": "example", + "ResourceAttributes": "example" + } + }, + { + "format": "windows_event_security", + "variant": "network_share_access", + "fields": { + "EventID": 5140, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectType": "example", + "IpAddress": "10.0.0.1", + "IpPort": 1, + "ShareName": "example", + "ShareLocalPath": "example", + "AccessMask": "0x1", + "AccessList": "example" + } + }, + { + "format": "windows_event_security", + "variant": "network_share_access_check", + "fields": { + "EventID": 5145, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectType": "example", + "IpAddress": "10.0.0.1", + "IpPort": 1, + "ShareName": "example", + "ShareLocalPath": "example", + "RelativeTargetName": "example", + "AccessMask": "0x1", + "AccessList": "example", + "AccessReason": "example" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task_deleted", + "fields": { + "EventID": 4699, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example", + "TaskContent": "" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task_enabled", + "fields": { + "EventID": 4700, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example", + "TaskContent": "" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task_disabled", + "fields": { + "EventID": 4701, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example", + "TaskContent": "" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_process_create", + "fields": { + "EventID": 1, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "CommandLine": "example", + "User": "example", + "RuleName": "witness", + "FileVersion": "witness", + "Description": "witness", + "Product": "witness", + "Company": "witness", + "OriginalFileName": "witness", + "CurrentDirectory": "C:\\Windows\\", + "LogonGuid": "{11111111-1111-1111-1111-111111111111}", + "LogonId": "0x12", + "TerminalSessionId": 42, + "IntegrityLevel": "witness", + "Hashes": "SHA256=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "ParentProcessGuid": "{22222222-2222-2222-2222-222222222222}", + "ParentProcessId": 42, + "ParentImage": "C:\\Windows\\explorer.exe", + "ParentCommandLine": "explorer.exe", + "ParentUser": "CORP\\witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_process_terminate", + "fields": { + "EventID": 5, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "User": "example", + "RuleName": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_create_remote_thread", + "fields": { + "EventID": 8, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "SourceProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "SourceProcessId": 1, + "SourceImage": "example", + "TargetProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "TargetProcessId": 1, + "TargetImage": "example", + "NewThreadId": 1, + "StartAddress": "example", + "SourceUser": "example", + "TargetUser": "example", + "RuleName": "witness", + "StartModule": "witness", + "StartFunction": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_process_access", + "fields": { + "EventID": 10, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "SourceProcessGUID": "example", + "SourceProcessId": 1, + "SourceThreadId": 1, + "SourceImage": "example", + "TargetProcessGUID": "example", + "TargetProcessId": 1, + "TargetImage": "example", + "GrantedAccess": "example", + "SourceUser": "example", + "TargetUser": "example", + "RuleName": "witness", + "CallTrace": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_network_connect", + "fields": { + "EventID": 3, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "User": "example", + "Protocol": "example", + "Initiated": "example", + "SourceIsIpv6": "false", + "SourceIp": "10.0.0.1", + "SourcePort": 1, + "DestinationIsIpv6": "false", + "DestinationIp": "10.0.0.1", + "DestinationPort": 1, + "RuleName": "witness", + "SourceHostname": "source.example.test", + "SourcePortName": "witness", + "DestinationHostname": "destination.example.test", + "DestinationPortName": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_image_loaded", + "fields": { + "EventID": 7, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "ImageLoaded": "example", + "Signed": "example", + "SignatureStatus": "example", + "User": "example", + "RuleName": "witness", + "FileVersion": "witness", + "Description": "witness", + "Product": "witness", + "Company": "witness", + "OriginalFileName": "witness", + "Hashes": "SHA256=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "Signature": "Microsoft Windows" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_file_create", + "fields": { + "EventID": 11, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "TargetFilename": "example", + "CreationUtcTime": "example", + "User": "example", + "RuleName": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_registry_create_delete", + "fields": { + "EventID": 12, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "EventType": "example", + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "TargetObject": "example", + "User": "example", + "RuleName": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_registry_set_value", + "fields": { + "EventID": 13, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "EventType": "example", + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "TargetObject": "example", + "Details": "example", + "User": "example", + "RuleName": "witness" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_dns_query", + "fields": { + "EventID": 22, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "QueryName": "example", + "QueryStatus": "example", + "Image": "example", + "RuleName": "witness", + "QueryResults": "192.0.2.20", + "User": "CORP\\user" + } + } +] diff --git a/tests/fixtures/record_validation/targets/proxy_access.log b/tests/fixtures/record_validation/targets/proxy_access.log new file mode 100644 index 000000000..b04e3c876 --- /dev/null +++ b/tests/fixtures/record_validation/targets/proxy_access.log @@ -0,0 +1 @@ +{"byte_scope":"connect-control-message","bytes_in":352,"bytes_out":205,"cache_result":"NONE","client":"10.10.1.31","dest_port":443,"http_method":"CONNECT","http_referrer":"","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0","http_version":"HTTP/1.1","ident":"-","proxy_action":"tunnel","response_time_microseconds":74029000,"server":"s3.amazonaws.com","status":200,"timestamp":"2024-03-18T12:00:11.105240Z","tunnel_cs_bytes":3618084,"tunnel_duration_ms":105278,"tunnel_sc_bytes":5465,"uri_path":"/","uri_query":"","url_category":"Business/Economy","user":"MERIDIANHCS\\marcus.chen"} diff --git a/tests/fixtures/record_validation/targets/snare_v1/windows_event_security_snare.log b/tests/fixtures/record_validation/targets/snare_v1/windows_event_security_snare.log new file mode 100644 index 000000000..12c70f194 --- /dev/null +++ b/tests/fixtures/record_validation/targets/snare_v1/windows_event_security_snare.log @@ -0,0 +1 @@ +<86>Mar 18 12:00:14 DC-02.meridianhcs.local DC-02.meridianhcs.local MSWinEventLog 0 Security 25377457 Mon Mar 18 12:00:14 2024 5156 Microsoft-Windows-Security-Auditing N/A N/A Success Audit DC-02.meridianhcs.local Filtering Platform Connection The Windows Filtering Platform allowed a connection.: ProjectionVersion: 1 SourceIp: 10.10.2.11 DestinationIp: 10.10.2.11 DestinationPort: 53 ProcessId: 5136 Image: \device\harddiskvolume3\windows\system32\svchost.exe Process ID: 4 TimeCreated: 2024-03-18T12:00:14.520988+00:00 Level: 0 ExecutionProcessID: 4 ExecutionThreadID: 2729692 ProcessID: 5136 Application: \device\harddiskvolume3\windows\system32\svchost.exe Direction: %%14593 SourceAddress: 10.10.2.11 SourcePort: 64428 DestAddress: 10.10.2.11 DestPort: 53 Protocol: 17 FilterRTID: 20760 LayerName: %%14611 LayerRTID: 48 RemoteUserID: S-1-0-0 RemoteMachineID: S-1-0-0 EventRecordID: 25377457 ProjectionEnd: 1 diff --git a/tests/fixtures/record_validation/targets/snare_v1/windows_event_sysmon_snare.log b/tests/fixtures/record_validation/targets/snare_v1/windows_event_sysmon_snare.log new file mode 100644 index 000000000..eb818f24b --- /dev/null +++ b/tests/fixtures/record_validation/targets/snare_v1/windows_event_sysmon_snare.log @@ -0,0 +1 @@ +<14>Mar 18 12:00:14 DC-02.meridianhcs.local DC-02.meridianhcs.local MSWinEventLog 0 Microsoft-Windows-Sysmon/Operational 1368530 Mon Mar 18 12:00:14 2024 22 Microsoft-Windows-Sysmon NT AUTHORITY\SYSTEM N/A Information DC-02.meridianhcs.local Dns query Dns query: ProjectionVersion: 1 Process ID: 2000 TimeCreated: 2024-03-18T12:00:14.550883+00:00 Level: 4 ExecutionProcessID: 2000 ExecutionThreadID: 3156 UtcTime: 2024-03-18 12:00:14.547 ProcessGuid: {d55311aa-c346-65e1-d902-000030c6ed7c} ProcessId: 5096 QueryName: DC-01.meridianhcs.local QueryStatus: 0 QueryResults: 10.10.2.10; Image: C:\Windows\System32\lsass.exe User: NT AUTHORITY\SYSTEM EventRecordID: 1368530 ProjectionEnd: 1 diff --git a/tests/fixtures/record_validation/targets/web_access.log b/tests/fixtures/record_validation/targets/web_access.log new file mode 100644 index 000000000..82e71f2a2 --- /dev/null +++ b/tests/fixtures/record_validation/targets/web_access.log @@ -0,0 +1 @@ +{"bytes_in":0,"bytes_out":464,"client":"185.220.233.25","dest_port":80,"http_content_type":"application/javascript","http_method":"GET","http_referrer":"","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0","http_version":"HTTP/1.1","ident":"-","response_time_microseconds":3646966,"server":"WEB-EXT-01.meridianhcs.local","status":301,"timestamp":"2024-03-18T12:04:02.634938Z","uri_path":"/assets/app.js","uri_query":"","user":"-"} diff --git a/tests/fixtures/record_validation/targets/windows_event_security_snare.log b/tests/fixtures/record_validation/targets/windows_event_security_snare.log new file mode 100644 index 000000000..f9bed44e5 --- /dev/null +++ b/tests/fixtures/record_validation/targets/windows_event_security_snare.log @@ -0,0 +1 @@ +<86>Mar 18 12:04:11 WS-EBROOKS-01.meridianhcs.local WS-EBROOKS-01.meridianhcs.local MSWinEventLog 0 Security 949137 Mon Mar 18 12:04:11 2024 5156 Microsoft-Windows-Security-Auditing N/A N/A Success Audit WS-EBROOKS-01.meridianhcs.local Filtering Platform Connection The Windows Filtering Platform allowed a connection.: ProcessID: 3404 Application: \device\harddiskvolume7\windows\system32\svchost.exe Direction: %%14593 SourceIp: 10.10.1.33 SourcePort: 65502 DestinationIp: 10.10.2.10 DestPort: 53 Protocol: 17 FilterRTID: 26327 LayerName: %%14611 LayerRTID: 48 RemoteUserID: S-1-0-0 RemoteMachineID: S-1-0-0 _host_type: workstation diff --git a/tests/fixtures/record_validation/windows_variants.json b/tests/fixtures/record_validation/windows_variants.json new file mode 100644 index 000000000..bcd6a28bf --- /dev/null +++ b/tests/fixtures/record_validation/windows_variants.json @@ -0,0 +1,940 @@ +[ + { + "format": "windows_event_security", + "variant": "logon", + "fields": { + "EventID": 4624, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "LogonType": 2, + "WorkstationName": "example", + "ProcessId": "0x1", + "ProcessName": "example", + "IpAddress": "example", + "IpPort": 1 + } + }, + { + "format": "windows_event_security", + "variant": "logoff", + "fields": { + "EventID": 4634, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "LogonType": 2 + } + }, + { + "format": "windows_event_security", + "variant": "rdp_session_reconnect", + "fields": { + "EventID": 4778, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "AccountName": "example", + "AccountDomain": "example", + "LogonID": "0x1", + "SessionName": "example", + "ClientName": "example", + "ClientAddress": "example", + "ClientPort": 1 + } + }, + { + "format": "windows_event_security", + "variant": "rdp_session_disconnect", + "fields": { + "EventID": 4779, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "AccountName": "example", + "AccountDomain": "example", + "LogonID": "0x1", + "SessionName": "example", + "ClientName": "example", + "ClientAddress": "example", + "ClientPort": 1 + } + }, + { + "format": "windows_event_security", + "variant": "process_creation", + "fields": { + "EventID": 4688, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "NewProcessId": "0x1", + "NewProcessName": "example", + "TokenElevationType": "example", + "ProcessId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "failed_logon", + "fields": { + "EventID": 4625, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "Status": "0x1", + "SubStatus": "0x1", + "FailureReason": "example", + "LogonType": 2, + "IpAddress": "example" + } + }, + { + "format": "windows_event_security", + "variant": "special_privileges", + "fields": { + "EventID": 4672, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "PrivilegeList": "example" + } + }, + { + "format": "windows_event_security", + "variant": "workstation_locked", + "fields": { + "EventID": 4800, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "SessionId": 1 + } + }, + { + "format": "windows_event_security", + "variant": "workstation_unlocked", + "fields": { + "EventID": 4801, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetLogonId": "0x1", + "SessionId": 1 + } + }, + { + "format": "windows_event_security", + "variant": "process_termination", + "fields": { + "EventID": 4689, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "Status": "0x1", + "ProcessId": "0x1", + "ProcessName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "explicit_credentials", + "fields": { + "EventID": 4648, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetServerName": "example", + "ProcessId": "0x1", + "ProcessName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "kerberos_tgt", + "fields": { + "EventID": 4768, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "ServiceName": "example", + "ServiceSid": "S-1-5-18", + "TicketOptions": "0x1", + "Status": "0x1", + "TicketEncryptionType": "0x1", + "IpAddress": "example" + } + }, + { + "format": "windows_event_security", + "variant": "kerberos_service_ticket", + "fields": { + "EventID": 4769, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "ServiceName": "example", + "ServiceSid": "S-1-5-18", + "TicketOptions": "0x1", + "TicketEncryptionType": "0x1", + "IpAddress": "example", + "Status": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "ntlm_validation", + "fields": { + "EventID": 4776, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "PackageName": "example", + "TargetUserName": "example", + "Workstation": "example", + "Status": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "wfp_connection", + "fields": { + "EventID": 5156, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "ProcessID": 1, + "Application": "example", + "Direction": "example", + "SourceAddress": "example", + "SourcePort": 1, + "DestAddress": "example", + "DestPort": 1, + "Protocol": 1 + } + }, + { + "format": "windows_event_security", + "variant": "kerberos_preauth_failed", + "fields": { + "EventID": 4771, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetSid": "S-1-5-18", + "ServiceName": "example", + "TicketOptions": "0x1", + "Status": "0x1", + "IpAddress": "::1" + } + }, + { + "format": "windows_event_security", + "variant": "log_cleared", + "fields": { + "EventID": 1102, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "service_installed", + "fields": { + "EventID": 4697, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ServiceName": "example", + "ServiceFileName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task", + "fields": { + "EventID": 4698, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "group_membership_change", + "fields": { + "EventID": 4728, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "MemberSid": "S-1-5-18", + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "account_created", + "fields": { + "EventID": 4720, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "password_change", + "fields": { + "EventID": 4723, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "password_reset", + "fields": { + "EventID": 4724, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "account_deleted", + "fields": { + "EventID": 4726, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "account_changed", + "fields": { + "EventID": 4738, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "TargetUserName": "example", + "TargetDomainName": "example", + "TargetSid": "S-1-5-18", + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1" + } + }, + { + "format": "windows_event_security", + "variant": "object_handle_requested", + "fields": { + "EventID": 4656, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectServer": "example", + "ObjectType": "example", + "ObjectName": "example", + "HandleId": "0x1", + "TransactionId": "example", + "AccessList": "example", + "AccessReason": "example", + "AccessMask": "0x1", + "PrivilegeList": "example", + "RestrictedSidCount": 1, + "ProcessId": "0x1", + "ProcessName": "example", + "ResourceAttributes": "example" + } + }, + { + "format": "windows_event_security", + "variant": "object_handle_closed", + "fields": { + "EventID": 4658, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectServer": "example", + "HandleId": "0x1", + "ProcessId": "0x1", + "ProcessName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "object_access", + "fields": { + "EventID": 4663, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectServer": "example", + "ObjectType": "example", + "ObjectName": "example", + "HandleId": "0x1", + "AccessList": "example", + "AccessMask": "0x1", + "ProcessId": "0x1", + "ProcessName": "example", + "ResourceAttributes": "example" + } + }, + { + "format": "windows_event_security", + "variant": "network_share_access", + "fields": { + "EventID": 5140, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectType": "example", + "IpAddress": "10.0.0.1", + "IpPort": 1, + "ShareName": "example", + "ShareLocalPath": "example", + "AccessMask": "0x1", + "AccessList": "example" + } + }, + { + "format": "windows_event_security", + "variant": "network_share_access_check", + "fields": { + "EventID": 5145, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "ObjectType": "example", + "IpAddress": "10.0.0.1", + "IpPort": 1, + "ShareName": "example", + "ShareLocalPath": "example", + "RelativeTargetName": "example", + "AccessMask": "0x1", + "AccessList": "example", + "AccessReason": "example" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task_deleted", + "fields": { + "EventID": 4699, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task_enabled", + "fields": { + "EventID": 4700, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example" + } + }, + { + "format": "windows_event_security", + "variant": "scheduled_task_disabled", + "fields": { + "EventID": 4701, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 0, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "SubjectUserSid": "S-1-5-18", + "SubjectUserName": "example", + "SubjectDomainName": "example", + "SubjectLogonId": "0x1", + "TaskName": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_process_create", + "fields": { + "EventID": 1, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "CommandLine": "example", + "User": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_process_terminate", + "fields": { + "EventID": 5, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "User": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_create_remote_thread", + "fields": { + "EventID": 8, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "SourceProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "SourceProcessId": 1, + "SourceImage": "example", + "TargetProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "TargetProcessId": 1, + "TargetImage": "example", + "NewThreadId": 1, + "StartAddress": "example", + "SourceUser": "example", + "TargetUser": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_process_access", + "fields": { + "EventID": 10, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "SourceProcessGUID": "example", + "SourceProcessId": 1, + "SourceThreadId": 1, + "SourceImage": "example", + "TargetProcessGUID": "example", + "TargetProcessId": 1, + "TargetImage": "example", + "GrantedAccess": "example", + "SourceUser": "example", + "TargetUser": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_network_connect", + "fields": { + "EventID": 3, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "User": "example", + "Protocol": "example", + "Initiated": "example", + "SourceIsIpv6": "false", + "SourceIp": "10.0.0.1", + "SourcePort": 1, + "DestinationIsIpv6": "false", + "DestinationIp": "10.0.0.1", + "DestinationPort": 1 + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_image_loaded", + "fields": { + "EventID": 7, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "ImageLoaded": "example", + "Signed": "example", + "SignatureStatus": "example", + "User": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_file_create", + "fields": { + "EventID": 11, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "TargetFilename": "example", + "CreationUtcTime": "example", + "User": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_registry_create_delete", + "fields": { + "EventID": 12, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "EventType": "example", + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "TargetObject": "example", + "User": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_registry_set_value", + "fields": { + "EventID": 13, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "EventType": "example", + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "Image": "example", + "TargetObject": "example", + "Details": "example", + "User": "example" + } + }, + { + "format": "windows_event_sysmon", + "variant": "sysmon_dns_query", + "fields": { + "EventID": 22, + "TimeCreated": "2026-09-15T12:00:00Z", + "Computer": "example", + "Channel": "example", + "Level": 1, + "EventRecordID": 1, + "ExecutionProcessID": 1, + "ExecutionThreadID": 1, + "UtcTime": "example", + "ProcessGuid": "{12345678-1234-1234-1234-123456789abc}", + "ProcessId": 1, + "QueryName": "example", + "QueryStatus": "example", + "Image": "example" + } + } +] diff --git a/tests/integration/test_checkpoint_smoke.py b/tests/integration/test_checkpoint_smoke.py index 69ab6a81b..27b6cef10 100644 --- a/tests/integration/test_checkpoint_smoke.py +++ b/tests/integration/test_checkpoint_smoke.py @@ -9,6 +9,7 @@ import time from pathlib import Path +import pytest import yaml from tests.support.output_equivalence import deterministic_bundle_files @@ -29,9 +30,13 @@ def _run_cli(*arguments: str, environment: dict[str, str]) -> str: return result.stdout -def test_short_generation_checkpoint_suspension_and_resume(tmp_path: Path) -> None: +@pytest.mark.parametrize("target", ["default", "sof-elk"]) +def test_short_generation_checkpoint_suspension_and_resume(tmp_path: Path, target: str) -> None: scenario_data = yaml.safe_load( - Path("tests/fixtures/scenarios/minimal.yaml").read_text(encoding="utf-8") + Path( + "tests/fixtures/scenarios" + / Path("checkpoint-all-formats.yaml" if target == "sof-elk" else "minimal.yaml") + ).read_text(encoding="utf-8") ) scenario_data["time_window"].update(warmup="1h", duration="3h") scenario_data["baseline_activity"]["intensity"] = "low" @@ -67,6 +72,8 @@ def test_short_generation_checkpoint_suspension_and_resume(tmp_path: Path) -> No str(output), "--seed", "42", + "--target", + target, "--checkpoint-hours", "1", ], @@ -115,12 +122,16 @@ def test_short_generation_checkpoint_suspension_and_resume(tmp_path: Path) -> No "42", "--checkpoint-hours", "0", + "--target", + target, environment=environment, ) resumed_files = deterministic_bundle_files(output) assert resumed_files == deterministic_bundle_files(control) assert any( - b" dict[str, bytes]: + manifest = json.loads((root / "GENERATION_MANIFEST.json").read_text()) + files = {name: (root / name).read_bytes() for name in manifest["files"]} + for name, content in files.items(): + assert hashlib.sha256(content).hexdigest() == manifest["files"][name] + assert ( + hashlib.sha256(files["RESOLVED_SCENARIO.yaml"]).hexdigest() + == manifest["resolved_file_sha256"] + ) + return files + + +@pytest.mark.slow +@pytest.mark.parametrize("target", ["default", "sof-elk"]) +def test_iteration_fresh_process_bytes_and_complete_evaluation(tmp_path: Path, target: str) -> None: + root = Path(__file__).parents[2] + scenario = root / "scenarios/iteration-test/scenario.yaml" + outputs = [tmp_path / "first", tmp_path / "second"] + for output in outputs: + generated = subprocess.run( + [ + sys.executable, + "-m", + "evidenceforge", + "generate", + str(scenario), + "--output", + str(output), + "--seed", + "42", + "--target", + target, + ], + cwd=root, + capture_output=True, + text=True, + timeout=600, + check=False, + ) + assert generated.returncode == 0, generated.stderr + assert _verified_snapshot(outputs[0]) == _verified_snapshot(outputs[1]) + evaluated = subprocess.run( + [sys.executable, "-m", "evidenceforge", "eval", str(outputs[0]), "--format", "json"], + cwd=root, + capture_output=True, + text=True, + timeout=180, + check=False, + ) + assert evaluated.returncode == 0, evaluated.stderr + report = json.loads(evaluated.stdout) + assert report["source_counts"]["email_artifacts"] > 0 + assert len(report["pillars"]) == 4 + assert all(pillar["score"] is not None for pillar in report["pillars"]) + parseability = next(p for p in report["pillars"] if p["name"] == "Parseability") + assert all(s["score"] == 100 for s in parseability["sub_scores"]) diff --git a/tests/integration/test_validation_checkpoint_upgrade.py b/tests/integration/test_validation_checkpoint_upgrade.py new file mode 100644 index 000000000..5c26cdabd --- /dev/null +++ b/tests/integration/test_validation_checkpoint_upgrade.py @@ -0,0 +1,156 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Historical checkpoint compatibility gate; supply the retained baseline interpreter.""" + +import hashlib +import json +import os +import shutil +import subprocess +import sys +import time +from pathlib import Path + +import pytest +import yaml + +from tests.support.output_equivalence import deterministic_bundle_files + +pytestmark = pytest.mark.slow + + +def _snapshot(root: Path) -> dict[str, str]: + return { + str(p.relative_to(root)): hashlib.sha256(p.read_bytes()).hexdigest() + for p in root.rglob("*") + if p.is_file() + } + + +def test_baseline_checkpoint_upgrade(tmp_path: Path) -> None: + baseline = os.environ.get("EFORGE_VALIDATION_BASELINE_PYTHON") + if not baseline: + pytest.skip("Historical gate requires the isolated 787fd733 baseline interpreter") + data = yaml.safe_load(Path("tests/fixtures/scenarios/checkpoint-all-formats.yaml").read_text()) + data["time_window"].update(warmup="1h", duration="3h") + scenario = tmp_path / "scenario.yaml" + scenario.write_text(yaml.safe_dump(data)) + output = tmp_path / "suspended" + sync = tmp_path / "sync" + sync.mkdir() + environment = { + k: v for k, v in os.environ.items() if not k.startswith("EFORGE_TEST_CHECKPOINT_SYNC_") + } + + environment["TMPDIR"] = str(tmp_path.resolve()) + + def run(exe: str, *args: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [exe, "-m", "evidenceforge", *args], + env=environment, + capture_output=True, + text=True, + timeout=180, + check=False, + ) + + with (tmp_path / "suspend.log").open("w") as log: + process = subprocess.Popen( + [ + baseline, + "-m", + "evidenceforge", + "generate", + str(scenario), + "--output", + str(output), + "--seed", + "42", + "--checkpoint-hours", + "1", + ], + env=environment + | { + "EFORGE_TEST_CHECKPOINT_SYNC_DIR": str(sync), + "EFORGE_TEST_CHECKPOINT_SYNC_HOUR": "2", + "EFORGE_TEST_CHECKPOINT_SYNC_TIMEOUT": "120", + }, + stdout=log, + stderr=subprocess.STDOUT, + ) + try: + marker = sync / "00000000000000000002.ready" + deadline = time.monotonic() + 120 + while not marker.exists() and process.poll() is None and time.monotonic() < deadline: + time.sleep(0.05) + assert marker.exists() + suspended = run(baseline, "checkpoint", "suspend", str(output)) + assert suspended.returncode == 0, suspended.stderr + (sync / "00000000000000000002.continue").touch() + assert process.wait(timeout=120) == 0 + finally: + if process.poll() is None: + process.kill() + process.wait(timeout=30) + preserved = tmp_path / "preserved" + shutil.copytree(output, preserved) + original = _snapshot(output) + exact = run( + sys.executable, "generate", "--output", str(output), "--resume", "--resume-policy", "exact" + ) + assert exact.returncode != 0 + assert "exact" in (exact.stdout + exact.stderr).lower() + assert _snapshot(output) == original + status = run(sys.executable, "checkpoint", "status", str(output), "--json") + assert status.returncode == 0, status.stderr + assert "not-guaranteed" in status.stdout + verify = run(sys.executable, "checkpoint", "verify", str(output)) + assert verify.returncode == 0, verify.stderr + assert _snapshot(output) == original + resumed = run(sys.executable, "generate", "--output", str(output), "--resume") + assert resumed.returncode == 0, resumed.stderr + assert _snapshot(preserved) == original + controls = [] + for label, exe in (("baseline", baseline), ("candidate", sys.executable)): + control = tmp_path / label + result = run( + exe, + "generate", + str(scenario), + "--output", + str(control), + "--seed", + "42", + "--checkpoint-hours", + "0", + ) + assert result.returncode == 0, result.stderr + controls.append(control) + + def evidence(root: Path) -> dict[str, bytes]: + return { + name: value + for name, value in deterministic_bundle_files(root).items() + if name != "RESOLVED_SCENARIO.yaml" + } + + assert evidence(output) == evidence(controls[0]) == evidence(controls[1]) + manifest = json.loads((output / "GENERATION_MANIFEST.json").read_text()) + text = json.dumps(manifest) + assert '"accepted_policy": "compatible"' in text + assert '"migration_count": 1' in text + assert "json-logic-qubit" in text + (tmp_path / "upgrade-evidence.json").write_text( + json.dumps( + { + "exact_exit": exact.returncode, + "checkpoint_unchanged": True, + "status": json.loads(status.stdout), + "resume_exit": resumed.returncode, + "evidence_files": len(evidence(output)), + "manifest": manifest, + }, + indent=2, + ) + ) diff --git a/tests/support/native_records.py b/tests/support/native_records.py new file mode 100644 index 000000000..134d167e6 --- /dev/null +++ b/tests/support/native_records.py @@ -0,0 +1,46 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Production rendering boundary for validation fixtures.""" + +from pathlib import Path + +from evidenceforge.generation.engine.emitter_setup import _build_emitter_classes + + +def render_record(tmp_path: Path, case: dict) -> str: + from datetime import UTC, datetime + + from evidenceforge.formats.loader import load_format + + name = case["format"] + definition = load_format(name) + fields = dict(case["fields"]) + for key in ("timestamp", "TimeCreated", "ts"): + if isinstance(fields.get(key), str): + fields[key] = datetime.fromisoformat(fields[key].replace("Z", "+00:00")) + if name == "ecar": + fields["timestamp"] = fields.pop("timestamp_ms") / 1000 + if name in {"snort_alert", "proxy_access", "web_access", "bash_history"}: + if isinstance(fields.get("timestamp"), (int, float)): + fields["timestamp"] = datetime.fromtimestamp(fields["timestamp"], UTC) + if name == "proxy_access": + fields.update(method="GET", url="http://example/", protocol="HTTP/1.1", sc_bytes=1) + if name == "zeek_smb_files": + for key in ("size", "prev_name", "fuid"): + fields.setdefault(key, None) + if case.get("variant") == "process_creation": + fields.setdefault("TargetUserSid", "S-1-0-0") + path = tmp_path / (name + definition.output.file_extension) + emitter = _build_emitter_classes()[name](definition, path, threaded=False) + try: + raw = ( + emitter._prepare_event(fields)["rendered"] + if name == "bash_history" + else emitter._render_alert(fields) + if name == "snort_alert" + else emitter._render_event(fields) + ) + return raw + finally: + emitter.close() diff --git a/tests/unit/test_activity.py b/tests/unit/test_activity.py index 1cf088329..ec14f7313 100644 --- a/tests/unit/test_activity.py +++ b/tests/unit/test_activity.py @@ -9117,10 +9117,10 @@ def test_log_cleared_can_inherit_causative_process_logon_id( assert event.auth.subject_username == "jsmith" assert event.auth.subject_logon_id == "0xabc123" - def test_kerberos_preauth_failed_preserves_missing_source_ip( + def test_kerberos_preauth_failed_renders_missing_source_as_localhost( self, activity_gen, test_user, state_manager, mock_emitters ): - """4771 should not render missing source IP as invalid ::ffff:-.""" + """A DC-local 4771 should use the native localhost address and port zero.""" timestamp = datetime(2024, 1, 15, 10, 0, 0, tzinfo=UTC) state_manager.set_current_time(timestamp) activity_gen._dc_systems = { @@ -9141,7 +9141,7 @@ def test_kerberos_preauth_failed_preserves_missing_source_ip( event = mock_emitters["windows_event_security"].emit.call_args[0][0] assert event.event_type == "kerberos_preauth_failed" - assert event.kerberos.source_ip == "-" + assert event.kerberos.source_ip == "::1" assert event.kerberos.source_port == 0 def test_kerberos_preauth_failed_status_0x18_never_emits_type_zero( diff --git a/tests/unit/test_apache_json_validation.py b/tests/unit/test_apache_json_validation.py new file mode 100644 index 000000000..479b80459 --- /dev/null +++ b/tests/unit/test_apache_json_validation.py @@ -0,0 +1,126 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Supported Splunk web/proxy JSON uses the same exact evidence gates.""" + +import json +from datetime import UTC, datetime +from pathlib import Path + +import pytest +from typer.testing import CliRunner + +from evidenceforge.cli.commands import app +from evidenceforge.evaluation.parsers import get_parser +from evidenceforge.evaluation.pillars.causality import CausalityScorer +from evidenceforge.evaluation.pillars.parseability import ParseabilityScorer +from evidenceforge.evaluation.storyline import ResolvedEvent + +ROOT = Path(__file__).parents[1] / "fixtures/record_validation/targets" + + +@pytest.mark.parametrize("source", ["web_access", "proxy_access"]) +@pytest.mark.parametrize("username", ["-", "alice", "bob", "CORP\\alice", "HOST$"]) +def test_apache_json_user_indicator_semantics(source: str, username: str) -> None: + document = json.loads((ROOT / (source + ".log")).read_text()) + document["user"] = username + record = get_parser(source)._parse_line(json.dumps(document), 1) + assert not record.parse_errors + if username == "-": + assert "username" not in record.fields + else: + assert record.fields["username"] == username + event = ResolvedEvent( + index=0, + time=datetime(2024, 3, 18, tzinfo=UTC), + actor="alice", + system="WEB-01", + system_ip=None, + activity="HTTP request", + details={}, + event_types=["connection"], + ) + checks = CausalityScorer()._check_indicators(event, record) + if username == "-": + assert not any(name == "username" for name, _ in checks) + elif username in {"alice", "bob"}: + assert ("username", username == "alice") in checks + + +@pytest.mark.parametrize("source", ["web_access", "proxy_access"]) +@pytest.mark.parametrize("reverse", [False, True]) +def test_anonymous_user_does_not_hide_conflicting_alias(source: str, reverse: bool) -> None: + document = json.loads((ROOT / (source + ".log")).read_text()) + document.update(user="-", username="alice") + if reverse: + document = dict(reversed(document.items())) + record = get_parser(source)._parse_line(json.dumps(document), 1) + assert "Conflicting JSON field: username" in record.parse_errors + + +@pytest.mark.parametrize("source", ["web_access", "proxy_access"]) +@pytest.mark.parametrize( + "mutation", + [ + None, + "timestamp", + "uri_path", + "bytes_out", + "bytes_in", + "dest_port", + "response_time_microseconds", + "client", + "conflict", + "username_conflict", + "shape", + ], +) +def test_apache_json_records_stay_counted( + tmp_path: Path, source: str, mutation: str | None +) -> None: + document = json.loads((ROOT / (source + ".log")).read_text()) + if mutation == "shape": + document = [] + elif mutation == "conflict": + document["client_ip"] = "192.0.2.99" + elif mutation == "username_conflict": + document.update(user="-", username="alice") + elif mutation: + document[mutation] = {"invalid": "value"} + path = tmp_path / (source + ".log") + path.write_text(json.dumps(document) + "\n") + records = list(get_parser(source).parse_file(path)) + assert len(records) == 1 + scores = ParseabilityScorer()._score_both({source: records}) + if mutation is None: + assert all(s.score == 100 for s in scores) + else: + assert any(s.score < 100 for s in scores) + result = CliRunner().invoke( + app, + [ + "eval", + str(tmp_path), + "--scenario", + str(ROOT.parents[1] / "scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ], + ) + assert result.exit_code == 0, result.stderr + report = json.loads(result.stdout) + assert report["source_counts"][source] == 1 + if mutation is not None: + assert report["acceptance_passed"] is False + + +def test_historical_snare_unavailable_fields_remain_visible() -> None: + """Do not silently waive missing XML metadata or invent ambiguous account fields.""" + records = list( + get_parser("windows_event_security").parse_file(ROOT / "windows_event_security_snare.log") + ) + assert len(records) == 1 + schema, _ = ParseabilityScorer()._score_both({"windows_event_security": records}) + assert schema.score == 100 + assert "Level" in {f.rule_id for f in schema.sample_unavailable_findings} + assert schema.unavailable_check_count > 0 diff --git a/tests/unit/test_baseline_canonical.py b/tests/unit/test_baseline_canonical.py index 271cf5688..f391f2e29 100644 --- a/tests/unit/test_baseline_canonical.py +++ b/tests/unit/test_baseline_canonical.py @@ -1723,6 +1723,7 @@ def test_failed_logon_attaches_syslog_context( user=User(username="attacker", full_name="Attacker", email="a@t.com", enabled=True), system=linux, time=timestamp, + logon_type=3, source_ip="10.0.10.99", ) @@ -1845,10 +1846,10 @@ def test_local_linux_failed_logon_does_not_render_ssh_from_dash( for event in zeek_events ) - def test_self_sourced_linux_failed_logon_renders_local_auth( + def test_self_sourced_linux_network_failed_logon_stays_network_auth( self, activity_gen, state_manager, mock_emitters, timestamp ): - """A Linux host should not render sshd as connecting from its own host IP.""" + """An explicit type-3 attempt must not be rewritten as console authentication.""" linux = System(hostname="LNX-01", ip="10.0.10.2", os="Linux Ubuntu 22.04", type="server") state_manager.set_current_time(timestamp) activity_gen.generate_failed_logon( @@ -1863,11 +1864,10 @@ def test_self_sourced_linux_failed_logon_renders_local_auth( assert syslog.emit.called event = syslog.emit.call_args[0][0] assert event.syslog is not None - assert event.syslog.app_name == "login" - assert "logname=LOGIN" in event.syslog.message - assert "tty=/dev/tty1" in event.syslog.message - assert "rhost= user=alice" in event.syslog.message - assert "from 10.0.10.2" not in event.syslog.message + assert event.syslog.app_name == "sshd" + assert "Failed password for alice from 10.0.10.2" in event.syslog.message + assert "tty=/dev/tty1" not in event.syslog.message + assert event.auth.source_ip == "10.0.10.2" def test_generate_syslog_event_helper( self, activity_gen, state_manager, mock_emitters, timestamp diff --git a/tests/unit/test_emitters.py b/tests/unit/test_emitters.py index 5985f6ff6..b85cb007b 100644 --- a/tests/unit/test_emitters.py +++ b/tests/unit/test_emitters.py @@ -3254,10 +3254,8 @@ def test_emit_kerberos_preauth_failed(self, format_def, temp_output): assert "14339" in content assert '0x18' in content - def test_kerberos_preauth_without_source_ip_does_not_keep_source_port( - self, format_def, temp_output - ): - """4771 source port should not survive when the source address is unavailable.""" + def test_kerberos_preauth_without_source_ip_renders_localhost(self, format_def, temp_output): + """4771 should render a missing canonical source as a DC-local request.""" emitter = WindowsEventEmitter(format_def, temp_output, buffer_size=1) host = HostContext( hostname="DC-01", @@ -3290,8 +3288,8 @@ def test_kerberos_preauth_without_source_ip_does_not_keep_source_port( emitter.close() content = temp_output.read_text() - assert '-' in content - assert '-' in content + assert '::1' in content + assert '0' in content assert "49888" not in content def test_emit_log_cleared(self, format_def, temp_output): diff --git a/tests/unit/test_eval_cross_source.py b/tests/unit/test_eval_cross_source.py index bf4efa03d..646abd747 100644 --- a/tests/unit/test_eval_cross_source.py +++ b/tests/unit/test_eval_cross_source.py @@ -1328,6 +1328,134 @@ def test_failed_logon_indicator_uses_target_username(self): assert CrossSourceScorer._username_indicator_matches("aisha.johnson", event) assert not CrossSourceScorer._username_indicator_matches("root", event) + scorer = CrossSourceScorer() + assert scorer._record_matches( + _record( + "windows_event_security", + { + "EventID": 4625, + "Computer": "WS-AJOHNSON-01.meridianhcs.local", + "TargetUserName": "aisha.johnson", + }, + ts=T0, + ), + "windows_event_security", + ResolvedEvent( + index=0, + time=T0, + actor="root", + system="WS-AJOHNSON-01", + system_ip="10.10.1.35", + activity="wrong password fumble", + details={"target_username": "aisha.johnson"}, + event_types=["failed_logon"], + ), + "failed_logon", + ) + + def test_failed_logon_source_sentinel_is_an_indicator_mismatch(self): + """An explicit source must not receive credit when a source-bearing trace loses it.""" + from evidenceforge.evaluation.storyline import ResolvedEvent + + event = ResolvedEvent( + index=0, + time=T0, + actor="root", + system="WS-AJOHNSON-01", + system_ip="10.10.1.35", + activity="wrong password fumble", + details={"source_ip": "10.10.1.99", "target_username": "aisha.johnson"}, + event_types=["failed_logon"], + ) + trace = _record( + "ecar", + { + "hostname": "WS-AJOHNSON-01", + "object": "USER_SESSION", + "action": "LOGIN", + "principal": "aisha.johnson", + "src_ip": "-", + }, + ts=T0, + ) + + assert ("source_ip", False) in CrossSourceScorer()._check_indicators(event, trace) + + del trace.fields["src_ip"] + assert ("source_ip", False) in CrossSourceScorer()._check_indicators(event, trace) + + def test_failed_logon_dc_supporting_traces_use_requester_identity(self): + """4771/4776 support a failed logon without borrowing the target as requester.""" + from evidenceforge.evaluation.storyline import ResolvedEvent + from evidenceforge.models.scenario import System + + source = System( + hostname="LT-MRIVERA-02", + ip="10.10.1.99", + os="Linux Ubuntu 22.04", + type="workstation", + ) + target = System( + hostname="WS-AJOHNSON-01", + ip="10.10.1.35", + os="Windows 10", + type="workstation", + ) + dc = System( + hostname="DC-01", + ip="10.10.2.10", + os="Windows Server 2022", + type="domain_controller", + ) + scenario = _make_scenario(systems=[source, target, dc]) + event = ResolvedEvent( + index=0, + time=T0, + actor="root", + system=target.hostname, + system_ip=target.ip, + activity="wrong password fumble", + details={"source_ip": source.ip, "target_username": "aisha.johnson"}, + event_types=["failed_logon"], + ) + scorer = CrossSourceScorer() + scorer._initialize_pivot_identity(scenario) + kerberos = _record( + "windows_event_security", + { + "EventID": 4771, + "Computer": "DC-01.meridianhcs.local", + "TargetUserName": "aisha.johnson", + "IpAddress": "::ffff:10.10.1.99", + }, + ts=T0, + ) + ntlm = _record( + "windows_event_security", + { + "EventID": 4776, + "Computer": "DC-01.meridianhcs.local", + "TargetUserName": "aisha.johnson", + "Workstation": "LT-MRIVERA-02", + }, + ts=T0, + ) + + assert scorer._record_matches(kerberos, "windows_event_security", event, "failed_logon") + assert scorer._record_matches(ntlm, "windows_event_security", event, "failed_logon") + assert all(result for _name, result in scorer._check_indicators(event, kerberos)) + assert all(result for _name, result in scorer._check_indicators(event, ntlm)) + + kerberos.fields["IpAddress"] = "10.10.1.88" + ntlm.fields["Workstation"] = target.hostname + assert ("source_ip", False) in scorer._check_indicators(event, kerberos) + assert ("source_workstation", False) in scorer._check_indicators(event, ntlm) + + index = scorer._build_host_time_index({"windows_event_security": [kerberos, ntlm]}) + assert scorer._search_for_event_indexed(event, "failed_logon", index) == [ + kerberos, + ntlm, + ] def test_ipv4_mapped_source_indicator_matches_plain_ipv4(self): """Windows IPv4-mapped addresses should not create source mismatch noise.""" diff --git a/tests/unit/test_eval_record_fidelity.py b/tests/unit/test_eval_record_fidelity.py index 173e5b871..e5bf7e2e3 100644 --- a/tests/unit/test_eval_record_fidelity.py +++ b/tests/unit/test_eval_record_fidelity.py @@ -241,8 +241,7 @@ def test_failed_connect_error_bodies_do_not_fail_co_occurrence(self): ), ] - scorer = PlausibilityScorer() - tier_c = scorer._score_co_occurrence({"zeek_http": records}) + tier_c = RecordFidelityScorer()._score_format_constraints({"zeek_http": records}) assert tier_c.score == 100.0 @@ -259,8 +258,7 @@ def test_successful_connect_with_body_fails_co_occurrence(self): ), ] - scorer = PlausibilityScorer() - tier_c = scorer._score_co_occurrence({"zeek_http": records}) + tier_c = RecordFidelityScorer()._score_format_constraints({"zeek_http": records}) assert tier_c.score < 100.0 diff --git a/tests/unit/test_eval_strict_parsers.py b/tests/unit/test_eval_strict_parsers.py index f0db909a8..0b73f5330 100644 --- a/tests/unit/test_eval_strict_parsers.py +++ b/tests/unit/test_eval_strict_parsers.py @@ -219,14 +219,24 @@ def test_valid_ecar_user_session_login(self): def test_invalid_unknown_object(self): """Object type not in the allowed set — fails.""" raw = '{"object": "KERNEL_MODULE", "action": "CREATE"}' - result = validate_strict("ecar", raw, {}) + import json + + from evidenceforge.formats.loader import load_format + from evidenceforge.formats.validator import validate_event + + result = validate_event(load_format("ecar"), json.loads(raw)) assert not result.valid assert any("kernel_module" in e.lower() or "object" in e.lower() for e in result.errors) def test_invalid_unknown_action(self): """Action not in the allowed set — fails.""" raw = '{"object": "PROCESS", "action": "EXPLODE"}' - result = validate_strict("ecar", raw, {}) + import json + + from evidenceforge.formats.loader import load_format + from evidenceforge.formats.validator import validate_event + + result = validate_event(load_format("ecar"), json.loads(raw)) assert not result.valid assert any("explode" in e.lower() or "action" in e.lower() for e in result.errors) diff --git a/tests/unit/test_eval_thresholds.py b/tests/unit/test_eval_thresholds.py index 74e49014e..cce809d26 100644 --- a/tests/unit/test_eval_thresholds.py +++ b/tests/unit/test_eval_thresholds.py @@ -7,7 +7,6 @@ EvalThresholds, PillarThresholds, SubScoreThreshold, - _defaults, load_thresholds, ) @@ -138,10 +137,13 @@ def test_hard_gates_cover_all_high_impact_acceptance_contracts(self): "storyline_trace_coverage", } <= gates - def test_defaults_fallback(self): - """_defaults() should return a valid minimal EvalThresholds.""" - thresh = _defaults() - assert isinstance(thresh, EvalThresholds) - assert thresh.overall_minimum == 70.0 - assert thresh.overall_aspirational == 85.0 - assert len(thresh.pillars) == 0 + def test_missing_policy_fails_closed(self, monkeypatch): + import pytest + + from evidenceforge.models.exceptions import ConfigurationError + + load_thresholds.cache_clear() + monkeypatch.setattr("evidenceforge.evaluation.thresholds.load_rules_file", lambda _: {}) + with pytest.raises(ConfigurationError, match="thresholds.yaml"): + load_thresholds() + load_thresholds.cache_clear() diff --git a/tests/unit/test_exact_publication.py b/tests/unit/test_exact_publication.py index e0ae0bcc9..69f8b55cf 100644 --- a/tests/unit/test_exact_publication.py +++ b/tests/unit/test_exact_publication.py @@ -5,10 +5,12 @@ from __future__ import annotations +import builtins import gc from pathlib import Path from threading import Event, Thread from time import monotonic, sleep +from typing import Any from weakref import ref import pytest @@ -23,7 +25,7 @@ LogEmitter, stage_exact_publication_row, ) -from evidenceforge.generation.emitters.host_base import HostMultiplexEmitter +from evidenceforge.generation.emitters.host_base import HostMultiplexEmitter, _SingleHostWriter from evidenceforge.generation.emitters.zeek_base import SensorMultiplexEmitter @@ -66,6 +68,37 @@ def _new_batch() -> ExactPublicationBatch: return ExactPublicationAuthority(capacity=1).issue_batch() +def test_sorted_host_writer_uses_lf_for_checkpoint_equivalence( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Ordinary sorted output must match checkpoint external-sort newline bytes.""" + + output = tmp_path / "host.log" + original_open = builtins.open + newline_arguments: list[str | None] = [] + + def recording_open(*args: Any, **kwargs: Any) -> Any: + if args and Path(args[0]) == output: + newline = kwargs.get("newline") + assert newline is None or isinstance(newline, str) + newline_arguments.append(newline) + return original_open(*args, **kwargs) + + monkeypatch.setattr(builtins, "open", recording_open) + writer = _SingleHostWriter( + output, + sort_on_flush=True, + defer_sorted_flush_until_close=True, + ) + writer.write("second") + writer.write("first") + writer.close() + + assert newline_arguments == ["\n"] + assert output.read_bytes() == b"first\nsecond\n" + + def _wait_for_pending_exact_registration(emitter: LogEmitter) -> None: deadline = monotonic() + 2 while monotonic() < deadline: diff --git a/tests/unit/test_format_def.py b/tests/unit/test_format_def.py index d76a80590..626293732 100644 --- a/tests/unit/test_format_def.py +++ b/tests/unit/test_format_def.py @@ -67,7 +67,6 @@ def test_empty_constraint(self): assert constraint.min_value is None assert constraint.max_value is None assert constraint.allowed_values is None - assert constraint.json_logic is None def test_pattern_constraint(self): """Test constraint with pattern.""" @@ -99,8 +98,8 @@ def test_enum_constraint_with_integers(self): def test_json_logic_constraint(self): """Test constraint with JSON Logic rule.""" rule = {"==": [{"var": "LogonType"}, 3]} - constraint = FieldConstraint(json_logic=rule) - assert constraint.json_logic == rule + with pytest.raises(ValidationError, match="json_logic"): + FieldConstraint(json_logic=rule) def test_extra_fields_rejected(self): """Test that extra fields are rejected.""" @@ -337,7 +336,15 @@ def test_full_format(self): ) ] output = OutputTemplate(format="xml", template="", file_extension=".xml") - validators = [{"==": [{"var": "field1"}, "value"]}] + validators = [ + { + "id": "test.equal", + "message": "Expected value", + "checks": [ + {"op": "compare", "field": "field1", "relation": "eq", "value": "value"} + ], + } + ] fmt = FormatDefinition( name="test_format", @@ -354,7 +361,7 @@ def test_full_format(self): assert fmt.category == "network" assert len(fmt.fields) == 2 assert len(fmt.variants) == 1 - assert fmt.validators == validators + assert fmt.validators[0].id == "test.equal" def test_all_categories_valid(self): """Test that all valid categories work.""" diff --git a/tests/unit/test_format_validator.py b/tests/unit/test_format_validator.py index 69b4d7696..e9d08f939 100644 --- a/tests/unit/test_format_validator.py +++ b/tests/unit/test_format_validator.py @@ -336,26 +336,11 @@ def test_allowed_values_invalid(self): assert result.valid is False assert "must be one of" in result.errors[0] - def test_json_logic_simple_valid(self): - """Test simple JSON Logic rule passes.""" - constraints = FieldConstraint(json_logic={"==": [{"var": "value"}, 42]}) - result = validate_field_constraints("field", 42, constraints) - assert result.valid is True - - def test_json_logic_simple_invalid(self): - """Test simple JSON Logic rule fails.""" - constraints = FieldConstraint(json_logic={"==": [{"var": "value"}, 42]}) - result = validate_field_constraints("field", 99, constraints) - assert result.valid is False - assert "Failed JSON Logic" in result.errors[0] + def test_legacy_json_logic_rejected(self): + from pydantic import ValidationError - @pytest.mark.parametrize("falsey_result", [0, "", []]) - def test_json_logic_falsey_non_boolean_invalid(self, falsey_result): - """Test JSON Logic falsey non-boolean outputs fail validation.""" - constraints = FieldConstraint(json_logic={"var": "value"}) - result = validate_field_constraints("field", falsey_result, constraints) - assert result.valid is False - assert "Failed JSON Logic" in result.errors[0] + with pytest.raises(ValidationError, match="json_logic"): + FieldConstraint(json_logic={"==": [{"var": "value"}, 42]}) def test_multiple_constraints(self): """Test multiple constraints together.""" @@ -555,7 +540,20 @@ def test_cross_field_validator_pass(self): FieldDefinition(name="field2", type=FieldType.INTEGER), ], output=OutputTemplate(format="text", template="t", file_extension=".txt"), - validators=[{"<": [{"var": "field1"}, {"var": "field2"}]}], + validators=[ + { + "id": "test.order", + "message": "ordered", + "checks": [ + { + "op": "compare", + "field": "field1", + "relation": "lt", + "other_field": "field2", + } + ], + } + ], ) event_data = {"field1": 10, "field2": 20} result = validate_event(format_def, event_data) @@ -572,7 +570,20 @@ def test_cross_field_validator_fail(self): FieldDefinition(name="field2", type=FieldType.INTEGER), ], output=OutputTemplate(format="text", template="t", file_extension=".txt"), - validators=[{"<": [{"var": "field1"}, {"var": "field2"}]}], + validators=[ + { + "id": "test.order", + "message": "ordered", + "checks": [ + { + "op": "compare", + "field": "field1", + "relation": "lt", + "other_field": "field2", + } + ], + } + ], ) event_data = {"field1": 30, "field2": 20} result = validate_event(format_def, event_data) diff --git a/tests/unit/test_install_skills.py b/tests/unit/test_install_skills.py index 459fadbd9..ec9206d42 100644 --- a/tests/unit/test_install_skills.py +++ b/tests/unit/test_install_skills.py @@ -130,6 +130,11 @@ }, } +EXPECTED_CHATGPT_REFERENCES = { + name: refs | {"references/record-validation.md"} + for name, refs in EXPECTED_CHATGPT_REFERENCES.items() +} + class TestInstallSkills: """Tests for install_skills() function.""" @@ -486,11 +491,14 @@ def test_chatgpt_reference_bundles_exclude_large_or_unrelated_contracts(self): & scenario_refs ) - assert set(_CHATGPT_REFERENCES_BY_SKILL["evaluate"]) == EVIDENCE_REFERENCES + assert ( + set(_CHATGPT_REFERENCES_BY_SKILL["evaluate"]) == EXPECTED_CHATGPT_REFERENCES["evaluate"] + ) assert ( set(_CHATGPT_REFERENCES_BY_SKILL["generate"]) == EXPECTED_CHATGPT_REFERENCES["generate"] ) assert set(_CHATGPT_REFERENCES_BY_SKILL["validate"]) == { + "references/record-validation.md", "references/project-context.md", "references/validation-safety.md", "references/validation-storage.md", diff --git a/tests/unit/test_native_record_mutations.py b/tests/unit/test_native_record_mutations.py new file mode 100644 index 000000000..ddb80c5b2 --- /dev/null +++ b/tests/unit/test_native_record_mutations.py @@ -0,0 +1,355 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Single-property corruption across native parsing and exact acceptance gates.""" + +import json +import re +import xml.etree.ElementTree as ET +from pathlib import Path + +import pytest + +from evidenceforge.evaluation.engine import _build_acceptance_criteria +from evidenceforge.evaluation.models import PillarScore +from evidenceforge.evaluation.parsers import get_parser +from evidenceforge.evaluation.pillars.parseability import ParseabilityScorer +from evidenceforge.evaluation.thresholds import load_thresholds +from evidenceforge.formats.loader import load_format +from tests.support.native_records import render_record + +ROOT = Path(__file__).parents[1] / "fixtures/record_validation" +CASES = json.loads((ROOT / "formats.json").read_text()) + json.loads( + (ROOT / "windows_variants.json").read_text() +) +MUTATIONS = [] +for case in CASES: + definition = load_format(case["format"]) + if definition.output.format not in ("json", "xml"): + continue + for field in definition.validation_fields(case.get("variant")).values(): + if not field.required: + continue + for mode in ("missing", "empty", "wrong_type", "null"): + if mode == "null" and (definition.output.format == "xml" or field.nullable): + continue + if mode == "empty" and field.type.value in ("string", "list"): + continue # Empty text/lists are legal unless a separate rule constrains them. + if ( + mode == "wrong_type" + and definition.output.format == "xml" + and field.type.value in ("string", "enum") + ): + continue # XML attributes/text have no independent object-valued representation. + MUTATIONS.append((case, field.name, mode)) + + +def mutate_native(raw: str, name: str, field: str, mode: str) -> str: + if name.startswith("windows_"): + ET.register_namespace("", "http://schemas.microsoft.com/win/2004/08/events/event") + root = ET.fromstring(raw) + if field in {"ExecutionProcessID", "ExecutionThreadID"}: + target = next(e for e in root.iter() if e.tag.endswith("}Execution")) + attribute = field.removeprefix("Execution") + if mode == "missing": + del target.attrib[attribute] + else: + target.set(attribute, "" if mode == "empty" else "invalid-value") + return ET.tostring(root, encoding="unicode") + target = next( + ( + e + for e in root.iter() + if e.attrib.get("Name") == field or e.tag.rsplit("}", 1)[-1] == field + ), + None, + ) + assert target is not None, field + if mode == "missing": + parent = next(p for p in root.iter() if target in list(p)) + parent.remove(target) + elif field == "TimeCreated": + target.set("SystemTime", "" if mode == "empty" else "invalid-time") + else: + target.text = "" if mode == "empty" else "invalid-value" + return ET.tostring(root, encoding="unicode") + obj = json.loads(raw) + container = obj.get("properties", {}) if field in obj.get("properties", {}) else obj + assert field in container, field + if mode == "missing": + del container[field] + elif mode == "empty": + container[field] = "" + elif mode == "null": + container[field] = None + else: + container[field] = {"invalid": "type"} + return json.dumps(obj) + + +@pytest.mark.parametrize( + "case,field,mode", + MUTATIONS, + ids=[f"{c.get('variant', c['format'])}:{f}:{m}" for c, f, m in MUTATIONS], +) +def test_corrupt_required_field_cannot_pass_acceptance( + tmp_path: Path, case: dict, field: str, mode: str +) -> None: + raw = render_record(tmp_path, case) + path = tmp_path / "mutated.log" + path.write_text(mutate_native(raw, case["format"], field, mode) + "\n") + records = list(get_parser(case["format"]).parse_file(path)) + assert len(records) == 1 + scores = ParseabilityScorer()._score_both({case["format"]: records}) + assert any(s.score < 100 for s in scores), (field, mode, scores) + assert any(s.sample_findings for s in scores) + pillar = PillarScore( + number=1, name="Parseability", weight=0.3, score=0, sub_scores=list(scores) + ) + gates = _build_acceptance_criteria(load_thresholds(), [pillar]) + assert any(g.pillar == "parseability" and g.passed is False for g in gates) + + +@pytest.mark.parametrize( + "name", ["bash_history", "syslog", "cisco_asa", "snort_alert", "web_access", "proxy_access"] +) +def test_text_source_malformed_timestamp_is_counted(tmp_path: Path, name: str) -> None: + + case = next(c for c in CASES if c["format"] == name) + raw = render_record(tmp_path, case) + if name == "bash_history": + raw = re.sub(r"^#[0-9]+", "#" + "9" * 40, raw) + elif name in {"web_access", "proxy_access"}: + raw = re.sub(r"\[[^]]+\]", "[invalid-time]", raw, count=1) + elif name == "snort_alert": + raw = "99/99-99:99:99.000000" + raw[raw.index(" ") :] + elif name == "syslog": + raw = re.sub(r"2024-01-15T[^ ]+", "2024-99-99T99:99:99Z", raw) + else: + raw = raw.replace("Jan 15 10:01:21", "Jan 99 99:99:99") + path = tmp_path / "bad.log" + path.write_text(raw + "\n") + records = list(get_parser(name).parse_file(path)) + assert records + scores = ParseabilityScorer()._score_both({name: records}) + assert scores[0].score < 100 + assert scores[0].sample_findings + + +def test_malformed_native_records_complete_all_pillars(tmp_path: Path) -> None: + from typer.testing import CliRunner + + from evidenceforge.cli.commands import app + + expected = {} + rendered = { + (c["format"], c.get("variant")): render_record(tmp_path / "render", c) for c in CASES + } + for case, field, mode in MUTATIONS: + name = case["format"] + raw = rendered[(name, case.get("variant"))] + path = tmp_path / (name + (".xml" if name.startswith("windows_") else ".json")) + with path.open("a") as stream: + stream.write(mutate_native(raw, name, field, mode) + "\n") + expected[name] = expected.get(name, 0) + 1 + for case, field in JSON_FIELD_CASES: + name = case["format"] + obj = json.loads(rendered[(name, case.get("variant"))]) + container = obj["properties"] if name == "ecar" and field.name not in obj else obj + container[field.name] = {"wrong": "type"} + with (tmp_path / (name + ".json")).open("a") as stream: + stream.write(json.dumps(obj) + "\n") + expected[name] = expected.get(name, 0) + 1 + for name in ( + "bash_history", + "syslog", + "snort_alert", + "cisco_asa", + "web_access", + "proxy_access", + ): + path = tmp_path / ("bash_history/user.history" if name == "bash_history" else name + ".log") + path.parent.mkdir(exist_ok=True) + raw = ( + "#" + "9" * 40 + "\nls" + if name == "bash_history" + else "invalid-header " + rendered[(name, None)] + ) + path.write_text(raw + "\n") + expected[name] = len(list(get_parser(name).parse_file(path))) + assert len(expected) == 25 + result = CliRunner().invoke( + app, + [ + "eval", + str(tmp_path), + "--scenario", + str(ROOT.parent / "scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ], + ) + assert result.exit_code == 0, result.stderr + report = json.loads(result.stdout) + assert report["acceptance_passed"] is False + for name, count in expected.items(): + assert report["source_counts"][name] == count + assert all(p["score"] is not None for p in report["pillars"]) + + +RULE_CASES = json.loads((ROOT / "rule_cases.json").read_text()) + + +@pytest.mark.parametrize("witness", RULE_CASES, ids=lambda c: c["rule"]) +@pytest.mark.parametrize("outcome", ["pass", "fail"]) +def test_rule_witness_through_native_parser(tmp_path: Path, witness: dict, outcome: str) -> None: + from evidenceforge.evaluation.pillars.parseability import ( + _get_variant, + _normalize_for_validation, + ) + from evidenceforge.formats.loader import load_all_formats + from evidenceforge.formats.validator import validate_event + + definition, rule = next( + (d, r) + for d in load_all_formats().values() + for r in d.validators or [] + if r.id == witness["rule"] + ) + fields = dict(witness[outcome]) + if definition.name == "ecar" and "target_pid" in fields: + fields["target_pid"] = str(fields["target_pid"]) + candidates = [c for c in CASES if c["format"] == definition.name] + case = next( + (c for c in candidates if c["fields"].get("EventID") == fields.get("EventID")), + candidates[0], + ) + raw = render_record(tmp_path, case) + if definition.output.format == "xml": + ET.register_namespace("", "http://schemas.microsoft.com/win/2004/08/events/event") + root = ET.fromstring(raw) + event_data = next(e for e in root.iter() if e.tag.endswith("}EventData")) + for key in set(witness["pass"]) | set(witness["fail"]): + target = next( + ( + e + for e in root.iter() + if e.attrib.get("Name") == key or e.tag.endswith("}" + key) + ), + None, + ) + if key not in fields: + if target is not None: + next(p for p in root.iter() if target in list(p)).remove(target) + else: + if target is None: + target = ET.SubElement( + event_data, + "{http://schemas.microsoft.com/win/2004/08/events/event}Data", + Name=key, + ) + target.text = str(fields[key]) + raw = ET.tostring(root, encoding="unicode") + elif definition.output.format == "text": + if definition.name == "web_access": + raw = f'10.0.0.1 - - [15/Jun/2025:15:06:40 +0000] "{fields.get("method", "GET")} / HTTP/1.1" {fields.get("status_code", 200)} 1 "-" "-"' + elif definition.name == "syslog": + raw = f"<30>1 2024-01-15T10:00:00Z {fields.get('hostname', 'ws01')} sshd 1 - - {fields.get('message', 'accepted')}" + elif definition.name == "snort_alert": + raw = f"06/15-15:06:40.000000 [**] [1:1:1] test [**] [Classification: test] [Priority: {fields.get('priority', 1)}] {{TCP}} {fields.get('src_ip', '10.0.0.1') if witness['rule'].endswith('-1') else fields.get('src_ip', '')} -> {fields.get('dst_ip', '10.0.0.2')}" + else: + assert definition.name == "bash_history" + if witness["rule"] == "bash_history.legacy-2" and outcome == "fail": + pytest.skip( + "Username is derived from a nonempty filename; empty username has no native representation" + ) + raw = "#1750000000\n" + fields.get("command", "ls") + else: + assert definition.output.format == "json", definition.name + obj = json.loads(raw) + for key in set(witness["pass"]) | set(witness["fail"]): + container = obj["properties"] if definition.name == "ecar" and key not in obj else obj + if key in fields: + container[key] = fields[key] + else: + container.pop(key, None) + raw = json.dumps(obj) + path = tmp_path / "witness.log" + path.write_text(raw + "\n") + records = list(get_parser(definition.name).parse_file(path)) + assert len(records) == 1 + record = records[0] + result = validate_event( + definition, + _normalize_for_validation(definition.name, record.fields, record.timestamp), + _get_variant(definition.name, record), + ) + finding = next(f for f in result.findings if f.rule_id == rule.id) + if outcome == "pass": + assert finding.outcome == outcome, result.findings + else: + assert ( + finding.outcome == "fail" + or record.parse_errors + or any( + f.category in {"schema", "constraint"} + and f.outcome == "fail" + and set(f.fields) & set(finding.fields) + for f in result.findings + ) + ), result.findings + scores = ParseabilityScorer()._score_both({definition.name: records}) + if outcome == "fail" and rule.severity == "error": + assert scores[1].score < 100 or scores[0].score < 100 + + +JSON_FIELD_CASES = [ + (case, field) + for case in CASES + if load_format(case["format"]).output.format == "json" + for field in load_format(case["format"]).validation_fields(case.get("variant")).values() +] + + +@pytest.mark.parametrize( + "case,field", JSON_FIELD_CASES, ids=[f"{c['format']}:{f.name}" for c, f in JSON_FIELD_CASES] +) +def test_json_scalar_edges_and_native_sentinels(tmp_path: Path, case: dict, field) -> None: + from evidenceforge.evaluation.pillars.parseability import _normalize_for_validation + from evidenceforge.formats.validator import validate_event, validate_field + + raw = json.loads(render_record(tmp_path, case)) + candidates = [None, "", "-", {"wrong": "type"}] + if field.type.value == "list": + candidates.extend([[], [None], ["wrong-element"]]) + bounds = field.constraints + if bounds: + for bound in (bounds.min_value, bounds.max_value): + if bound is not None: + candidates.extend([int(bound) - 1, int(bound), int(bound) + 1]) + if field.type.value in {"float", "integer"}: + candidates.extend([float("inf"), float("nan")]) + for value in candidates: + obj = json.loads(json.dumps(raw)) + container = obj["properties"] if case["format"] == "ecar" and field.name not in obj else obj + container[field.name] = value + path = tmp_path / "edge.log" + path.write_text(json.dumps(obj) + "\n") + records = list(get_parser(case["format"]).parse_file(path)) + assert len(records) == 1 + record = records[0] + normalized = _normalize_for_validation(case["format"], record.fields, record.timestamp) + result = validate_event(load_format(case["format"]), normalized) + assert all(f.outcome != "evaluation_error" for f in result.findings) + scores = ParseabilityScorer()._score_both({case["format"]: records}) + if record.parse_errors or not validate_field(field, normalized.get(field.name)).valid: + assert any(s.score < 100 for s in scores), (field.name, value) + + +@pytest.mark.parametrize("digits", [40, 5000]) +def test_bash_oversized_epoch_is_evidence_failure(tmp_path: Path, digits: int) -> None: + path = tmp_path / "user.history" + path.write_text("#" + "9" * digits + "\nls\n") + records = list(get_parser("bash_history").parse_file(path)) + assert len(records) == 1 and records[0].parse_errors + assert ParseabilityScorer()._score_both({"bash_history": records})[0].score == 0 diff --git a/tests/unit/test_phase5_failed_logon.py b/tests/unit/test_phase5_failed_logon.py index 5e33a6ef5..6a7afe010 100644 --- a/tests/unit/test_phase5_failed_logon.py +++ b/tests/unit/test_phase5_failed_logon.py @@ -286,6 +286,33 @@ def test_4625_with_all_fields_validates(self): result = validate_event(fmt_def, event, variant_name="failed_logon") assert result.valid, f"Validation errors: {result.errors}" + def test_4771_rejects_missing_ip_sentinel(self): + """A 4771 client address must be a source-native IP, including for localhost.""" + fmt_def = load_format("windows_event_security") + event = { + "EventID": 4771, + "TimeCreated": "2024-03-15T10:00:00Z", + "Computer": "DC-01.corp.local", + "Channel": "Security", + "Level": 0, + "EventRecordID": 1001, + "ExecutionProcessID": 624, + "ExecutionThreadID": 100, + "TargetUserName": "alice.smith", + "TargetSid": "S-1-5-21-123-456-789-1001", + "ServiceName": "krbtgt/CORP.LOCAL", + "TicketOptions": "0x40810010", + "Status": "0x18", + "PreAuthType": 2, + "IpAddress": "-", + "IpPort": 0, + } + + result = validate_event(fmt_def, event, variant_name="kerberos_preauth_failed") + + assert not result.valid + assert any(error.startswith("IpAddress:") for error in result.errors) + class TestFailedLogonRate: """Test that baseline activity includes ~10% failed logons.""" @@ -390,13 +417,20 @@ def test_failed_logon_dc_gets_4776(self, state_manager, mock_emitters, timestamp hostname="DC-01", ip="10.0.10.100", os="Windows Server 2019", type="domain_controller" ) user = User(username="alice", full_name="Alice", email="a@t.com", enabled=True) + source = System( + hostname="LT-SOURCE", + ip="10.0.10.2", + os="Linux Ubuntu 22.04", + type="workstation", + ) + ag._ip_to_system[source.ip] = source ag.generate_failed_logon( user=user, system=wks, time=timestamp, logon_type=3, - source_ip="10.0.10.1", + source_ip=source.ip, dc_system=dc, ) @@ -411,6 +445,7 @@ def test_failed_logon_dc_gets_4776(self, state_manager, mock_emitters, timestamp assert "ntlm_validation" in event_types, "Missing 4776 on DC" ntlm_event = next(e for e in dc_events if e.event_type == "ntlm_validation") assert ntlm_event.auth.failure_status != "0x0" + assert ntlm_event.auth.source_ip == "LT-SOURCE" def test_failed_logon_can_emit_kerberos_without_ntlm( self, state_manager, mock_emitters, timestamp, monkeypatch @@ -461,6 +496,13 @@ def test_failed_logon_can_emit_kerberos_without_ntlm( } assert "kerberos_preauth_failed" in event_types assert "ntlm_validation" not in event_types + kerberos_event = next( + call[0][0] + for call in mock_emitters["windows_event_security"].emit.call_args_list + if call[0][0].event_type == "kerberos_preauth_failed" + ) + assert kerberos_event.kerberos.source_ip == "::ffff:45.83.221.45" + assert kerberos_event.kerberos.source_port > 0 def test_failed_logon_network_evidence_is_not_syn_only( self, state_manager, mock_emitters, timestamp, monkeypatch diff --git a/tests/unit/test_record_contracts.py b/tests/unit/test_record_contracts.py new file mode 100644 index 000000000..ddc4208ca --- /dev/null +++ b/tests/unit/test_record_contracts.py @@ -0,0 +1,459 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Regression proofs for schema, predicate, parser, and scoring boundaries.""" + +import json +from pathlib import Path +from unittest.mock import patch + +import pytest +from pydantic import ValidationError + +from evidenceforge.evaluation.parsers import ParsedRecord, get_parser +from evidenceforge.evaluation.pillars.parseability import ParseabilityScorer, _get_variant +from evidenceforge.formats.format_def import FieldConstraint, FieldDefinition, FieldType +from evidenceforge.formats.loader import load_all_formats, load_format +from evidenceforge.formats.rules import RecordRule, evaluate_rule +from evidenceforge.formats.validator import validate_event, validate_field +from evidenceforge.models.exceptions import ConfigurationError + + +def dns_record() -> dict: + return { + "ts": 1750000000.0, + "uid": "C12345678901234567", + "id.orig_h": "10.0.0.1", + "id.orig_p": 12345, + "id.resp_h": "10.0.0.2", + "id.resp_p": 53, + "proto": "udp", + "trans_id": 1, + "query": "example.com", + "qtype": 1, + "qtype_name": "A", + "rcode": 0, + "rcode_name": "NOERROR", + "AA": False, + "TC": False, + "RD": True, + "RA": True, + "Z": 0, + "answers": ["10.0.0.3"], + "TTLs": [60.0], + "rejected": False, + "opcode": 0, + "opcode_name": "query", + "rtt": 0.02, + } + + +@pytest.mark.parametrize( + "change", + [ + {"qtype_name": "AAAA"}, + {"rcode_name": "NXDOMAIN"}, + {"TTLs": []}, + {"TTLs": ["sixty"]}, + {"answers": [42]}, + {"rtt": "bad"}, + {"rtt": -1.0}, + ], +) +def test_corrupted_dns_fails_through_parser_and_scoring(change: dict) -> None: + scorer = ParseabilityScorer() + parser = get_parser("zeek_dns") + good = parser._parse_line(json.dumps(dns_record()), 1) + bad = parser._parse_line(json.dumps(dns_record() | change), 2) + assert scorer._score_spec_conformance({"zeek_dns": [good]}).score == 100 + assert scorer._score_format_constraints({"zeek_dns": [good]}).score == 100 + scores = [ + scorer._score_spec_conformance({"zeek_dns": [bad]}), + scorer._score_format_constraints({"zeek_dns": [bad]}), + ] + assert any(score.score < 100 for score in scores) + + +@pytest.mark.parametrize("value", [True, "1", None, float("nan"), float("inf"), []]) +def test_float_rejects_nonfinite_or_nonnumeric(value: object) -> None: + field = FieldDefinition(name="duration", type=FieldType.FLOAT) + assert not validate_field(field, value).valid + + +def test_float_bounds_apply_and_zero_is_valid() -> None: + field = FieldDefinition( + name="duration", type=FieldType.FLOAT, constraints=FieldConstraint(min_value=0) + ) + assert validate_field(field, 0.0).valid + assert not validate_field(field, -0.1).valid + + +@pytest.mark.parametrize("format_name", sorted(load_all_formats())) +def test_every_format_loads_and_rejects_missing_required_fields(format_name: str) -> None: + definition = load_format(format_name) + assert not validate_event(definition, {}).valid + assert len({r.id for r in definition.validators or []}) == len(definition.validators or []) + + +@pytest.mark.parametrize( + "check", + [ + {"op": "typo", "field": "x"}, + {"op": "presence", "field": "x", "minimum": 0}, + {"op": "compare", "field": "x", "relation": "eq"}, + {"op": "compare", "field": "x", "relation": "eq", "value": 1, "other_field": "y"}, + {"op": "bounds", "field": "x", "minimum": 5, "maximum": 1}, + {"op": "pattern", "field": "x", "pattern": "["}, + ], +) +def test_malformed_predicates_fail_loading(check: dict) -> None: + with pytest.raises(ValidationError): + RecordRule(id="test", message="test", checks=[check]) + + +@pytest.mark.parametrize( + "check,good,bad", + [ + ({"op": "presence", "field": "x"}, {"x": 0}, {}), + ({"op": "presence", "field": "x", "present": False}, {}, {"x": 0}), + ( + {"op": "compare", "field": "x", "relation": "lt", "other_field": "y"}, + {"x": 1, "y": 2}, + {"x": 2, "y": 1}, + ), + ( + {"op": "compare", "field": "id.orig_h", "relation": "eq", "value": "10.0.0.1"}, + {"id.orig_h": "10.0.0.1"}, + {"id": {"orig_h": "10.0.0.1"}}, + ), + ( + {"op": "membership", "field": "x", "values": ["tcp", "udp"]}, + {"x": "tcp"}, + {"x": "other"}, + ), + ({"op": "bounds", "field": "x", "minimum": 0}, {"x": 0.0}, {"x": -0.1}), + ({"op": "length", "field": "x", "minimum": 1}, {"x": "a"}, {"x": ""}), + ({"op": "pattern", "field": "x", "pattern": "^a$"}, {"x": "a"}, {"x": "ab"}), + ( + {"op": "same_length", "field": "x", "other_field": "y"}, + {"x": [1], "y": [2]}, + {"x": [1], "y": []}, + ), + ( + {"op": "combination", "field": "x", "other_field": "y", "pairs": [["FILE", "RENAME"]]}, + {"x": "FILE", "y": "RENAME"}, + {"x": "FILE", "y": "LOGIN"}, + ), + ( + {"op": "address_family", "field": "x", "other_field": "y"}, + {"x": "::1", "y": "true"}, + {"x": "127.0.0.1", "y": "true"}, + ), + ], +) +def test_predicate_positive_negative_and_applicability(check: dict, good: dict, bad: dict) -> None: + rule = RecordRule(id="test", message="test", checks=[check]) + assert evaluate_rule(rule, good, "test", None).outcome == "pass" + assert evaluate_rule(rule, bad, "test", None).outcome == "fail" + conditional = rule.model_copy( + update={ + "when": ( + RecordRule( + id="condition", + message="condition", + checks=[{"op": "presence", "field": "enabled"}], + ).checks[0], + ) + } + ) + assert evaluate_rule(conditional, good, "test", None).outcome == "not_applicable" + + +def test_bad_schema_is_not_a_perfect_score() -> None: + record = ParsedRecord(source_format="zeek_dns", raw="{}", fields={}) + with patch( + "evidenceforge.evaluation.pillars.parseability.load_format", + side_effect=ConfigurationError("broken schema"), + ): + with pytest.raises(ConfigurationError): + ParseabilityScorer()._score_spec_conformance({"zeek_dns": [record]}) + + +@pytest.mark.parametrize( + "format_name,raw", + [ + ("zeek_dns", "[]"), + ("zeek_dns", '{"ts":Infinity}'), + ("zeek_dns", '{"ts":1,"ts":2}'), + ("ecar", "[]"), + ("ecar", '{"properties":[]}'), + ("ecar", '{"object":"FILE","properties":{"object":"PROCESS"}}'), + ], +) +def test_json_shape_errors_are_counted(format_name: str, raw: str) -> None: + record = get_parser(format_name)._parse_line(raw, 1) + assert record.parse_errors + assert ParseabilityScorer()._score_spec_conformance({format_name: [record]}).score == 0 + + +@pytest.mark.parametrize("raw", ["", "not XML"]) +def test_windows_truncated_and_nonxml_input_is_counted(tmp_path: Path, raw: str) -> None: + path = tmp_path / "windows_event_security.xml" + path.write_text(raw) + records = list(get_parser("windows_event_security").parse_file(path)) + assert len(records) == 1 and records[0].parse_errors + + +@pytest.mark.parametrize("event_id", [4778, 4779, 4699, 4700, 4701]) +def test_previously_unmapped_windows_events_require_variant_fields(event_id: int) -> None: + record = ParsedRecord( + source_format="windows_event_security", raw="", fields={"EventID": event_id} + ) + variant = _get_variant(record.source_format, record) + assert variant is not None + assert not validate_event(load_format(record.source_format), record.fields, variant).valid + + +def test_rdp_port_is_parsed_as_integer() -> None: + raw = '47783389' + assert get_parser("windows_event_security")._parse_event(raw, 1).fields["ClientPort"] == 3389 + + +RULE_CASES = json.loads( + (Path(__file__).parents[1] / "fixtures/record_validation/rule_cases.json").read_text() +) + + +@pytest.mark.parametrize("case", RULE_CASES, ids=lambda case: case["rule"]) +def test_every_bundled_rule_witness(case: dict) -> None: + from evidenceforge.formats.rules import rule_fields + + matches = [ + (definition, rule) + for definition in load_all_formats().values() + for rule in definition.validators or [] + if rule.id == case["rule"] + ] + assert len(matches) == 1 + definition, rule = matches[0] + assert evaluate_rule(rule, case["pass"], definition.name, None).outcome == "pass" + assert evaluate_rule(rule, case["fail"], definition.name, None).outcome == "fail" + assert ( + evaluate_rule(rule, case["pass"], definition.name, None, set(rule_fields(rule))).outcome + == "not_applicable" + ) + if rule.when: + assert evaluate_rule(rule, {}, definition.name, None).outcome == "not_applicable" + for check in rule.checks: + if check.op == "presence": + null = case["pass"] | {check.field: None} + assert evaluate_rule(rule, null, definition.name, None).outcome == "fail" + + +def test_bundled_rule_witness_inventory_is_complete() -> None: + ids = [ + rule.id + for definition in load_all_formats().values() + for rule in definition.validators or [] + ] + assert len(ids) == len(set(ids)) + assert set(ids) == {case["rule"] for case in RULE_CASES} + + +def test_source_native_sentinel_and_explicit_exclusion() -> None: + rule = load_format("windows_event_security").validators[0] + good = {"EventID": 4624, "LogonType": 3, "TargetUserName": "alice"} + for address in (None, "", "-"): + assert evaluate_rule(rule, good | {"IpAddress": address}, rule.id, None).outcome == "fail" + unusual = good | {"IpAddress": "-", "TargetUserName": "ANONYMOUS LOGON"} + assert evaluate_rule(rule, unusual, rule.id, None).outcome == "not_applicable" + + +def test_rule_execution_error_never_becomes_a_warning() -> None: + rule = RecordRule.model_validate( + { + "id": "test.error", + "severity": "warning", + "message": "Cannot compare", + "checks": [{"op": "compare", "field": "a", "other_field": "b", "relation": "lt"}], + } + ) + finding = evaluate_rule(rule, {"a": [], "b": 1}, "test", None) + assert finding.outcome == "evaluation_error" + assert finding.severity == "error" + + +def test_format_field_plan_is_cached_per_variant() -> None: + definition = load_format("windows_event_security") + assert definition.validation_fields("logon") is definition.validation_fields("logon") + assert definition.validation_fields( + "scheduled_task_deleted" + ) is not definition.validation_fields(None) + + +def test_partial_dns_observation_and_unknown_codes_remain_supported() -> None: + """Zeek DNS::Info permits unanswered and partially observed protocol messages.""" + fields = dns_record() + for name in ("rcode", "rcode_name", "AA", "RA", "answers", "TTLs"): + fields.pop(name) + assert validate_event(load_format("zeek_dns"), fields).valid + fields.update(qtype=65534, qtype_name="unknown-65534", rcode=1, rcode_name="FORMERR") + assert validate_event(load_format("zeek_dns"), fields).valid + + +def test_null_comparison_distinguishes_missing_from_explicit_null() -> None: + rule = RecordRule.model_validate( + { + "id": "test.null", + "message": "Explicit null", + "checks": [{"op": "compare", "field": "a", "relation": "eq", "value": None}], + } + ) + assert evaluate_rule(rule, {"a": None}, "test", None).outcome == "pass" + for fields in ({}, {"a": ""}, {"a": "-"}, {"a": 0}): + assert evaluate_rule(rule, fields, "test", None).outcome == "fail" + + +def test_one_violation_among_many_fails_exact_acceptance() -> None: + from evidenceforge.evaluation.engine import _build_acceptance_criteria + from evidenceforge.evaluation.models import PillarScore + from evidenceforge.evaluation.thresholds import load_thresholds + + parser = get_parser("zeek_dns") + good = parser._parse_line(json.dumps(dns_record()), 1) + bad = parser._parse_line(json.dumps(dns_record() | {"qtype_name": "AAAA"}), 1001) + sub = ParseabilityScorer()._score_format_constraints({"zeek_dns": [good] * 1000 + [bad]}) + assert 99 < sub.score < 100 + criteria = _build_acceptance_criteria( + load_thresholds(), + [ + PillarScore( + number=1, name="Parseability", weight=0.3, score=sub.score, sub_scores=[sub] + ), + ], + ) + assert ( + next(item for item in criteria if item.sub_score_key == "format_constraints").passed + is False + ) + + +@pytest.mark.parametrize("command", ["validate", "resolve", "validate-config"]) +def test_commands_report_broken_package_contract_in_json(command: str) -> None: + from typer.testing import CliRunner + + from evidenceforge.cli.commands import app + + arguments = [command] + if command != "validate-config": + arguments.append(str(Path(__file__).parents[1] / "fixtures/scenarios/minimal.yaml")) + arguments.append("--json") + if command == "resolve": + arguments.append("--explain-composition") + with patch( + "evidenceforge.formats.loader.validate_packaged_contracts", + side_effect=ConfigurationError( + "Invalid format definition in /package/formats/zeek_dns.yaml: unknown operation" + ), + ): + result = CliRunner().invoke(app, arguments) + assert result.exit_code != 0 + payload = json.loads(result.stdout) + assert "zeek_dns.yaml" in json.dumps(payload) + assert "unknown operation" in json.dumps(payload) + + +WINDOWS_CASES = json.loads( + (Path(__file__).parents[1] / "fixtures/record_validation/windows_variants.json").read_text() +) + + +@pytest.mark.parametrize("case", WINDOWS_CASES, ids=lambda case: case["variant"]) +def test_every_windows_variant_selects_and_validates(case: dict) -> None: + definition = load_format(case["format"]) + record = ParsedRecord(source_format=case["format"], raw="", fields=case["fields"]) + selected = _get_variant(case["format"], record) + assert selected == case["variant"] + result = validate_event(definition, record.fields, selected) + assert result.valid, result.errors + for field in definition.validation_fields(selected).values(): + if not field.required: + continue + incomplete = {name: value for name, value in record.fields.items() if name != field.name} + assert not validate_event(definition, incomplete, selected).valid + + +def test_windows_variant_positive_fixture_inventory() -> None: + expected = { + (name, variant.name) + for name in ("windows_event_security", "windows_event_sysmon") + for variant in load_format(name).variants + } + assert expected == {(case["format"], case["variant"]) for case in WINDOWS_CASES} + + +FORMAT_CASES = json.loads( + (Path(__file__).parents[1] / "fixtures/record_validation/formats.json").read_text() +) + + +@pytest.mark.parametrize("case", FORMAT_CASES, ids=lambda case: case["format"]) +def test_every_nonvariant_format_has_positive_and_mutation_witness(case: dict) -> None: + definition = load_format(case["format"]) + result = validate_event(definition, case["fields"]) + assert result.valid, result.errors + for field in definition.fields: + if field.required: + incomplete = { + name: value for name, value in case["fields"].items() if name != field.name + } + assert not validate_event(definition, incomplete).valid + + +def test_all_formats_have_positive_witnesses() -> None: + assert set(load_all_formats()) == {c["format"] for c in FORMAT_CASES + WINDOWS_CASES} + + +@pytest.mark.parametrize("name", ["packet_filter", "reporter", "weird"]) +def test_standalone_native_zeek_fixtures(name: str) -> None: + format_name = f"zeek_{name}" + path = Path(__file__).parents[1] / f"fixtures/record_validation/native/{name}.json" + records = list(get_parser(format_name).parse_file(path)) + assert len(records) == 1 + assert not records[0].parse_errors + assert validate_event(load_format(format_name), records[0].fields).valid + + +def test_windows_protocol_conversion_is_source_specific() -> None: + sysmon = get_parser("windows_event_sysmon") + security = get_parser("windows_event_security") + assert sysmon._coerce_event_data_field("Protocol", "tcp") == "tcp" + assert security._coerce_event_data_field("Protocol", "6") == 6 + with pytest.raises(ValueError, match="Protocol"): + security._coerce_event_data_field("Protocol", "tcp") + + +@pytest.mark.parametrize("raw", ["\n", "\n", "\n\n"]) +def test_malformed_windows_wrapper_does_not_disappear(tmp_path: Path, raw: str) -> None: + path = tmp_path / "windows_event_security.xml" + path.write_text(raw) + records = list(get_parser("windows_event_security").parse_file(path)) + assert records + assert all(record.parse_errors for record in records) + + +def test_empty_complete_windows_wrapper_has_no_records(tmp_path: Path) -> None: + path = tmp_path / "windows_event_security.xml" + path.write_text("\n\n") + assert list(get_parser("windows_event_security").parse_file(path)) == [] + + +@pytest.mark.parametrize("status", [199, 200, 201, 299, 300, 407, 500]) +def test_connect_body_rule_uses_the_entire_successful_status_class(status: int) -> None: + rule = load_format("zeek_http").validators[0] + fields = {"method": "CONNECT", "status_code": status, "response_body_len": 1} + expected = "fail" if 200 <= status <= 299 else "not_applicable" + assert evaluate_rule(rule, fields, "zeek_http", None).outcome == expected + fields["response_body_len"] = 0 + expected = "pass" if 200 <= status <= 299 else "not_applicable" + assert evaluate_rule(rule, fields, "zeek_http", None).outcome == expected diff --git a/tests/unit/test_snare_projection.py b/tests/unit/test_snare_projection.py new file mode 100644 index 000000000..7eb55b8bb --- /dev/null +++ b/tests/unit/test_snare_projection.py @@ -0,0 +1,237 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Snare preserves canonical facts and keeps historical omissions explicit.""" + +import json +from datetime import datetime +from pathlib import Path + +import pytest +from typer.testing import CliRunner + +from evidenceforge.cli.commands import app +from evidenceforge.evaluation.parsers import get_parser +from evidenceforge.evaluation.pillars.parseability import ParseabilityScorer +from evidenceforge.formats.snare import load_snare_projections +from evidenceforge.generation.emitters.windows_snare import ( + render_windows_security_snare_syslog, + render_windows_sysmon_snare_syslog, +) + +CASES = json.loads( + (Path(__file__).parents[1] / "fixtures/record_validation/windows_variants.json").read_text() +) +FULL_CASES = json.loads( + (Path(__file__).parents[1] / "fixtures/record_validation/snare_full_variants.json").read_text() +) + + +def render_case(case: dict) -> str: + fields = dict(case["fields"]) + fields["TimeCreated"] = datetime.fromisoformat(fields["TimeCreated"].replace("Z", "+00:00")) + renderer = ( + render_windows_security_snare_syslog + if case["format"].endswith("security") + else render_windows_sysmon_snare_syslog + ) + return renderer(fields) + + +@pytest.mark.parametrize("case", CASES + FULL_CASES, ids=lambda c: c["format"] + ":" + c["variant"]) +def test_snare_variant_preserves_canonical_fields(tmp_path: Path, case: dict) -> None: + path = tmp_path / (case["format"] + "_snare.log") + path.write_text(render_case(case) + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + assert not record.parse_errors + assert record.representation == "windows_snare" + for name, value in case["fields"].items(): + if name in {"TimeCreated", "Channel", "Provider", "UtcTime"}: + continue + assert record.fields.get(name) == value, (name, record.fields.get(name), value) + scores = ParseabilityScorer()._score_both({case["format"]: [record]}) + assert all(score.score == 100 for score in scores), [s.sample_findings for s in scores] + assert scores[0].unavailable_check_count == 0 + + +def test_projection_inventory_is_exhaustive() -> None: + assert len(load_snare_projections().events) == len(CASES) == 43 + + +@pytest.mark.parametrize("mutation", ["missing", "numeric", "alias", "computer", "timestamp"]) +def test_snare_corruption_remains_counted(tmp_path: Path, mutation: str) -> None: + case = next(c for c in CASES if c["fields"]["EventID"] == 4624) + raw = render_case(case) + if mutation == "missing": + raw = raw.replace("ExecutionProcessID: 1 ", "") + elif mutation == "numeric": + raw = raw.replace("ExecutionProcessID: 1", "ExecutionProcessID: invalid") + elif mutation == "alias": + raw = raw.replace("Account Name: example", "Account Name: conflicting") + elif mutation == "computer": + raw = raw.replace("\tMSWinEventLog", "-changed\tMSWinEventLog", 1) + else: + raw = raw.replace("TimeCreated: 2026-09-15T12:00:00", "TimeCreated: 2026-09-16T12:00:00") + path = tmp_path / "windows_event_security_snare.log" + path.write_text(raw + "\n") + records = list(get_parser(case["format"]).parse_file(path)) + assert len(records) == 1 + scores = ParseabilityScorer()._score_both({case["format"]: records}) + assert scores[0].score == 0 + assert scores[0].sample_findings + result = CliRunner().invoke( + app, + [ + "eval", + str(tmp_path), + "--scenario", + str(Path(__file__).parents[1] / "fixtures/scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ], + ) + assert result.exit_code == 0, result.stderr + report = json.loads(result.stdout) + assert report["source_counts"][case["format"]] == 1 + assert report["acceptance_passed"] is False + + +@pytest.mark.parametrize("case", CASES, ids=lambda c: c["variant"]) +def test_snare_missing_system_metadata_is_invalid_in_current_projection( + tmp_path: Path, case: dict +) -> None: + raw = render_case(case) + raw = raw.replace(f"Level: {case['fields']['Level']} ", "") + path = tmp_path / (case["format"] + "_snare.log") + path.write_text(raw + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + schema, _ = ParseabilityScorer()._score_both({case["format"]: [record]}) + assert schema.score == 0 + assert any(f.rule_id == "Level" for f in schema.sample_findings) + + +def test_scoped_logon_ids_do_not_feed_generic_upstream_pattern() -> None: + case = next(c for c in CASES if c["fields"]["EventID"] == 4624) + raw = render_case(case) + assert "Canonical[SubjectLogonId]: 0x1" in raw + assert "Canonical[TargetLogonId]: 0x1" in raw + assert "SubjectLogonId: " not in raw + + +def test_unsupported_event_is_a_record_failure(tmp_path: Path) -> None: + case = CASES[0] + raw = render_case(case).replace(f"\t{case['fields']['EventID']}\t", "\t99999\t") + path = tmp_path / (case["format"] + "_snare.log") + path.write_text(raw + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + assert "Unsupported Snare EventID: 99999" in record.parse_errors + + +def test_generic_identity_labels_never_mix_subject_and_target() -> None: + for projection in load_snare_projections().events: + owners = { + owner.removesuffix("UserSid") + .removesuffix("UserName") + .removesuffix("DomainName") + .removesuffix("LogonId") + for label, owner in projection.aliases.items() + if label in {"Security ID", "Account Name", "Account Domain", "Logon ID"} + } + assert len(owners) <= 1, projection + + +def test_native_port_sentinel_is_preserved(tmp_path: Path) -> None: + case = next(c for c in CASES if c["fields"]["EventID"] == 4624) + case = case | {"fields": case["fields"] | {"IpPort": "-"}} + path = tmp_path / "windows_event_security_snare.log" + path.write_text(render_case(case) + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + assert not record.parse_errors + assert record.fields["IpPort"] == "-" + schema, _ = ParseabilityScorer()._score_both({case["format"]: [record]}) + assert schema.score == 100 + + +def test_empty_certificate_fields_do_not_attach_to_previous_port(tmp_path: Path) -> None: + case = next(c for c in CASES if c["fields"]["EventID"] == 4768) + case = case | { + "fields": case["fields"] + | {"IpPort": 50000, "CertIssuerName": "", "CertSerialNumber": "", "CertThumbprint": ""} + } + path = tmp_path / "windows_event_security_snare.log" + path.write_text(render_case(case) + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + assert not record.parse_errors + assert record.fields["IpPort"] == 50000 + assert record.fields["CertIssuerName"] == "" + assert record.fields["CertSerialNumber"] == "" + assert record.fields["CertThumbprint"] == "" + schema, _ = ParseabilityScorer()._score_both({case["format"]: [record]}) + assert schema.score == 100 + + +@pytest.mark.parametrize( + "mutation", + ["unknown", "duplicate", "missing", "reference", "label", "decimal", "fallback", "bool_id"], +) +def test_malformed_projection_definitions_fail_at_load(mutation: str) -> None: + from pydantic import ValidationError + + from evidenceforge.formats.snare import SnareProjections + + document = load_snare_projections().model_dump(mode="json") + event = document["events"][0] + if mutation == "unknown": + event["unexpected"] = True + elif mutation == "duplicate": + document["events"].append(event.copy()) + elif mutation == "missing": + document["events"].pop() + elif mutation == "reference": + event["aliases"]["Bad field"] = "Nonexistent" + elif mutation == "label": + event["aliases"]["Injected: field"] = "SubjectUserName" + elif mutation == "decimal": + event["decimal_aliases"]["Number"] = "SubjectUserName" + elif mutation == "fallback": + event["fallback_aliases"] = {"Process ID": "SubjectLogonId"} + else: + event["event_id"] = True + with pytest.raises(ValidationError): + SnareProjections.model_validate(document) + + +@pytest.mark.parametrize("source", ["windows_event_security", "windows_event_sysmon"]) +def test_committed_iteration_snare_fixture(source: str) -> None: + path = ( + Path(__file__).parents[1] + / "fixtures/record_validation/targets/snare_v1" + / (source + "_snare.log") + ) + (record,) = get_parser(source).parse_file(path) + assert not record.parse_errors + assert record.fields["ProjectionVersion"] == "1" + assert record.fields["ExecutionProcessID"] >= 0 + assert all(s.score == 100 for s in ParseabilityScorer()._score_both({source: [record]})) + + +def test_snare_counter_and_windows_record_id_are_distinct(tmp_path: Path) -> None: + case = CASES[0] + raw = render_case(case).replace("EventRecordID: 1 ", "EventRecordID: 100 ") + path = tmp_path / (case["format"] + "_snare.log") + path.write_text(raw + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + assert not record.parse_errors + assert record.fields["SnareCounter"] == 1 + assert record.fields["EventRecordID"] == 100 + assert all(s.score == 100 for s in ParseabilityScorer()._score_both({case["format"]: [record]})) + + +def test_supplied_sysmon_utc_time_is_not_replaced(tmp_path: Path) -> None: + case = next(c for c in CASES if c["format"].endswith("sysmon")) + case = case | {"fields": case["fields"] | {"UtcTime": "2026-09-15 11:59:59.987"}} + path = tmp_path / "windows_event_sysmon_snare.log" + path.write_text(render_case(case) + "\n") + (record,) = get_parser(case["format"]).parse_file(path) + assert not record.parse_errors + assert record.fields["UtcTime"] == case["fields"]["UtcTime"] diff --git a/tests/unit/test_sof_elk_combined_harness.py b/tests/unit/test_sof_elk_combined_harness.py index 623c33533..6c1c199d5 100644 --- a/tests/unit/test_sof_elk_combined_harness.py +++ b/tests/unit/test_sof_elk_combined_harness.py @@ -92,6 +92,10 @@ def test_build_sof_elk_configs_uses_one_pipeline_and_all_inputs( ).read_text(encoding="utf-8") assert "6018-cisco_asa.conf" in config.sof_elk_filter_files assert "6100-httpd.conf" in config.sof_elk_filter_files + assert "8054-postprocess-useragent.conf" in config.sof_elk_filter_files + assert "8004-postprocess-httpd.conf" in config.sof_elk_filter_files + assert "8060-postprocess-useragent.conf" not in config.sof_elk_filter_files + assert "8110-postprocess-httpd.conf" not in config.sof_elk_filter_files assert "6015-sshd.conf" in config.sof_elk_filter_files assert not (config.pipeline_dir / "6018-cisco_asa.conf").exists() assert not (config.pipeline_dir / "6100-httpd.conf").exists() diff --git a/tests/unit/test_sof_elk_sources_harness.py b/tests/unit/test_sof_elk_sources_harness.py index 9700a8cef..b6086077f 100644 --- a/tests/unit/test_sof_elk_sources_harness.py +++ b/tests/unit/test_sof_elk_sources_harness.py @@ -347,6 +347,87 @@ def test_validate_source_parsed_output_accepts_syslog_parse(tmp_path: Path) -> N assert not (parsed_dir / FAILURE_REPORT_FILENAME).exists() +def test_validate_source_parsed_output_accepts_pinned_asa_probe_miss( + tmp_path: Path, +) -> None: + manifest = _manifest( + tmp_path, + SYSLOG_SPEC, + Path("syslog/2026/linux-01/syslog.log"), + "syslog.log", + source_year=2026, + ) + parsed_dir = tmp_path / "parsed" + parsed_dir.mkdir() + event = _parsed_syslog_event() + event["tags"] = ["filebeat", "process_archive", "_grokparsefailure"] + event["process"] = {"name": "packagekitd"} + log = event["log"] + assert isinstance(log, dict) + syslog = log["syslog"] + assert isinstance(syslog, dict) + syslog["appname"] = "packagekitd" + _write_jsonl(parsed_dir / EVENTS_OUTPUT_FILENAME, [event]) + + events = validate_source_parsed_output(manifest, parsed_dir) + + assert len(events) == 1 + assert not (parsed_dir / FAILURE_REPORT_FILENAME).exists() + + +@pytest.mark.parametrize( + ("process_name", "remove_hostname"), + [("AABBCCDDEEFF,UAP-AC-Pro", False), ("packagekitd", True)], +) +def test_validate_source_parsed_output_keeps_other_generic_grok_failures_fatal( + tmp_path: Path, + process_name: str, + remove_hostname: bool, +) -> None: + manifest = _manifest( + tmp_path, + SYSLOG_SPEC, + Path("syslog/2026/linux-01/syslog.log"), + "syslog.log", + source_year=2026, + ) + parsed_dir = tmp_path / "parsed" + parsed_dir.mkdir() + event = _parsed_syslog_event() + event["tags"] = ["filebeat", "process_archive", "_grokparsefailure"] + event["process"] = {"name": process_name} + if remove_hostname: + log = event["log"] + assert isinstance(log, dict) + syslog = log["syslog"] + assert isinstance(syslog, dict) + del syslog["hostname"] + _write_jsonl(parsed_dir / EVENTS_OUTPUT_FILENAME, [event]) + + with pytest.raises(SofElkParserError, match="_grokparsefailure"): + validate_source_parsed_output(manifest, parsed_dir) + + +def test_validate_source_parsed_output_keeps_cisco_generic_grok_failure_fatal( + tmp_path: Path, +) -> None: + manifest = _manifest( + tmp_path, + CISCO_ASA_SPEC, + Path("syslog/2026/fw-01/cisco_asa.log"), + "cisco_asa.log", + source_year=2026, + ) + parsed_dir = tmp_path / "parsed" + parsed_dir.mkdir() + event = _parsed_cisco_asa_event() + event["tags"] = ["filebeat", "process_archive", "_grokparsefailure"] + _write_jsonl(parsed_dir / EVENTS_OUTPUT_FILENAME, [event]) + + with pytest.raises(SofElkParserError, match="_grokparsefailure"): + validate_source_parsed_output(manifest, parsed_dir) + + def test_validate_source_parsed_output_reports_syslog_parser_context( tmp_path: Path, ) -> None: diff --git a/tests/unit/test_splunk_harness.py b/tests/unit/test_splunk_harness.py index 1627d46bc..2dcc2783a 100644 --- a/tests/unit/test_splunk_harness.py +++ b/tests/unit/test_splunk_harness.py @@ -504,11 +504,12 @@ def test_splunk_cim_dataset_failures_report_count_and_field_gaps() -> None: def test_splunk_search_result_rows_ignore_export_info_messages() -> None: rows = [ {"messages": [{"type": "INFO", "text": "No matching fields exist."}], "lastrow": True}, - {"result": {"component": "TailReader", "message": "real warning"}}, + {"preview": True, "result": {"component": "TailReader", "message": "partial warning"}}, + {"preview": False, "result": {"component": "TailReader", "message": "real warning"}}, ] assert _search_result_rows(rows) == [ - {"result": {"component": "TailReader", "message": "real warning"}} + {"preview": False, "result": {"component": "TailReader", "message": "real warning"}} ] diff --git a/tests/unit/test_sysmon_source_finalization.py b/tests/unit/test_sysmon_source_finalization.py index 38663fa41..46b454e48 100644 --- a/tests/unit/test_sysmon_source_finalization.py +++ b/tests/unit/test_sysmon_source_finalization.py @@ -442,7 +442,7 @@ def test_sysmon_terminal_seal_sorts_late_earlier_row_and_defers_public_output( ( OutputTarget.SOF_ELK, "windows_event_sysmon_snare.log", - "30182c0082491dcfe200b4e537f5da3ac8504a4230399959330422cad481c197", + "bae90967265a2ff9a94727ac2193dc6dc913931619b1e2d90c10c4b787957875", ), ], ) diff --git a/tests/unit/test_terminal_generator_admission.py b/tests/unit/test_terminal_generator_admission.py index 25e81cf75..be241c501 100644 --- a/tests/unit/test_terminal_generator_admission.py +++ b/tests/unit/test_terminal_generator_admission.py @@ -148,7 +148,7 @@ def _failed_logon_headroom( source_ip=source_ip, dc_system=dc_system, ) - local_logon = logon_type in (2, 5, 7, 11) or source_ip == system.ip + local_logon = logon_type in (2, 4, 5, 7, 11) normalized_source = "-" if local_logon else source_ip or system.ip return generator._failed_logon_completion_headroom( request=request, diff --git a/tests/unit/test_validation_routes.py b/tests/unit/test_validation_routes.py new file mode 100644 index 000000000..2add17bc8 --- /dev/null +++ b/tests/unit/test_validation_routes.py @@ -0,0 +1,334 @@ +"""Parser ownership and evaluator boundary regressions.""" + +import json +import logging +from pathlib import Path + +import pytest +from jinja2 import Environment +from typer.testing import CliRunner + +from evidenceforge.cli.commands import app +from evidenceforge.evaluation import validation_routes as routes +from evidenceforge.evaluation.engine import DIMENSION_SCORERS +from evidenceforge.evaluation.parsers import get_parser +from evidenceforge.evaluation.pillars.parseability import ParseabilityScorer +from evidenceforge.evaluation.pillars.plausibility import PlausibilityScorer +from evidenceforge.formats.loader import load_all_formats +from evidenceforge.generation.engine.emitter_setup import _build_emitter_classes +from evidenceforge.models.exceptions import ConfigurationError + +FIXTURES = Path(__file__).parents[1] / "fixtures" + + +def test_every_parser_schema_and_emitter_has_an_owner() -> None: + routes.validate_route_inventory() + native = {r.validator for r in routes.VALIDATION_ROUTES if r.kind == "native"} + assert native == set(load_all_formats()) == set(_build_emitter_classes()) + for definition in load_all_formats().values(): + for template in ( + definition.output.template, + definition.output.header_template, + definition.output.footer_template, + ): + if template is not None: + Environment().parse(template) + + +@pytest.mark.parametrize("mutation", ["missing", "duplicate", "stale", "artifact", "schema"]) +def test_broken_route_inventory_is_an_execution_error(monkeypatch, mutation: str) -> None: + entries = list(routes.VALIDATION_ROUTES) + if mutation == "missing": + entries.pop() + elif mutation == "duplicate": + entries.append(entries[0]) + elif mutation == "stale": + entries.append(routes.ValidationRoute(source="future", kind="native", validator="future")) + elif mutation == "artifact": + entries[-1] = entries[-1].model_copy(update={"validator": "missing"}) + else: + entries[0] = entries[0].model_copy(update={"validator": "missing"}) + monkeypatch.setattr(routes, "VALIDATION_ROUTES", tuple(entries)) + with pytest.raises(ConfigurationError): + routes.validate_route_inventory() + + +@pytest.mark.parametrize( + "payload", + [ + [], + None, + {"email": []}, + {"email": {"messages": {}}}, + {"email": {"messages": [42]}}, + {"email": {"messages": [{"date": "invalid"}]}}, + {"email": {"messages": [{"to": "not-a-list"}]}}, + ], +) +def test_malformed_email_artifacts_count_as_failures(tmp_path: Path, payload: object) -> None: + path = tmp_path / "ARTIFACTS_MANIFEST.json" + path.write_text(json.dumps(payload)) + records = list(get_parser("email_artifacts").parse_file(path)) + assert len(records) == 1 + schema, _ = ParseabilityScorer()._score_both({"email_artifacts": records}) + assert schema.score == 0 + assert schema.sample_findings + + +@pytest.mark.parametrize("payload", [{}, {"email": {}}, {"email": {"messages": []}}]) +def test_empty_artifact_sections_are_legitimate(tmp_path: Path, payload: dict) -> None: + path = tmp_path / "ARTIFACTS_MANIFEST.json" + path.write_text(json.dumps(payload)) + assert list(get_parser("email_artifacts").parse_file(path)) == [] + + +def test_sparse_email_metadata_and_extensions_remain_supported(tmp_path: Path) -> None: + path = tmp_path / "ARTIFACTS_MANIFEST.json" + path.write_text( + json.dumps({"email": {"messages": [{"message_id": "", "extension": 1}]}}) + ) + records = {"email_artifacts": list(get_parser("email_artifacts").parse_file(path))} + schema, constraints = ParseabilityScorer()._score_both(records) + assert schema.score == constraints.score == 100 + PlausibilityScorer()._score_co_occurrence(records) + + +@pytest.mark.parametrize("failure", [False, True]) +def test_json_cli_is_clean_across_repeated_calls(monkeypatch, failure: bool) -> None: + scorer = DIMENSION_SCORERS[0] + original = scorer.score + + def scoring(*args, **kwargs): + logging.getLogger("evidenceforge.routing_test").warning("routing-test-warning") + if failure: + raise RuntimeError("injected pillar failure") + return original(*args, **kwargs) + + monkeypatch.setattr(scorer, "score", scoring) + runner = CliRunner() + for verbose in (False, True): + args = [ + "eval", + str(FIXTURES / "eval/good"), + "--scenario", + str(FIXTURES / "scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ] + if verbose: + args.append("--verbose") + result = runner.invoke(app, args) + assert "routing-test-warning" in result.stderr + if failure: + assert result.exit_code == 22 + assert result.stdout == "" + assert "Pillar 1 (Parseability)" in result.stderr + if not verbose: + assert "Traceback" not in result.stderr + else: + assert result.exit_code == 0, result.stderr + report = json.loads(result.stdout) + assert len(report["pillars"]) == 4 + assert report["acceptance_passed"] is False + + +RECORD_CASES = sum( + ( + json.loads((FIXTURES / "record_validation" / name).read_text()) + for name in ("formats.json", "windows_variants.json") + ), + [], +) + + +@pytest.mark.parametrize("case", RECORD_CASES, ids=lambda c: c.get("variant", c["format"])) +def test_native_render_parse_validate_roundtrip(tmp_path: Path, case: dict) -> None: + from datetime import UTC, datetime + + from evidenceforge.formats.loader import load_format + + name = case["format"] + definition = load_format(name) + fields = dict(case["fields"]) + for key in ("timestamp", "TimeCreated", "ts"): + if isinstance(fields.get(key), str): + fields[key] = datetime.fromisoformat(fields[key].replace("Z", "+00:00")) + if name == "ecar": + fields["timestamp"] = fields.pop("timestamp_ms") / 1000 + if name in {"snort_alert", "proxy_access", "web_access", "bash_history"}: + if isinstance(fields.get("timestamp"), (int, float)): + fields["timestamp"] = datetime.fromtimestamp(fields["timestamp"], UTC) + if name == "proxy_access": + fields.update(method="GET", url="http://example/", protocol="HTTP/1.1", sc_bytes=1) + if name == "zeek_smb_files": + for key in ("size", "prev_name", "fuid"): + fields.setdefault(key, None) + if case.get("variant") == "process_creation": + fields.setdefault("TargetUserSid", "S-1-0-0") + path = tmp_path / (name + definition.output.file_extension) + emitter = _build_emitter_classes()[name](definition, path, threaded=False) + try: + raw = ( + emitter._prepare_event(fields)["rendered"] + if name == "bash_history" + else emitter._render_alert(fields) + if name == "snort_alert" + else emitter._render_event(fields) + ) + path.write_text(raw + "\n") + records = list(get_parser(name).parse_file(path)) + assert len(records) == 1 + schema, constraints = ParseabilityScorer()._score_both({name: records}) + assert schema.score == constraints.score == 100, (schema, constraints, raw) + finally: + emitter.close() + + +def test_mixed_native_email_bundle_retains_cross_source_checks() -> None: + from evidenceforge.evaluation.pillars.plausibility import _score_email_evidence_consistency + + root = FIXTURES / "record_validation/email" + records = { + name: list(get_parser(name).parse_file(root / filename)) + for name, filename in ( + ("email_artifacts", "ARTIFACTS_MANIFEST.json"), + ("zeek_smtp", "smtp.json"), + ("zeek_conn", "conn.json"), + ) + } + schema, constraints = ParseabilityScorer()._score_both(records) + assert schema.score == constraints.score == 100 + matched, agreeing, failures = _score_email_evidence_consistency(records) + assert matched == agreeing == 2 + assert failures == [] + records["email_artifacts"][0].fields["subject"] = "Conflicting subject" + matched, agreeing, failures = _score_email_evidence_consistency(records) + assert matched == 2 and agreeing == 1 + assert failures + + +def test_duplicate_parser_registration_is_rejected() -> None: + from evidenceforge.evaluation.parsers import LogParser, register_parser + + class DuplicateParser(LogParser): + format_name = "email_artifacts" + + with pytest.raises(ValueError, match="Duplicate parser"): + register_parser(DuplicateParser) + + +def test_missing_native_schema_cli_exits_22_without_report(monkeypatch) -> None: + def missing_schema(name: str): + raise ConfigurationError(f"Missing schema: {name}") + + monkeypatch.setattr(routes, "load_format", missing_schema) + result = CliRunner().invoke( + app, + [ + "eval", + str(FIXTURES / "eval/good"), + "--scenario", + str(FIXTURES / "scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ], + ) + assert result.exit_code == 22, result.stderr + assert result.stdout == "" + assert "Missing schema" in result.stderr + + +@pytest.mark.parametrize("message", [{"message_id": []}, {"to": 42}, {"date": "bad-date"}]) +def test_malformed_artifact_completes_failed_evaluation(tmp_path: Path, message: dict) -> None: + import shutil + + for source in (FIXTURES / "record_validation/email").iterdir(): + shutil.copyfile(source, tmp_path / source.name) + (tmp_path / "ARTIFACTS_MANIFEST.json").write_text( + json.dumps({"email": {"messages": [message]}}) + ) + result = CliRunner().invoke( + app, + [ + "eval", + str(tmp_path), + "--scenario", + str(FIXTURES / "scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ], + ) + assert result.exit_code == 0, result.stderr + report = json.loads(result.stdout) + assert report["source_counts"]["email_artifacts"] == 1 + assert report["acceptance_passed"] is False + assert all(p["score"] is not None for p in report["pillars"]) + spec = next(s for s in report["pillars"][0]["sub_scores"] if s["key"] == "spec_conformance") + assert spec["score"] < 100 + + +@pytest.mark.parametrize("owner", ["correctness", "diagnostic", "artifact"]) +def test_returned_execution_error_aborts_cli(monkeypatch, tmp_path: Path, owner: str) -> None: + import shutil + from types import SimpleNamespace + + from evidenceforge.formats.rules import Finding + + source = "email_artifacts" if owner == "artifact" else "zeek_conn" + finding = Finding( + rule_id="injected.rule", + format=source, + variant="test-variant", + fields=("field_a",), + category="evaluation", + outcome="evaluation_error", + message="injected execution error", + ) + output = FIXTURES / "eval/good" + if owner == "correctness": + monkeypatch.setattr( + "evidenceforge.evaluation.pillars.parseability.validate_event", + lambda *a, **kw: SimpleNamespace(findings=[finding]), + ) + elif owner == "diagnostic": + monkeypatch.setattr("evidenceforge.formats.rules.evaluate_rule", lambda *a, **kw: finding) + else: + for path in (FIXTURES / "record_validation/email").iterdir(): + shutil.copyfile(path, tmp_path / path.name) + output = tmp_path + monkeypatch.setitem(routes.ARTIFACT_VALIDATORS, "email_manifest", lambda record: [finding]) + result = CliRunner().invoke( + app, + [ + "eval", + str(output), + "--scenario", + str(FIXTURES / "scenarios/retail-store-ftp-attack.yaml"), + "--format", + "json", + ], + ) + assert result.exit_code == 22, result.stderr + assert result.stdout == "" + for detail in ("injected.rule", source, "test-variant", "field_a"): + assert detail in result.stderr + + +def test_validate_event_retains_returned_error_compatibility(monkeypatch) -> None: + from evidenceforge.formats.rules import Finding + from evidenceforge.formats.validator import validate_event + + failure = Finding( + rule_id="test.returned", + outcome="evaluation_error", + category="evaluation", + message="cannot execute", + fields=("orig_bytes",), + ) + monkeypatch.setattr("evidenceforge.formats.validator.evaluate_rule", lambda *a, **kw: failure) + result = validate_event(load_all_formats()["zeek_conn"], {}) + assert result.valid is False + assert any("test.returned" in message for message in result.errors) + assert failure.rule_id in { + f.rule_id for f in result.findings if f.outcome == "evaluation_error" + } diff --git a/tests/unit/test_validation_snapshot_compatibility.py b/tests/unit/test_validation_snapshot_compatibility.py new file mode 100644 index 000000000..ac972af22 --- /dev/null +++ b/tests/unit/test_validation_snapshot_compatibility.py @@ -0,0 +1,53 @@ +# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates +# SPDX-License-Identifier: MIT + +"""Only recognized immutable validation snapshots receive compatibility decoding.""" + +from copy import deepcopy +from pathlib import Path +from types import SimpleNamespace + +import pytest + +from evidenceforge.config import get_config_directory, provider +from evidenceforge.formats.snapshot_compatibility import decode_validation_snapshot +from evidenceforge.models.exceptions import ConfigurationError +from evidenceforge.utils.yaml_loader import load_yaml_text + +ROOT = Path(__file__).parents[1] / "fixtures/record_validation/legacy" + + +@pytest.mark.parametrize("name", ["windows_event_security", "zeek_conn", "thresholds"]) +def test_known_snapshot_decodes_without_mutating_input(monkeypatch, name: str) -> None: + group = "evaluation" if name == "thresholds" else "formats" + path = get_config_directory() / group / f"{name}.yaml" + legacy = load_yaml_text((ROOT / path.name).read_text()) + original = deepcopy(legacy) + runtime = load_yaml_text(path.read_text()) + effective = SimpleNamespace( + ambient_overlay_compat=False, packaged_defaults={f"{group}/{name}.yaml": legacy} + ) + monkeypatch.setattr(provider, "current_effective_config", lambda: effective) + assert decode_validation_snapshot(path, legacy) == runtime + assert legacy == original + if name != "thresholds": + assert runtime["output"] == legacy["output"] + changed = deepcopy(legacy) + changed["unexpected"] = True + assert decode_validation_snapshot(path, changed) is changed + monkeypatch.setattr(provider, "current_effective_config", lambda: None) + assert decode_validation_snapshot(path, legacy) is legacy + assert decode_validation_snapshot(path, runtime) is runtime + + +def test_decoder_refuses_changed_rendering(monkeypatch) -> None: + import evidenceforge.formats.snapshot_compatibility as decoder + + path = get_config_directory() / "formats/zeek_conn.yaml" + legacy = load_yaml_text((ROOT / path.name).read_text()) + monkeypatch.setattr(decoder, "packaged_default_document", lambda path: (True, legacy)) + runtime = deepcopy(legacy) + runtime["output"]["template"] += "changed" + monkeypatch.setattr(decoder, "load_yaml_text", lambda *args, **kwargs: runtime) + with pytest.raises(ConfigurationError, match="rendering-compatible"): + decoder.decode_validation_snapshot(path, legacy) diff --git a/tests/unit/test_windows_snare_sidecar.py b/tests/unit/test_windows_snare_sidecar.py index ed0597fb3..3f29b8cf1 100644 --- a/tests/unit/test_windows_snare_sidecar.py +++ b/tests/unit/test_windows_snare_sidecar.py @@ -46,7 +46,7 @@ def test_windows_security_snare_renderer_uses_payload_marker_without_syslog_app_ ) assert "\t4624\tMicrosoft-Windows-Security-Auditing\talice\t" in rendered assert "An account was successfully logged on.: " in rendered - assert "Security ID: S-1-5-18" in rendered + assert "SubjectUserSid: S-1-5-18" in rendered assert "Account Name: alice" in rendered diff --git a/tests/unit/test_windows_source_finalization.py b/tests/unit/test_windows_source_finalization.py index 436d645d4..df56bed3c 100644 --- a/tests/unit/test_windows_source_finalization.py +++ b/tests/unit/test_windows_source_finalization.py @@ -1352,7 +1352,7 @@ def test_windows_terminal_seal_sorts_late_earlier_row_and_uses_exact_writer( ( OutputTarget.SOF_ELK, "windows_event_security_snare.log", - "d6cdf8ebc88d3c170841f7cd3d0e0b35f8f336105ff34e6262172e90e1ef9124", + "d0950e06a328011984feb6abf766ee96618f8532104e890790eb1163ba813ff8", ), ], ) diff --git a/uv.lock b/uv.lock index 79d7ec202..d2d298a18 100644 --- a/uv.lock +++ b/uv.lock @@ -277,13 +277,12 @@ wheels = [ [[package]] name = "evidence-forge" -version = "2.1.0" +version = "2.1.1" source = { editable = "." } dependencies = [ { name = "click" }, { name = "cryptography" }, { name = "jinja2" }, - { name = "json-logic-qubit" }, { name = "psutil" }, { name = "pydantic" }, { name = "python-dotenv" }, @@ -310,7 +309,6 @@ requires-dist = [ { name = "click", specifier = ">=8.4.2" }, { name = "cryptography", specifier = ">=50.0.0" }, { name = "jinja2", specifier = ">=3.1.0" }, - { name = "json-logic-qubit", specifier = ">=0.9.1" }, { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=4.6.1" }, { name = "psutil", specifier = ">=7.0.0" }, { name = "pydantic", specifier = ">=2.13.4" }, @@ -368,17 +366,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] -[[package]] -name = "json-logic-qubit" -version = "0.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/62/2b023e1dcc6917d40a9f5687916d1c647e26af06c579f200bd0f3b91481a/json_logic_qubit-0.9.1-py2.py3-none-any.whl", hash = "sha256:d024ff0c77659eb97ddf742e0bd1b7caacd44bc53fdfc8f3977f4062a3c3b056", size = 13196, upload-time = "2018-08-15T14:41:05.867Z" }, -] - [[package]] name = "markdown-it-py" version = "4.0.0" @@ -852,15 +839,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, ] -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - [[package]] name = "typer" version = "0.27.2"