You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
messages send: content silently truncated at first NUL byte, still accepted:true (Windows CLI) #5916
buzz messages send (Windows CLI, buzz.exe) silently truncates message content at the first NUL byte (0x00) and still returns {"accepted":true} — the relay stores only the prefix, with no error and no indication of data loss.
To Reproduce
On Windows, invoke buzz.exe messages send with a --content argument containing an embedded NUL byte (e.g. ...codigo + 0x00 + 0xc0000005 ...). Rust OsString/argv on Windows can carry NUL-free strings only past Win32 CommandLineToArgvW, but a NUL inside the argument — produced, for instance, by PowerShell escape sequences — gets the string cut at the C-string boundary when the content is handled as a NUL-terminated string.
Real-world path we hit (agents running goose with GOOSE_SHELL=powershell): the model composes a message with Markdown inline code and passes it through a PowerShell expandable here-string:
In an expandable here-string, `0 is the PowerShell escape for NUL. The resulting argument contains a real 0x00 byte, and buzz.exe accepts and publishes only the prefix before it:
Composed content: 2,329 chars
Relay event content: 466 chars — cut exactly at `0
Differential validation (messages sent to a test channel and deleted after inspection):
Here-string
Content sent
Content on relay
Expandable @"..."@ with `0xc...`
~78 chars
40 chars — cut at `0
Literal @'...'@ (same content)
~90 chars
90 chars — complete
CLI output in both cases: {"accepted":true,"event_id":"...","message":""}.
Expected behavior
At minimum, buzz messages send should fail loudly (non-zero exit, error JSON) when the resolved --content contains a NUL byte — or sanitize/strip it with a warning. accepted:true with silently truncated content is the worst outcome: the agent believes the full message was delivered, and no layer (CLI, relay, Desktop UI) surfaces the loss.
Same class of issue as the one we reported in goose (aaif-goose/goose#11259, silently executing only the first line of a multi-line cmd /C command): silent truncation anywhere in the send path is much costlier than a hard error.
Discovered via Buzz-managed goose agents on 2026-08-14; evidence extracted from goose sessions DB vs relay events, plus controlled send/delete tests on a live channel.
One boundary matters here: Buzz cannot reject the NUL from the reported --content call because the process never receives it. Windows gives CreateProcessW one null-terminated command line, and CommandLineToArgvW produces null-terminated argument strings. The native command line is therefore cut before buzz.exe starts. On current main, Buzz enters through std::env::args(), and Clap hands cmd_send_message an already-shortened String; the missing suffix is indistinguishable from an intentional short message.
#3116, #3202, and #4700 cover a different case: a NUL that actually reaches Buzz, such as through stdin or another event transport. Rejecting that before persistence is useful, but it cannot detect this argv loss.
For the command in this report, the safe PowerShell shape is a literal here-string sent on stdin:
That preserves the Markdown backtick and avoids the Windows argv boundary. A Buzz follow-up could add this literal-here-string example to CLI help or docs, but --content $msg cannot truthfully fail on truncation it has no way to observe.
Activity
kiranmagic7 commentedon Aug 15, 2026
One boundary matters here: Buzz cannot reject the NUL from the reported
--contentcall because the process never receives it. Windows givesCreateProcessWone null-terminated command line, andCommandLineToArgvWproduces null-terminated argument strings. The native command line is therefore cut beforebuzz.exestarts. On currentmain, Buzz enters throughstd::env::args(), and Clap handscmd_send_messagean already-shortenedString; the missing suffix is indistinguishable from an intentional short message.#3116, #3202, and #4700 cover a different case: a NUL that actually reaches Buzz, such as through stdin or another event transport. Rejecting that before persistence is useful, but it cannot detect this argv loss.
For the command in this report, the safe PowerShell shape is a literal here-string sent on stdin:
That preserves the Markdown backtick and avoids the Windows argv boundary. A Buzz follow-up could add this literal-here-string example to CLI help or docs, but
--content $msgcannot truthfully fail on truncation it has no way to observe.fix(cli): honest NUL contract + post-truncation diff validate
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in message content instead of silently tru…
fix(cli): reject NUL bytes in Rust-visible message content
fix(cli): reject NUL bytes in message content instead of silently tru…