Skip to content

[updater] feat: caller-enforceable size bound on download() (unbounded in-memory buffering before signature verification) #3554

Description

@alejoamiras

Describe the problem

Update::download() (plugins/updater/src/updater.rs, currently ~L724–L735) buffers the entire artifact into an unbounded Vec<u8> before verify_signature runs:

let mut buffer = Vec::new();
while let Some(chunk) = /* stream */ {
    on_chunk(chunk.len(), content_length);
    buffer.extend(chunk);
}

There is no way for the caller to bound the bytes actually read:

  • on_chunk(usize, Option<u64>) returns () — it can observe progress but cannot abort the download.
  • content_length comes from the response the attacker controls, so pre-checking it (or the size a custom feed advertises) authenticates nothing — a tampered manifest can omit the size or declare a small one while url points at a multi-GB blob.

Signature verification still protects integrity (minisign rejects tampered bytes), but it runs only after the full body is in memory, so availability is unprotected: an attacker who can tamper the update feed (or MITM a plain-HTTP feed) can make the app allocate until OOM, without ever needing the signing key.

Request

An enforceable, caller-set bound on bytes read in the download path. Any of these shapes would work:

  1. A builder option, e.g. UpdaterBuilder::max_download_bytes(u64), aborting the request with a typed error once exceeded (checked against actual bytes read, not headers);
  2. Making the chunk callback fallible/controlling, e.g. on_chunk: FnMut(usize, Option<u64>) -> ControlFlow<()>, so callers can abort mid-stream (with the plugin treating Break as a download error);
  3. Streaming the body to a temp file instead of RAM (bounds memory, though a disk cap would still be nice).

Option 1 is the smallest surface and keeps the verified-download path fully inside the plugin — important because working around this today means reimplementing download+verify outside the plugin, which turns a hand-rolled path into the sole authenticity control (exactly what one wants to avoid).

Context

  • tauri-plugin-updater 2.10.1 (current), behavior confirmed at repo HEAD.
  • Not reporting as a vulnerability: it requires a compromised/MITM'd feed and is availability-only; filing as hardening so apps can enforce a pre-flight cap that actually holds.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions