Skip to content

XMODEM download accepts EOT without verifying the advertised MD5 #666

Description

@righteousgambit

Environment

Summary

The receiver reads the machine-provided whole-file MD5 from block zero, but only uses it to decide whether an existing local file can be reused. It does not retain that digest and verify the bytes received during the current transfer. A peer that sends EOT after only a valid prefix therefore gets an ACK and the receiver reports a nonnegative byte count, leaving the caller to treat an incomplete artifact as a successful download.

Root cause

Reproduction

Use a deterministic XMODEM stream containing:

  1. Block zero advertising the MD5 of the intended complete file.
  2. Block one containing only a truncated prefix.
  3. EOT.

On the pinned revision, the receiver ACKs EOT and returns 8192 rather than rejecting the artifact. The regression assertion fails as:

E       assert 8192 is None

The same pinned revision also fails to preserve the cache shortcut when the equivalent local MD5 is supplied in uppercase; it proceeds with the transfer instead of returning 0, leaving the output empty, and issuing three CAN writes.

Impact

Ordinary TCP packet loss does not manufacture an EOT, so this is specifically an integrity failure when the peer ends the protocol prematurely. The remote play command is sent before the download in Controller.py, so this reproduction does not establish remote mid-cut execution. It does establish that incomplete local downloads can be accepted and then affect supported local behavior such as previewing, line counting, resuming, or reusing the artifact.

Acceptance criteria

  • Retain the expected MD5 supplied in block zero.
  • Incrementally hash only the actual, unpadded payload bytes written to the destination.
  • ACK EOT for protocol compatibility, but return None when the expected digest is missing or does not match.
  • Preserve the block-zero cache shortcut, including case-insensitive comparison of equivalent hexadecimal MD5 strings: return 0, write no output, and send exactly three CAN bytes.
  • Add deterministic regression coverage for matching content, mismatched/truncated content, and the uppercase-local-MD5 cache shortcut.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions