Skip to content

from_url: Validate HTTP response status and Content-Range header when resuming downloads to prevent data corruption #11

@coderabbitai

Description

@coderabbitai

Summary

In flash_from_url (src/fls/from_url.rs), when a connection is interrupted and the download is retried, start_download is called with resume_from = Some(progress.bytes_received), which sends a Range: bytes=<offset>- header. However:

  1. The HTTP response status code is never checked — if the server returns 200 OK (full content) instead of 206 Partial Content, the data stream restarts from byte 0 and gets silently stitched to the previously-received bytes, corrupting the output.
  2. The Content-Range response header is not validated — even for a 206 response, the actual start offset returned by the server is never confirmed to match progress.bytes_received.

Additionally, the content-length calculation response.content_length().map(|len| len + offset) assumes the server honored the Range request; if it returned 200 instead, this produces an inflated and incorrect total length.

Impact

  • For uncompressed files, data would be silently corrupted.
  • For compressed files (gzip, xz, etc.): if the server returns 200 with a full restart, the decompressor receives a valid but restarted stream stitched mid-stream, potentially causing subtle corruption that survives decompression (depending on format/block boundaries).

Suggested Fix

After calling start_download with a non-None resume_from:

  1. Check that the response status is 206 Partial Content; if 200, either restart from scratch (reset bytes_received) or return an error indicating the server does not support resumable downloads.
  2. Parse the Content-Range header and verify the start offset matches resume_from.

References

/cc @mangelajo

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions