Skip to content

apt uploads: a 40 KB .deb makes the control parser hold about 0.5 GiB, so a few concurrent uploads OOM-kill the instance #815

Closed

Description

@schmitch

Problem

Reading a .deb's control member (crates/formats/apt/src/deb.rs) bounds the CPU time but not the memory:

  • MAX_CONTROL_TAR_BYTES (deb.rs:15) lets the control member inflate to 256 MiB. Real control members are a few KB.
  • control_in_tar (deb.rs:156-157) reads the inflated tar with tar::Archive. The tar crate reads a GNU long-name or long-link entry, and a PAX header entry, whole into memory before it returns the next entry. So one long-name entry of up to 256 MiB is buffered.
  • The xz decoder (lzma_rust2::XzReader::new, deb.rs:130) has no memory limit, so a large dictionary adds its window on top.

This runs on every upload and every apt import, in publish_staged (crates/core/src/repo/hosted.rs:843), before anything is refused. Nothing limits how many publishes parse at once.

npm had the same hole: #487 fixed it for npm tarballs in 2.0.0.

Scenario

  1. A writer of any apt repository uploads a .deb whose control.tar.xz holds one GNU L (long-name) entry of about 256 MiB of a, compressed with a large dictionary. The file is 39 KB.
  2. The upload is refused with 400, but only after the process has held about 515 MiB.
  3. Two or three such uploads at once go past the Helm chart's and the kustomize base's default limits.memory: 1Gi, and the pod is OOM-killed, taking every other repository on it down. The writer can repeat this at will.

Measured with forge_format_apt::deb::control_file on crafted files:

Variant File size Peak RSS (VmHWM) Time
xz 39,368 bytes 527 MB 2.06 s
gzip 261 KB 265 MB —

Expected

Test: the crafted xz and gzip packages are refused while holding no more than a few MiB.

New with #176 (#725). #797 covers the memory of an index generation, not of the upload parser. Found in the 2.2.0 release review.

Activity

  1. added this to the 2.3.0 milestone on Nov 2, 2026
  2. modified the milestones: 2.3.0, 2.2.0 on Nov 3, 2026
  3. self-assigned this
    on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions