Skip to navigation

OCSF JSON Export

View as Markdown

The shorthand log format is optimized for humans and agents reading logs in real time. For machine consumption or SIEM integration, enable OCSF JSON output: one native JSON object per record. Collection is best-effort, not a guarantee of complete audit history.

Gateway Output

Configure [openshell.gateway.ocsf_log] in gateway.toml to collect gateway-origin OCSF events into one JSONL file. This includes gateway-wide events such as TLS certificate reloads, even when no sandbox log stream applies. Collection preserves native OCSF fields and event IDs and does not depend on RUST_LOG.

The gateway writes OCSF events to a local JSONL file. Give each replica its own path and configure the shipper to follow renamed rotation segments. See OCSF JSONL configuration for queue bounds, retention, loss metrics, and best-effort delivery limits.

This output is separate from the supervisor stderr and file output described below. Enabling one does not enable the other. The gateway JSONL sink does not archive supervisor log lines pushed to the gateway; those lines carry OCSF shorthand text, not the full structured record.

Gateway records use the configured gateway name for both device.uid and device.name. Replicas of one installation share that identity; device.hostname identifies the emitting replica. Assign distinct gateway names to installations whose events are collected together. Reusing a name, including the default name, groups those installations under the same identity. Renaming a gateway changes its audit identity.

Without JSONL enabled, gateway OCSF events still appear as shorthand in console output, subject to the diagnostic log filter. Events associated with a sandbox also appear in its gateway log stream; gateway-wide events have no sandbox association.

Enable Sandbox JSON Export

Use the ocsf_json_enabled setting to toggle JSON export. The setting can be applied globally, for all sandboxes, or per-sandbox.

Global:

openshell settings set --global --key ocsf_json_enabled --value true

Per-sandbox:

openshell settings set my-sandbox --key ocsf_json_enabled --value true

The setting takes effect on the next poll cycle, by default every 10 seconds. No sandbox restart is required.

To disable:

openshell settings set --global --key ocsf_json_enabled --value false

Windows MXC gateways

MXC audit events originate in the Windows gateway rather than an in-sandbox supervisor. Enable the MXC ETW consumer in gateway.toml, then explicitly opt the gateway into durable JSONL output:

[openshell.drivers.mxc]
etw_audit = true
$env:OPENSHELL_OCSF_JSON = "1"
# Optional; defaults to %PROGRAMDATA%\OpenShell\logs.
$env:OPENSHELL_OCSF_LOG_DIR = "D:\OpenShell\audit"
openshell-gateway --drivers mxc --config gateway.toml

The sink is available only when Windows selects the MXC driver. It rotates daily and retains the three most recent files. Diagnostic --log-level values do not suppress records in this explicitly enabled audit sink.

Output Location

When ocsf_json_enabled=true, sandbox supervisors emit full OCSF JSON to stderr alongside shorthand output:

2026-10-07T23:21:19.000Z OCSF NET:OPEN [MED] DENIED ...
2026-10-07T23:21:19.000Z OCSF-JSON {"class_uid":4001,...}

The example payload is abbreviated. Each actual OCSF-JSON line contains one complete compact JSON object. Configure your collector to match the OCSF-JSON token after the UTC timestamp and decode everything after the following space as JSON. Select these lines to avoid ingesting the shorthand copy of each event. The JSON preserves the original metadata.uid and follows ocsf_schema_version; with that setting unset, it uses the full native schema.

Collect stderr through the supervisor’s platform log interface:

docker logs --follow <supervisor-container>
podman logs --follow <supervisor-container>
kubectl -n <sandbox-namespace> logs <supervisor-pod> -c supervisor --follow

JSON stderr output works independently of writable log storage and the diagnostic log filter. Disabling the setting stops new JSON records. The console writer uses a bounded queue of 1,024 complete lines shared by diagnostics, shorthand, and JSON; when the queue is full, new lines are dropped rather than blocking enforcement. Delivery is best-effort, and retention depends on your runtime and external collector. The gateway log API and openshell logs continue to return shorthand.

When file logging is available, supervisors also write plain JSONL to /var/log/openshell-ocsf.YYYY-MM-DD.log in their own filesystem, separate from the workload. openshell sandbox exec cannot read those files. File output requires a writable /var/log; a missing file sink does not disable JSON stderr output.

This file contains supervisor-originated events, not the sandbox-runtime events emitted into workload container logs.

Supervisor files rotate daily with a configured three-file limit, but cleanup can remove JSONL history earlier. See supervisor file retention for the limits. Docker and Podman store them on tmpfs; Kubernetes stores them in the supervisor pod’s emptyDir. For durable retention, arrange external collection before rotation or teardown. See supervisor file access for collection paths and best-effort limits.

Windows MXC gateway records use %PROGRAMDATA%\OpenShell\logs or OPENSHELL_OCSF_LOG_DIR. That sink also rotates daily and retains the three most recent files. The separate [openshell.gateway.ocsf_log] sink uses its configured path and retention.

JSON Record Structure

Gateway-produced records use the OpenShell Gateway product identity; supervisor records use OpenShell Sandbox Supervisor. The producing device and the affected sandbox are separate identities, so a gateway event can still identify an affected sandbox through its container fields.

For gateway-produced records, device.os.name identifies the OS running the gateway process: Linux, Windows, or macOS. Linux supervisor records continue to report Linux, regardless of the gateway’s OS. A native macOS gateway therefore reports macOS while its Linux sandboxes report Linux; a gateway running inside a Linux container reports Linux, even on a Mac host.

metadata.uid uniquely identifies an event and stays unchanged when that record is serialized again. Use container.uid to associate the event with its sandbox, not metadata.uid. Records without a sandbox association omit the container; unknown images are omitted rather than represented by an empty image name.

Each JSONL file line, or the payload after the stderr marker, is a complete OCSF v1.8.0 JSON object when no downgrade is configured. Here is an example of a network connection event:

{
"class_uid": 4001,
"class_name": "Network Activity",
"category_uid": 4,
"category_name": "Network Activity",
"activity_id": 1,
"activity_name": "Open",
"severity_id": 1,
"severity": "Informational",
"status_id": 1,
"status": "Success",
"time": 1775014138811,
"message": "CONNECT allowed api.github.com:443",
"metadata": {
"product": {
"name": "OpenShell Sandbox Supervisor",
"vendor_name": "NVIDIA",
"version": "0.3.0"
},
"version": "1.8.0"
},
"action_id": 1,
"action": "Allowed",
"disposition_id": 1,
"disposition": "Allowed",
"dst_endpoint": {
"domain": "api.github.com",
"port": 443
},
"src_endpoint": {
"ip": "10.42.0.31",
"port": 37494
},
"actor": {
"process": {
"name": "/usr/bin/curl",
"pid": 57
}
},
"firewall_rule": {
"name": "github_api",
"type": "opa"
}
}

And a denied connection:

{
"class_uid": 4001,
"class_name": "Network Activity",
"activity_id": 1,
"activity_name": "Open",
"severity_id": 3,
"severity": "Medium",
"status_id": 2,
"status": "Failure",
"action_id": 2,
"action": "Denied",
"disposition_id": 2,
"disposition": "Blocked",
"status_detail": "no matching policy",
"message": "CONNECT denied httpbin.org:443",
"dst_endpoint": {
"domain": "httpbin.org",
"port": 443
},
"actor": {
"process": {
"name": "/usr/bin/curl",
"pid": 63
}
},
"firewall_rule": {
"name": "-",
"type": "opa"
}
}

The JSON examples above are formatted for readability. The actual JSONL file contains one JSON object per line with no whitespace formatting.

OCSF Event Classes in JSON

The class_uid field identifies the event type:

class_uidClassShorthand prefix
0Base EventEVENT
4001Network ActivityNET:
4002HTTP ActivityHTTP:
4007SSH ActivitySSH:
1007Process ActivityPROC:
2004Detection FindingFINDING:
5019Device Config State ChangeCONFIG:
6002Application LifecycleLIFECYCLE:

HTTP Activity records include request or response details. Rejections that have parsed a request, including early credential-binding failures, include safe method-only request context and the generated response.

Connection-error records include the known peer or listening endpoint.

Policy configuration warnings use Device Config State Change.

Unix socket relay and relay-control notifications, and proxy or mediation failures without an observed network endpoint, use Base Event (class_uid: 0). Include these classes when filtering supervisor operational events. Relay-control records that previously appeared as NET:* now appear as EVENT.

SIEM Schema Version Compatibility

OpenShell emits OCSF v1.8.0 events internally, but many SIEMs only support older schema versions. The ocsf_schema_version setting tells the JSONL layer to downgrade events before writing, stripping fields and profiles that don’t exist in the target version.

For gateway JSONL, set schema_version on the output destination. The target applies uniformly to every record written to that file and requires a gateway restart:

[openshell.gateway.ocsf_log]
path = "/var/log/openshell/gateway-ocsf.jsonl"
schema_version = "1.3"

The sandbox-scoped setting below controls the legacy supervisor-local JSONL file only.

Set the target version globally:

openshell settings set --global --key ocsf_schema_version --value "1.1"

Or per-sandbox:

openshell settings set my-sandbox --key ocsf_schema_version --value "1.3"

The setting takes effect on the next poll cycle, by default every 10 seconds. No sandbox restart is required.

Supported target versions are 1.1 and 1.3. When set, the JSONL layer applies the following transformations:

  • Strips fields added after the target version: ai_model, container, observation_point_id
  • Removes unknown profile names from metadata.profiles: ai_operation, container
  • Rewrites metadata.version to match the target version

The shorthand log output is unaffected. The internal event model stays at v1.8.0; only the serialized JSONL is transformed.

When unset or empty, no downgrade is applied and events are written at the current schema version.

SIEMRequired OCSF Versionocsf_schema_version Value
AWS Security Lakev1.1.01.1
Splunk CIM Add-Onv1.1-v1.31.1 or 1.3
CrowdStrike FDRv1.5.0Not yet supported
Datadog Cloud SIEMv1.5.0 (selectable)Not yet supported

Downgrading is lossy. The ai_model field and ai_operation profile are stripped for v1.1 and v1.3 targets, so AI model attribution is not present in downgraded events. If your audit workflow requires knowing which model handled a request, use the full schema version (leave ocsf_schema_version unset). OpenShell supports OCSF v1.8.0 natively; upgrade your SIEM’s OCSF schema if you need AI attribution alongside backward-compatible ingestion.

Downgraded events include a downgraded_from marker in the unmapped object so auditors can distinguish “no model was involved” from “model attribution was stripped”:

{
"unmapped": {
"downgraded_from": "1.8.0"
}
}

The core OCSF event structure (class UIDs, activity IDs, network and HTTP fields) is identical across v1.1 through v1.8. The stripped fields are all profile-gated additions.

Integration with External Tools

The JSONL file can be shipped to any tool that accepts OCSF-formatted data:

ToolIntegration Path
SplunkUse the Splunk OCSF Add-on to ingest OCSF JSONL files. Set ocsf_schema_version to 1.3 for CIM Add-On compatibility.
Amazon Security LakeOCSF is the native schema for Security Lake. Set ocsf_schema_version to 1.1 for v1.1.0 compatibility.
CrowdStrike FDRShip JSONL files to Falcon Data Replicator. v1.5 downgrade target is not yet supported.
ElasticUse Filebeat to ship JSONL files with the OCSF field mappings.
Custom pipelinesParse the JSONL file with jq, Python, or any JSON-capable tool.

After copying supervisor files into ./supervisor-logs, use jq to extract all denied connections:

jq -c 'select(.action == "Denied")' ./supervisor-logs/openshell-ocsf.*.log

Relationship to Shorthand Logs

Sandbox events identify the sandbox environment with device.type_id: 99 (Other) and device.type: "Sandbox". The operating system is reported separately in device.os.name; the device type does not classify the underlying host or compute backend.

The shorthand format in openshell.YYYY-MM-DD.log and the JSON format in openshell-ocsf.YYYY-MM-DD.log are derived from the same OCSF events. The shorthand is a human-readable projection; the JSON is the full structured record when no schema downgrade is configured. When ocsf_schema_version is set, the JSON export is a lossy projection of the internal event model. Both formats are generated at the same time from the same event data.

Shorthand stderr output follows the diagnostic log filter; its local file is available when file logging starts successfully. JSON stderr and file export are opt-in through ocsf_json_enabled. File export requires the supervisor’s JSONL sink to start successfully; stderr export is independent of that sink.

Next Steps