Skip to content

buzz upload file rejects PDFs/documents the relay accepts β€” agents can't attach files the desktop canΒ #2963

Open

Description

@ams1

Thank you so much for releasing this beast in the wild! πŸ€—

Describe the bug

The CLI applies a client-side MIME allowlist that is stricter than the relay it uploads to, on the endpoint that exists to accept generic files. Files are rejected locally and never reach the server.

crates/buzz-cli/src/client.rs:1116 (upload_file):

if !ALLOWED_MIMES.contains(&mime.as_str()) {
    return Err(CliError::Usage(format!("unsupported file type: {mime}")));
}

ALLOWED_MIMES (client.rs:63) is image/jpeg, image/png, image/gif, image/webp, video/mp4.

But the same function uploads to PUT {relay}/upload (client.rs:1144) β€” the generic route, which the relay validates with validate_file_content() (crates/buzz-media/src/validation.rs:159) using a denylist (BLOCKED_FILE_MIME_TYPES: HTML/JS/SVG + executables). application/pdf is not blocked, and file_mime_to_ext() explicitly maps application/pdf β†’ pdf and …spreadsheetml.sheet β†’ xlsx.

So the server accepts these; the client refuses to send them.

To Reproduce

  1. buzz upload file --file report.xlsx
  2. β†’ {"error":"user_error","message":"unsupported file type: application/zip"}
    (an .xlsx is a zip container, so infer reports application/zip β€” a type the relay
    accepts on this endpoint.)
  3. Same for .pdf, .docx, .csv.
  4. buzz messages send --file report.xlsx fails identically β€” same code path, and this is the
    path agents use to attach anything.

Confirmed the server side by patching the check out locally and re-running: the same file
uploads and returns a normal {url, sha256, size} descriptor. Nothing server-side had to
change.

Expected behavior

The CLI should accept what the relay accepts. Either mirror BLOCKED_FILE_MIME_TYPES, or drop the pre-check and surface the server's 4xx β€” the server is the authority anyway, since it verifies magic bytes rather than a client-supplied type.

Why this matters

This is the file-attachment path for agents. Desktop already handles generic attachments (#2381 describes the composer as accepting "images, videos, PDFs, archives, and other supported files"), so an agent cannot attach a file that a human can attach to the same channel on the same relay.

Concretely: an agent that generates a spreadsheet or PDF report has no way to deliver it through Buzz.

Additional context

Two smaller issues in the same function:

  • Size cap: non-video files are checked against MAX_IMAGE_BYTES (50 MB, client.rs:1121). The relay has a separate max_file_bytes for the generic path, which the CLI has no notion of.
  • Error message: unsupported file type: application/pdf states the opposite of the truth for this relay, which makes the mismatch hard to diagnose.

If the relay ever exposes Blossom BUD-06 (HEAD /upload), asking the server for its
requirements would remove the duplicated policy entirely β€” the client would stop carrying a
second copy of a policy that only the server can enforce.

Environment

  • CLI built from source at 9cc9652c; code references above are against main @ a64cc71f, where client.rs is unchanged since that build
  • Relay: self-hosted, main @ ab3af828
  • macOS 15 (arm64)

Activity

  1. added
    bugSomething isn't working
    on Jul 26, 2026
  2. SteveSmart75 commented on Aug 7, 2026

    @SteveSmart75

    The error message is actively misleading β€” unsupported file type: application/pdf (or application/octet-stream in our case) states the type as the problem when it's really "not on this hardcoded allowlist."

    Note there's a related open issue, #3083, proposing exactly the fix: expand ALLOWED_MIMES to match what the relay actually accepts.

  3. maikunari commented on Aug 7, 2026

    @maikunari

    Tracking note: #3060 (denylist mirror) is still open but conflicted/stale. Several later PRs target the same bug (e.g. #4298). Bug still reproduces on current main. No action needed from reporters beyond picking any landed fix once one merges.

  4. mlamp commented on Aug 27, 2026

    @mlamp

    On current main, I found that the buzz CLI rejects most file types before contacting the relay. A non-interactive agent that produces Markdown documents cannot attach them, while the desktop client uploads the same bytes successfully. This is a different case from the PDF and Office examples above.

    I measured two points that I have not seen stated in this thread.

    The refusal is client-side

    Point the CLI at a dead port and compare a refused type with an allowed type:

    $ BUZZ_RELAY_URL=http://127.0.0.1:1 buzz upload file --file note.md
    rc=1  unsupported file type: application/octet-stream
    
    $ BUZZ_RELAY_URL=http://127.0.0.1:1 buzz upload file --file image.png
    rc=2  network error: Connection refused
    

    The PNG reaches the connection attempt. The Markdown file never opens a socket. I also confirmed this with a listener that received 0 bytes. The refusal is entirely client-side, so the relay is not consulted and cannot apply its own rules.

    The effective allowlist

    I probed ~50 types against a self-hosted relay. The entire accepted set was png, jpg, gif, webp, and mp4. This effective allowlist is narrower than the issue title suggests.

    The full refused list, with MIME types correctly detected, was: pdf, zip, gz, tar, 7z, xz, zst, html, svg, sh, doc, rtf, wasm, ttf, sqlite, bmp, tiff, ico, avif, heif, jxl, psd, mov, mkv, webm, avi, mp3, flac, wav, ogg, opus, m4a, aac, and midi.

    The issue is not limited to documents. Most ordinary image and audio formats are also refused.

    Text files (md, txt, csv, and json) are refused as application/octet-stream because infer returns nothing for them. That value is the fallback, not a special case. Allowing application/octet-stream would therefore be the wrong fix. The set needs to be widened or inverted.

    Relay behavior and #4880

    I uploaded the same Markdown with a raw Blossom PUT /upload. The request used a kind:24242 auth event signed with the same key the CLI uses. It returned HTTP 200, and the file round-tripped byte-identically through buzz media get. The relay stored it as application/octet-stream.

    I also uploaded synthetic files with valid PNG magic bytes but invalid image payloads. The relay returned HTTP 422 with invalid image data.

    The relay therefore re-validates the five types that the CLI permits and stores as-is the type that the CLI blocks. The client allowlist adds scrutiny where the server already has some and blocks the case the server handles most permissively.

    These results support mirroring BLOCKED_FILE_MIME_TYPES instead of maintaining a second, stricter, unrelated client policy. Mirroring the relay's denylist keeps the CLI from drifting out of sync. That is the approach in #4880.

  5. aclark-avantiweb commented on Nov 8, 2026

    @aclark-avantiweb

    We're hitting this too, on a self-hosted relay (relay-v0.2.1). Our agents use buzz messages send --file to pass plans to each other, and the CLI refuses .md, .txt, .pdf and .zip locally with "unsupported file type". We checked against an unreachable relay URL: the file never leaves the machine, while the same files upload fine from Buzz Desktop. For now our agents paste documents as message text instead.

    Any of #2431 or #7476 would fix it for us, together with #7324 so documents don't show up as broken images.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions