Skip to content

fix(ocsf): validate sandbox attribution against exported schemas - #5048

Open
aeilot wants to merge 5 commits into
NVIDIA:mainfrom
aeilot:fix/4915-ocsf-validated/aeilot
Open

aeilot wants to merge 5 commits into
NVIDIA:mainfrom
aeilot:fix/4915-ocsf-validated/aeilot

Conversation

@aeilot

@aeilot aeilot commented Oct 29, 2026

Copy link
Copy Markdown

Move supervisor attribution to device.container and gateway attribution to resources or unmapped. Remove the top-level container validation exemption and cover exported schemas, gateway profiles, and runtime JSONL attribution.

Refs #4915

Signed-off-by: Louis Deng louisaeilotd@gmail.com

Summary

Fix sandbox-associated OCSF records being rejected by strict OCSF 1.8.0 consumers because of the undefined top-level container attribute. Preserve sandbox identity in schema-defined fields and validate the complete records without a container exemption.

Related Issue

Closes #4915

Changes

  • Move supervisor sandbox identity to device.container and declare the container profile.
  • Keep gateway host identity in device. Use sandbox resources entries for API Activity and Detection Finding, and unmapped for other applicable gateway classes. Authentication records do not attach a sandbox container.
  • Set Docker and Podman image.uid from the resolved workload image ID, retaining the requested reference in image.name. Omit image when no resolved UID is available.
  • Remove the top-level container allowance from openshell-ocsf-validate, following the validator replacement in feat(ocsf): validate OCSF events against exported JSON Schemas #5019.
  • Add schema exports and regression coverage, and document the new attribution paths.

Kubernetes image enrichment remains a follow-up, as agreed in the issue. Kubernetes records omit image while retaining sandbox identity.

Release Notes

Sandbox attribution paths have changed:

  • Supervisor: device.container.uid and device.container.name.
  • Gateway API Activity and Detection Finding: resources entries with type: "sandbox".
  • Other applicable gateway classes: unmapped.sandbox_id and unmapped.sandbox_name.

SIEM parsers using top-level container.uid or container.name must update their mappings.

The new shape is finalized for review. As discussed in the issue, maintainers will coordinate with the XSIAM content pack maintainer before shipping; that notification remains outstanding.

Testing

  • Checks appropriate to the affected code and behavior pass
  • Unit tests added/updated
  • E2E tests added/updated

After synchronizing with upstream main:

  • 1,599 component tests passed; 4 ignored.
  • 33 gateway OCSF tests and 1 SPIFFE JWT integration test passed.
  • Clippy, Rust formatting, and Cargo lockfile alignment passed.
  • Docker ocsf_console passed using rebuilt runtime images.
  • Podman ocsf_jsonl_conformance passed, validating real supervisor JSONL, sandbox attribution, and the resolved workload image UID.

Thirty synthetic records also passed the official OCSF 1.8 validator with zero errors. This online validation is separate from the real JSONL validation performed by the Podman E2E test.

Documentation validation reported zero errors and three warnings: MDX parsing on the unchanged gateway configuration page, redirect checking skipped without authentication, and theme contrast.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Relevant supervisor and OCSF documentation updated

Move supervisor attribution to device.container and gateway attribution to resources or unmapped. Remove the top-level container validation exemption and cover exported schemas, gateway profiles, and runtime JSONL attribution.

Refs NVIDIA#4915

Signed-off-by: Louis Deng <louisaeilotd@gmail.com>
Port resolved Docker and Podman image identity to the exported-schema implementation. Preserve upstream network trust helpers, validate complete image-bearing events, and assert the actual workload image identity in supervisor JSONL conformance.

Refs NVIDIA#4915

Signed-off-by: Louis Deng <louisaeilotd@gmail.com>
Merge upstream dependency security fixes and Go SDK routing updates before review. Validate OCSF regressions, gateway SPIFFE JWT verification, and Docker/Podman end-to-end behavior against the synchronized tree.

Refs NVIDIA#4915

Signed-off-by: Louis Deng <louisaeilotd@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Oct 29, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

All contributors have signed the DCO ✍️ ✅
Posted by the DCO Assistant Lite bot.

@aeilot

aeilot commented Oct 29, 2026

Copy link
Copy Markdown
Author

I have read the DCO document and I hereby sign the DCO.

@aeilot

aeilot commented Oct 29, 2026

Copy link
Copy Markdown
Author

recheck

@krishicks

krishicks commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

@aeilot Let's get those merge conflicts resolved and I can kick off CI for it.

@aeilot

aeilot commented Nov 2, 2026

Copy link
Copy Markdown
Author

@aeilot Let's get those merge conflicts resolved and I can kick off CI for it.

Sure, I'll do that.

Signed-off-by: Louis Deng <louisaeilotd@gmail.com>
@aeilot

aeilot commented Nov 2, 2026

Copy link
Copy Markdown
Author

@krishicks The merge conflicts have now been resolved. You can start the CI.

@krishicks

Copy link
Copy Markdown
Collaborator

/ok to test 0e08ac2

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

Compatibility review (advisory)

New or updated breaking changes; see the full report for all findings.

1. api-behavior — No explicit risk acceptance found

Top-level container.uid and container.name move to device.container for supervisor records and resources or unmapped for gateway records.

2. api-behavior — No explicit risk acceptance found

Kubernetes supervisor records previously emitted container.image.name for known image references but now omit the entire image object without a resolved image UID.

Review details
  • Execution: complete
  • Candidate: PR #5048 (ce08d01fb5ce07a52f97c4712f40a52421409378)
  • Baseline: 9cc5f6e4ccb8d5740c9a8dc7b4c0dc4e1d0f97f2 (9cc5f6e4ccb8d5740c9a8dc7b4c0dc4e1d0f97f2)
  • Reviewed: rust-sdk, python-sdk, go-sdk, typescript-sdk, api-behavior, cli, configuration, policy, helm, state

Advisory review; publication gates are unchanged.

Branch check run

@krishicks

Copy link
Copy Markdown
Collaborator

Written by Claude Code, reviewed by @krishicks

Thanks for this, the supervisor side looks right: device.container with the container profile, and resolving image.uid from the provisioned image ID (rather than re-resolving the tag) is what we want, since it lets us keep image.name. A few changes before we merge:

1. Gateway attribution must not route on request-supplied sandbox IDs.
OcsfEvent::sandbox_id() falls back to the first resources[type=sandbox] entry, and the tracing bus and the OTLP openshell.sandbox.id attribute now use it. The gateway's authz-denial audit puts the requested sandbox ID in exactly that resource (AuthzDenial::CrossSandbox in crates/openshell-server/src/auth/audit.rs), with an empty context sandbox. Before this PR that denial stayed gateway-wide. With it, a sandbox that calls a sandbox-scoped RPC with another sandbox's ID gets the denial written into that sandbox's openshell logs tail and live stream, and tagged with that ID in OTLP. Repeating with arbitrary IDs also creates tracing-bus entries for sandboxes that don't exist and are never removed.

Routing should only use identity that came from EventContext. The simplest option is to use unmapped.sandbox_id / unmapped.sandbox_name for every gateway class, and have sandbox_id() read only device.container.uid and unmapped.sandbox_id. That also removes the 6003 | 2004 special case in apply_common_fields, add_sandbox_resource, and the new DetectionFindingEvent.resources field. If you'd rather keep resources for API Activity and Detection Finding, that's fine too, but then sandbox_id() shouldn't read them. Either way, please add a test showing that a cross-sandbox denial isn't routed to the named sandbox.

2. Keep the image reference when no UID is available.
On main, Kubernetes, VM, and shared-supervisor records carry container.image.name; with this PR they drop image entirely. Until those drivers can supply a resolved ID, could you put the reference in unmapped.container_image when container_image_uid is absent? That keeps the field on every driver without putting a tag in uid. Kubernetes image.uid enrichment can still be a follow-up; please file an issue for it.

3. Smaller items.

  • With a UID but no reference, Docker emits image.name: "". Making Image::name an Option would omit it instead.
  • The gateway unmapped branch writes sandbox_name: "" when the name is empty; add_sandbox_resource already skips that case.
  • Optional: declaring the container profile without the attribute is valid, so the metadata() filter and the two new gateway schemas aren't needed for conformance. Keep them if you prefer gateway records not to declare a profile they don't use.

We'll handle the XSIAM content pack notification before this ships.

@aeilot

aeilot commented Nov 3, 2026

Copy link
Copy Markdown
Author

Thanks for the review. I’ll make the following changes before requesting another review:

  1. Use context-derived identity for gateway routing. All gateway event classes will write sandbox attribution from EventContext to unmapped.sandbox_id and, when nonempty, unmapped.sandbox_name. OcsfEvent::sandbox_id() will read only device.container.uid and unmapped.sandbox_id, never resources. I’ll remove add_sandbox_resource, the class-specific attribution branch, and the newly added DetectionFindingEvent.resources field. API Activity resources will continue to describe requested targets as audit evidence.

  2. Add routing regression coverage. A cross-sandbox denial naming sandbox B will remain gateway-wide: it must not appear in B’s log tail or live stream, receive B’s OTLP sandbox attribute, or create tracing-bus entries for arbitrary requested IDs. I’ll also verify that gateway events with trusted context identity still route correctly.

  3. Preserve image references without a resolved UID. When a nonempty container_image_uid is available, supervisor events will retain the standard device.container.image representation. Otherwise, a known image reference will be preserved in unmapped.container_image. I’ll file a follow-up issue for Kubernetes image UID enrichment using the provisioned workload’s resolved identity.

  4. Omit empty optional names. I’ll make Image::name optional and omit it when no reference is available. Empty gateway sandbox names will also be omitted. Tests will cover UID-only, reference-only, both-present, and both-absent cases.

  5. Update documentation and validation. I’ll update the attribution documentation and PR description, run the affected schema, routing, and OTLP tests, and rerun the relevant OCSF end-to-end checks. I plan to retain the gateway profile filtering and schema exports, since they accurately describe the profiles those records use.

The compatibility advisory will still need an explicit release decision: preserving the image reference prevents information loss, but existing parsers still need to migrate from the legacy field paths. Could you record whether that migration is accepted for v0.1.7 or should move to a later release?

Thanks for handling the XSIAM content pack notification before shipping.

Signed-off-by: Louis Deng <louisaeilotd@gmail.com>
@aeilot

aeilot commented Nov 3, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed review. I’ve pushed the changes in fea7613.

Thanks for coordinating the XSIAM content pack notification

@krishicks

Copy link
Copy Markdown
Collaborator

/ok to test fea7613

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(ocsf): top-level container is undefined in OCSF 1.8.0 event classes

2 participants