flashman
← All posts

Base64 binary corruption from UTF-8 decoding

Debug Base64 binary corruption by preserving bytes, avoiding accidental UTF-8 conversion, comparing hashes, and validating signatures across API boundaries.

2026-08-27 · 6 min read · Rahul Chitturi

  • base64
  • binary
  • debugging

Base64 encodes bytes, but many application APIs are built around strings. If arbitrary file bytes are decoded as UTF-8 before Base64 encoding, invalid byte sequences may become replacement characters and the original file cannot be recovered.

The encoded text can still look valid and decode successfully. The damage is visible only when byte length, magic bytes, checksum, or the consuming file parser is checked.

Find the first byte-to-text conversion

Start with a small, non-sensitive binary fixture and record its byte length and hash. Trace whether each boundary carries a byte array, stream, Blob, Buffer, or string.

  • Do not pass arbitrary binary data through TextDecoder and TextEncoder
  • Check whether a database column or message field coerces bytes to text
  • Confirm browser code reads files as ArrayBuffer rather than text
  • Compare decoded magic bytes with the expected file format

Keep text and binary contracts separate

For text content, specify the character encoding and encode that text to bytes once. For files, preserve raw bytes from input through Base64 conversion and back. Do not infer that a payload is text merely because its transport representation is a string.

Set decoded-size limits before allocation and reject malformed input clearly. A Base64 decoder accepting the alphabet says nothing about whether the resulting bytes form a valid image, archive, or document.

A Flashman workflow

Use the Base64 tool with a safe fixture, the hash tool to compare source and decoded data, the diff tool for transport strings, and the hex/text converter to inspect leading bytes without pretending the whole file is Unicode text.

Add round-trip tests containing zero bytes and invalid UTF-8 sequences. If the final hash differs from the source, inspect the first changed boundary rather than changing padding or alphabets at random.

Try these tools