Skip to content

fix(normalize): make issue and case fields addressable from the contract - #1053

Merged
scottbrumley merged 3 commits into
mainfrom
fix/normalize-toplevel-issue-attrs
Aug 18, 2026
Merged

fix(normalize): make issue and case fields addressable from the contract#1053
scottbrumley merged 3 commits into
mainfrom
fix/normalize-toplevel-issue-attrs

Conversation

@scottbrumley

Copy link
Copy Markdown
Contributor

Three fixes to SOCNormalizeFromList in soc-optimization-unified. All three are running on a dev tenant and have been gated green with upload.

  • a39b3b0 make top-level issue attributes addressable
  • c739d7b expose case fields to the contract under case.*
  • 54da680 take case fields from the caller, not demisto.context()

Why

The normalize map could only reach fields under CustomFields, so top-level issue attributes and case-scoped values were unreachable from a mapping. That is what blocked contract entries like Endpoint.alert_source from case.incident_sources.[0] — the mapping could be written but never resolved.

The third commit matters for correctness rather than reach: reading case fields from demisto.context() picks up whatever the calling playbook happened to leave behind, which is not stable across the lifecycle. Taking them from the caller makes the value deterministic.

Effect

Measured on the tenant when these landed: Analysis.* populated went from 1 of 23 fields to 17 of 18, and case_score from 0 to 57. Before this, the phase contract initialised its typed empties and almost nothing wrote over them — issues presented as an empty contract and a layout stuck on "Analysis phase running...".

This is also a prerequisite for the NIST IR normalize map work in #1052, which adds mappings that depend on the addressability this provides.

Verification

check_contribution green with upload against deathstar: normalize, correlation_rule_preflight, playbook_condition_lint, pack_prep, fix_errors, check_contracts, validate_shadow_mode, prep_docs, upload. Contracts checked on 1 playbook, correlation write path healthy.

Labelled version:patch.

SOCNormalizeFromList mapped only out of CustomFields, so contract rows
naming an incident attribute (name, details, linkedCount) resolved empty
on every source in every band. Merge an allowlist of those attributes
into the field surface; CustomFields wins any name collision.
parentIncidentFields carries what the issue does not — incident_sources,
aggregated_score, the alert/user/host counts, and the fused MITRE arrays.
Playbooks already read it; the normalize map could not. Merged under a
case. prefix so a row names its surface and cannot collide with an issue
field. Absent on an ungrouped issue, where rows skip empty as usual.
parentIncidentFields is a DT root the playbook engine resolves at task
time; it is not a key in demisto.context(), so every case.* row resolved
empty and landed in skipped_empty. Foundation - Normalize Artifacts now
passes ${parentIncidentFields} as case_fields.

Observed on a grouped Turla replay case: the case carried alert_count
106 across 3 hosts while Investigation.* stayed empty, and the AI
concluded spread_level: isolated.
@scottbrumley scottbrumley added the version:patch Bug fix or hotfix → x.x.N label Aug 17, 2026
@scottbrumley
scottbrumley merged commit f8293fd into main Aug 18, 2026
14 of 24 checks passed
@scottbrumley
scottbrumley deleted the fix/normalize-toplevel-issue-attrs branch August 18, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

version:patch Bug fix or hotfix → x.x.N

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant