Security Data Works

Standards proposal

OCSF and operational technology: the ICS field-extensions proposal.

OCSF has no native fields for the industrial control protocols organizations actually run on the floor, so Modbus, DNP3, BACnet, and S7comm all sit outside the schema. A power grid SOC normalizing telemetry to OCSF today either drops the protocol-specific detail or stuffs it into raw_data, which puts ICS-aware detection permanently downstream of the normalization step. I filed a proposal to add six fields under an ics. namespace, anchored on Zeek-to-OCSF mapping work that already validated against production Modbus, DNP3, and S7comm traffic, and the rest of this essay walks through why I think the change should land.

Reading time: about 12 minutes. Evidence tier: A for the protocol specifications and standards (IEC 62443, NIST SP 800-82 Rev. 3), B for the production-validation numbers from the Zeek-to-OCSF mapping project, C for the threat-actor attribution where attribution is itself contested. The proposal is OCSF Issue #1515, OPEN as of this writing and pending community review. Nothing here describes a merged schema change; what it describes is the architectural argument for why the change should land.

The gap

What OCSF doesn't represent today.

The Network Activity class in current OCSF carries the IT-network primitives an analyst expects: source and destination endpoints, ports, protocol numbers, byte counts, service names. None of those carry the information an ICS analyst needs to investigate Modbus, DNP3, or BACnet traffic. The function code embedded in a Modbus PDU isn't a port; it's a one-byte value that distinguishes a read-coils request from a write-multiple-registers command. Whether a DNP3 frame is a request, a response, or an unsolicited response isn't a TCP flag; it's an application-layer attribute that anomaly detection depends on. The object type a BACnet frame addresses isn't a hostname; it's a controller-specific identifier that says whether you're touching an analog input or a binary output.

Today an OCSF-normalized ICS pipeline either drops these attributes at the transformation step or smuggles them through in unstructured fields. Both options break detection portability. A Sigma rule looking for "any write to a holding register on a safety PLC" can't be expressed against OCSF, because the OCSF event doesn't carry "holding register" anywhere a portable query language can name. The analyst who wants the rule has to write it against the original Zeek conn.log or the original PLC log in vendor format, which puts ICS-aware detection logic permanently on the wrong side of the normalization layer, so whatever the OCSF investment bought at the IT layer never reaches the OT layer.

The gap is structural rather than a missing parser, because the protocol parsers already exist in Zeek and in commercial ICS-aware sensors, so what's actually missing is the schema-level shape that lets the parsed information cross the normalization boundary intact. The Issue #1515 proposal exists because the parsers are ready and the schema is the thing holding the architecture back.

The six fields

What the proposal adds.

Six fields, grouped under an ics. namespace to keep them clearly scoped and avoid collisions with adjacent domains. All optional, all additive; existing OCSF deployments are unaffected if they choose not to emit them.

Field Type What it carries
ics.function_code integer Modbus / DNP3 / S7comm function code. e.g. 3 = Read Holding Registers, 16 = Write Multiple Registers.
ics.pdu_type string BACnet / DNP3 PDU type. "request", "response", "unsolicited_response".
ics.pdu_service string BACnet / S7comm service requested. "read_property", "write_property", "upload", "download".
ics.unit_id integer Modbus / DNP3 slave device identifier (1–255).
ics.register_address integer Modbus register or coil address. 30001 for input registers, 40001 for holding registers.
ics.object_type string BACnet / DNP3 object type. "analog_input", "binary_output", "device".

Six is a deliberate floor rather than a ceiling, and the proposal lists open community questions about whether additional fields (exception codes, data values, quality flags) belong in the same namespace, and whether the ICS coverage should sit as an extension to the existing Network Activity class or warrant a dedicated event class. Those are good questions, and I'd rather see them resolved with community input than baked in by a single contributor.

The shape the namespace produces in practice looks like this:

{
  "class_uid": 4001,
  "time": "2026-05-27T14:30:00Z",
  "src_endpoint": { "ip": "10.4.2.17" },
  "dst_endpoint": { "ip": "10.4.2.42", "port": 502 },
  "connection_info": { "protocol_name": "modbus" },
  "ics": {
    "function_code": 16,
    "unit_id": 3,
    "register_address": 40001,
    "pdu_type": "request"
  }
}

What detection looks like with the fields in place

Four use cases the fields unlock.

Anomaly detection on function-code distributions

The most common ICS detection pattern is baseline-and-deviate on function-code mix. Modbus traffic on a working manufacturing line is dominated by read operations: function codes 1 (Read Coils), 3 (Read Holding Registers), 4 (Read Input Registers). Writes happen, but the ratio is stable, and the writes that happen are scheduled and addressed to a small set of known registers. An unexpected spike in function code 16 (Write Multiple Registers) addressed to unfamiliar register ranges is the shape of the early stages of an attack against the control logic. Without ics.function_code in the normalized event, that detection can't be made portable across SIEMs or tested with a Sigma rule or evaluated in a cross-engine query, whereas with the field in place the rule comes down to a three-line aggregation.

Unsolicited responses on BACnet and DNP3

Both BACnet and DNP3 support unsolicited responses, where a controller pushes information without having been polled, and the protocol mechanism is legitimate, so in most environments the traffic shape is predictable across HVAC controllers, smart meters, and RTUs. What's not predictable is unsolicited responses arriving from devices that have never sent them before, or arriving in patterns that don't match the normal cadence, and ics.pdu_type = "unsolicited_response" is the field that lets a detection author write "alert me on unsolicited responses from any device not in the configured whitelist." The rule is one line of SQL, and it's the same line of SQL whether the underlying engine is ClickHouse, Trino, or a SIEM, which is exactly the portability OCSF is supposed to provide and currently doesn't.

NERC CIP and IEC 62443 audit posture

The compliance frameworks for energy and industrial automation (NERC CIP for North American bulk electric, IEC 62443 for industrial automation broadly) expect the operator to log control-system access in a way that lets an auditor verify which functions were invoked against which devices. The field shape the auditor wants is what's in the proposal: who connected, what function code they called, which unit and register were addressed, whether the call was a read or a write. The normalized-OCSF version of that audit trail is straightforward once the fields exist; today it requires the auditor to read original vendor logs alongside the OCSF tables, which is the exact friction the compliance framing was supposed to remove.

Threat hunting against TRITON-style and CRASHOVERRIDE-style TTPs

The publicly documented OT-targeted intrusions of the last decade (TRITON against the Schneider Triconex safety system, CRASHOVERRIDE against the Ukrainian grid, STUXNET against Iranian centrifuges) all share a structural property: the attacker eventually issued writes against control points that should have been read-only from the network. A hunt for "writes against the safety-system address range from any host that isn't the engineering workstation" is a one-page query if the data carries ics.function_code and ics.register_address. The hunt isn't theoretical, because publicly available threat intelligence already describes the field-shape sequences that should trigger it, so the bottleneck has been a normalized schema that carries the fields rather than the detection idea itself.

Reference implementation

The fields aren't theoretical. The mapping ships.

Standards proposals fail when they land without a working reference implementation, because reviewers have no way to evaluate whether the proposed shape survives contact with real protocol traffic. The ICS field-extensions proposal is paired with the Zeek-to-OCSF mapping project, which already implements the mapping for Modbus at 99.7% field coverage (35 of 35 mapped, with one nullable outlier that doesn't always appear in capture), for DNP3 against production traffic from an operator that ran a pilot, and for S7comm against Siemens PLC test traffic.

That coverage is what lets the proposal be specific about field names, types, and example values rather than abstract about the namespace. The reverse mapping path that the companion essay on legal-team objections describes also works for ICS protocols on top of these fields: an OCSF-stored Modbus event can be reverse-mapped back to native Modbus shape for incident-response tooling, because the function code, unit ID, and register address travel through the normalization step intact.

The downside of pairing the proposal with a specific implementation is that the implementation is Zeek-centric. Operators running ICS-aware sensors from other vendors (Claroty, Nozomi, Dragos) would need parallel work to emit OCSF in the proposed shape. That isn't a blocker for the schema change; the schema can be ratified without every vendor having shipped emitters yet. But it's an honest caveat: the community-wide rollout depends on adoption beyond the one Zeek-based reference.

Regulatory framing

How the fields intersect IEC 62443 and NIST SP 800-82.

IEC 62443 is the international standards series for industrial automation and control-system security. Part 3-3 specifies system security requirements; Part 4-2 covers component requirements. The audit posture both parts assume is that the operator can produce an event-level record of network access to control devices, with enough detail to demonstrate that unauthorized writes can be detected and investigated. The proposed OCSF fields are the schema shape that makes that posture portable across SIEMs and lakehouses; without them, the operator has to anchor compliance on vendor-specific log formats that the next SIEM migration may break.

NIST SP 800-82 Rev. 3 (Guide to Operational Technology Security, published 2023) makes a similar recommendation in less prescriptive language. The guidance asks for "comprehensive logging of control system communications including command and control messages, configuration changes, and unauthorized access attempts." Comprehensive in this context means the function code is preserved, the unit identifier is preserved, and the addressed register is preserved, which is the same set the proposal adds.

I want to be honest about the standards work. Neither IEC 62443 nor NIST SP 800-82 explicitly requires OCSF; both predate it. What they require is that the operator can produce the audit trail. The argument for the OCSF extension isn't that the standards mandate it; it's that the standards mandate a property (auditability of control-system access) which is materially easier to achieve when the normalization layer carries the protocol-specific fields rather than dropping them.

Open community questions

What the proposal leaves on the table.

Five questions the issue explicitly defers to community discussion, where I have a view but don't want to bake one in without input.

Dedicated ICS event class versus Network Activity extension. The proposal currently extends Network Activity. The alternative is a new event class for industrial control communications. Dedicated class is cleaner; extension lowers the implementation barrier for vendors who already emit Network Activity events. My current preference is extension first, dedicated class later if the traffic patterns justify it. The OCSF working group's view is what should settle this.

Exception codes, data values, quality flags. The six proposed fields cover the identification layer. They don't cover the values being read or written (which often matter for detection) or the protocol-level error responses (which often indicate reconnaissance). Adding those is non-trivial because data values are protocol- and device-specific. The right path may be a generic ics.data field with type guidance per protocol, rather than per-protocol value fields.

Vendor-specific fields. Siemens S7, Rockwell EtherNet/IP, Schneider Modicon all carry vendor-specific extensions to the standard protocols. The question is whether OCSF should model those natively, or whether they belong in a separate vendor-extensions namespace. My instinct is the latter, because OCSF's value is portability and per-vendor fields erode portability. But the operators with big single-vendor estates have legitimate reasons to want native support.

Namespace organization. Flat (ics_function_code) versus nested (ics.function_code). I picked nested for the proposal because the existing OCSF namespaces (src_endpoint, dst_endpoint, connection_info) are nested, and consistency seems worth more than the marginal query convenience of flat names.

ICS security event types. Separate from the field additions, OCSF could add named event types for "unauthorized write," "safety system access," "firmware upload." Those are the analyst-facing labels that bridge field shape to detection intent. My current view is that event types are downstream of fields: get the fields in, let the community write Sigma rules that produce the event types, formalize once the rule library is mature enough to suggest the right shapes.

What this changes for IT/OT convergence

The architecture reason this proposal matters.

The IT/OT convergence story has been told the same way for a decade. The IT-side investments (centralized SOC, SIEM, normalized telemetry, detection-as-code) extend to cover the OT-side estate. What's broken about that story in practice is that the IT-side normalization layer doesn't carry OT protocol detail, so the OT events that land in the SOC are either lossy or trapped in vendor-specific shapes that don't query alongside IT events, which leaves SOC analysts maintaining two separate mental models for two separate event languages. The convergence is real on the network and at the procurement layer, but because the detection vocabulary stays split, it hasn't arrived at the layer where analysts actually write rules.

Adding the six fields in Issue #1515 doesn't close that gap by itself. It closes a specific subset of it: the SOC analyst can write a single Sigma rule that joins an OT alert (Modbus write to a safety register) with an IT alert (anomalous SSH from the same source endpoint that issued the write) in a single query against a single normalized table. That join is the part the current OCSF schema can't express. Once it can, the practical IT/OT convergence story gets meaningfully better, because the detection vocabulary is shared.

That's the framing I'd use with an executive sponsor asking why an OCSF schema change matters, because the six fields are less six entries in a spec than a schema-level commitment that the OT side counts as a first-class citizen of the normalized telemetry plane instead of an afterthought routed around the OCSF layer.

Status and next steps

Where the proposal sits, and what would help.

OCSF Issue #1515 is OPEN as of this writing. The PR with concrete schema changes is ready to submit; the proposal text invites community feedback on the five open questions before that PR lands. The Modbus reference implementation in the Zeek-to-OCSF mapping repo is publicly available for reviewers who want to see how the fields populate against real traffic. DNP3 and S7comm reference traces are available under NDA for operator review.

The most useful community contribution at this stage is operator validation. If you run an OT estate that emits Modbus, DNP3, BACnet, or S7comm, and you've built detection logic against vendor-specific log shapes today, the question I'd want answered is whether the six proposed fields are sufficient to express your existing rules, because the places where they fall short are the right input for refining the field set before the PR lands, and I'd rather the proposal stay narrow and correct than grow broad and approximate.

For the broader IT/OT convergence argument that motivates the work, the thesis page carries the architecture-level case. For the legal and forensic implications of OCSF normalization that the companion reverse-mapping essay covers, the same chain-of-custody framework applies to ICS data with one extension: the protocol-specific fields here are part of the evidence record, and the reverse-mapping documentation needs to cover them too.