Skip to content

fix(ocsf): widen the shorthand [reason:] budget so denial endpoints stay readable (NVIDIA/NemoClaw#4760)#1799

Open
latenighthackathon wants to merge 1 commit into
NVIDIA:mainfrom
latenighthackathon:fix/4760-ocsf-reason-truncation
Open

fix(ocsf): widen the shorthand [reason:] budget so denial endpoints stay readable (NVIDIA/NemoClaw#4760)#1799
latenighthackathon wants to merge 1 commit into
NVIDIA:mainfrom
latenighthackathon:fix/4760-ocsf-reason-truncation

Conversation

@latenighthackathon
Copy link
Copy Markdown
Contributor

@latenighthackathon latenighthackathon commented Jun 7, 2026

Summary

When a sandbox blocks an outbound connection, it writes a denial log line that should explain what was blocked and why: the destination address and the policy that rejected it. That explanation was being cut off at 80 characters and replaced with a literal ..., so nemoclaw <sb> logs --tail showed something like [reason:endpoint host.example:44...], with the port and the policy name chopped off. The operator can see that something was denied but not which endpoint to allow or which policy to adjust.

This widens the reason budget from 80 to 256 characters so the full endpoint and policy name fit. It also makes the truncation cut on a character boundary instead of a raw byte position, which keeps multi-byte text intact and removes a latent crash (the old byte-position slice could panic if it landed in the middle of a multi-byte character). The same safe truncation now also covers the related [msg:...] field.

Related Issue

Fixes NemoClaw issue #4760.

The user-facing symptom surfaces via nemoclaw <sb> logs --tail, but the OCSF shorthand emitter that truncates the reason is OpenShell code (crates/openshell-ocsf), so the fix lands in this repo.

Changes

  • MAX_REASON_LEN 80 -> 256 in crates/openshell-ocsf/src/format/shorthand.rs so a denial reason (endpoint <fqdn>:<port> not in policy <name>) stays readable instead of being cut mid-endpoint.
  • New truncate_with_ellipsis(text, max) helper that steps back to the nearest UTF-8 char boundary before slicing; used by both reason_tag and message_tag (the latter carried the same latent &text[..MAX] panic on multibyte input).

Testing

Ran the full gate in a container matching CI (rust 1.95.0 per rust-toolchain.toml plus the mise toolchain):

  • mise run pre-commit passes end-to-end (rust:format:check, rust:lint, rust:check, test:rust, python:format:check/lint/typecheck/proto, helm:lint, helm:docs:check, markdown:lint, license:check).
  • Unit tests added/updated: test_shorthand_reason_keeps_full_endpoint_and_policy (regression for NemoClaw issue #4760: a full endpoint <fqdn>:443 not in policy balanced reason renders end-to-end with no ...), test_shorthand_reason_truncated_beyond_max_len (an over-256 reason still truncates), and test_shorthand_reason_truncates_on_multibyte_char_boundary (multibyte input truncates without panicking).
  • E2E tests: N/A. This is a display-only projection in the openshell-ocsf leaf crate (it changes the rendered width of one log tag); there is no cluster or gateway-runtime behavior to assert, so the crate's own #[cfg(test)] module is the appropriate coverage.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs: N/A (no bootstrap/manifest/entrypoint change).

…tay readable (NVIDIA/NemoClaw#4760)

A denied egress logs an OCSF NET:OPEN DENIED line whose [reason:] field carries the full destination endpoint and the rejecting policy name, but the shorthand formatter capped the reason at 80 bytes and appended a literal "...". A typical reason is longer than that, so `nemoclaw <sb> logs --tail` showed the endpoint cut mid-string with the port and policy name lost:

  NET:OPEN [MED] DENIED ... [reason:endpoint host.example:44...]

Raise MAX_REASON_LEN to 256 so a full endpoint plus policy name fits, and route both reason_tag and message_tag through a shared char-boundary truncation helper. The previous `&text[..MAX]` byte slice would also panic if the cut fell inside a multibyte UTF-8 character.

The issue was reported on the NemoClaw tracker (NVIDIA/NemoClaw#4760, the user-facing `nemoclaw <sb> logs --tail` diagnostic), but the OCSF shorthand emitter is OpenShell code, so the fix lands here. Cross-repo references do not auto-close, so no closing keyword is used.

Ref: NVIDIA/NemoClaw#4760  (NVIDIA/NemoClaw#4760)
Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@latenighthackathon latenighthackathon force-pushed the fix/4760-ocsf-reason-truncation branch from bacdb37 to 041c98e Compare June 7, 2026 21:05
@latenighthackathon latenighthackathon changed the title fix(ocsf): widen the shorthand [reason:] budget so denial endpoints stay readable (#4760) fix(ocsf): widen the shorthand [reason:] budget so denial endpoints stay readable (NVIDIA/NemoClaw#4760) Jun 7, 2026
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.

1 participant