Repository navigation
bug(ocsf): schema downgrade labels events 1.1 or 1.3 that do not conform to those versions #4284
Description
User Story
I use OpenShell with Splunk as the OCSF sink and set ocsf_schema_version so that older SIEM integrations accept the events. I need events labelled 1.1 or 1.3 to actually conform to those schemas, so that the SIEM's data models and any audit relying on them are correct.
Problem Statement
downgrade_event() (crates/openshell-ocsf/src/format/downgrade.rs) strips a few profile-gated fields and rewrites metadata.version, but never checks the target version's requirements. OCSF 1.8 relaxed several requirements that 1.1 and 1.3 enforce, and OpenShell's emitters rely on that relaxation:
| Requirement | 1.1 | 1.3 | 1.8 | OpenShell today |
|---|---|---|---|---|
HTTP Activity http_request and http_response |
both required | both required | at least one | allow decisions are logged with a request only |
src_endpoint (Network, HTTP, SSH) |
required | recommended | at least one endpoint | can be absent |
dst_endpoint (Network, HTTP, SSH) |
required | required | at least one endpoint | can be absent |
action_id with security_control profile |
required | required | recommended | can be absent |
is_src_dst_assignment_known |
undefined | undefined | defined on Network Activity | emitted |
The result is events labelled 1.1 or 1.3 that the official validator rejects. The setting applies to the supervisor JSONL (ocsf_schema_version, released in v0.1.0) and the gateway JSONL ([openshell.gateway.ocsf_log] schema_version, on main). docs/observability/ocsf-json-export.mdx states the core structure is identical across 1.1 to 1.8 and lists AWS Security Lake as supported.
Impact / Why This Matters
Lenient sinks such as Splunk accept the events, so operators believe they hold conformant audit logs when they do not. Strict sinks that validate against 1.1 can reject them, and the operator sees this only in the sink's ingestion errors. Leaving the setting unset is not a workaround for sinks that only accept older versions.
Proposed Design
- An event OpenShell labels with an older version must validate against that version. Never insert placeholder data to satisfy a requirement.
- Events that can be converted are downgraded as today, also removing attributes the target does not define.
- Events that cannot be converted are written unchanged at native 1.8, counted, and reported once per event class with the missing attribute.
- Where the missing data genuinely exists, emitters include it: the generated response on deny paths, the workload peer as
src_endpoint. - The docs list which event types convert to each target version.
Suggested UX (if applicable)
No configuration change. A warning when an event stays at native 1.8:
WARN ocsf downgrade: HTTP Activity kept at 1.8.0 for target 1.1.0 (missing http_response); further occurrences counted in openshell_ocsf_downgrade_kept_native_total
Acceptance Criteria
- Every event labelled 1.1.0 or 1.3.0 passes
POST https://schema.ocsf.io/api/<version>/validate. - Events that cannot be converted keep
metadata.version1.8.0 and nodowngraded_frommarker. - A metric counts events kept at native 1.8, by class and target version, on both supervisor and gateway outputs.
- Deny-path HTTP events carry
http_response, and L7 events carrysrc_endpointwhen the peer is known. - Regression tests validate downgraded events against vendored 1.1.0 and 1.3.0 schemas.
-
ocsf-json-export.mdxno longer claims structural identity and documents the per-class conversion table.
Alternatives Considered
- Remove the downgrade and move version mapping to the exporter proposed in feat(observability): define gateway-to-exporter extension contract #3224. Long term this is the likely home, but the exporter does not exist yet and users on older sinks need correct output now. This fix keeps the contract honest until then.
- Fill missing required fields with placeholders. Rejected: it produces fake audit data.
- Drop non-convertible events. Rejected as the default: it silently loses security records.
Agent Investigation
Verified against the OCSF schema tags v1.1.0, v1.3.0 and v1.8.0 and the official validator API. Related: #2717, #3264, #3554, #2640 (adds the trace object, which also needs removing for 1.3 and below), #3224. Depends on #4283, since even complete events currently fail on device.os.type_id.
Activity
fix(ocsf): emit schema-conformant OCSF events and honest downgrades
fix(ocsf): emit schema-conformant OCSF events and honest downgrades
fix(ocsf): emit schema-conformant OCSF events and honest downgrades
fix(ocsf): emit schema-conformant OCSF events and honest downgrades
fix(ocsf): emit schema-conformant OCSF events and honest downgrades
fix(ocsf): emit schema-conformant OCSF events and honest downgrades
zanetworker commentedon Oct 17, 2026
@krishicks OCSF 1.8 SIEM spike results: https://gist.github.com/zanetworker/dd3bf999d1f18e6557fa5b95bf87712d
Tested ten sinks and pipelines with 189 real OpenShell records: native 1.8.0, plus main's 1.1 and 1.3 downgrade output. Elastic, Splunk, nano's validator, Tenzir and Cribl ran live in local containers. The cloud services (Security Lake, Google SecOps, Cortex XSIAM, Sentinel, Datadog) were not run live; their verdicts come from published parser code, mapping tables and docs.
metadata.version. They route onclass_uidorclass_name. That includes Security Lake and Google SecOps, which are documented as older-only: Security Lake's "1.3 and earlier" is a note next to a client-side validator that accepts only 1.1.0 and rc.2.container, which the XSIAM pack uses for sandbox identity. The downgraded records also still carry a few fields that 1.1.0 doesn't define.container(nano's strict validator rejects every native record on it), and which classes each SIEM maps (SSH, Config State Change and Base Event are often unmapped).Recommendation: keep emitting 1.8.0, remove the downgrade (this issue), and fix
container(#4283) together with the XSIAM pack author.