Skip to content

apt: one package with a malformed Depends (or another relationship field) is published as is, and apt-get update then fails on every client of the repository #814

Open

Description

@schmitch

Problem

Control::parse (crates/formats/apt/src/manifest.rs:60-97) checks only Package, Version, Architecture and Section. The relationship fields are never validated:

  • control::relations (crates/formats/apt/src/control.rs:235) is lenient and never fails.
  • The control text is stored as it is (manifest.rs:144-156) and written into each Packages file (crates/formats/apt/src/index.rs:50-78).
  • An Architecture: all package goes into every architecture's Packages.

apt refuses a whole Packages file when one stanza's relationship field does not parse:

E: Problem parsing dependency 20 of teama-x:amd64=1.0
E: Problem with MergeList …_Packages
E: The package lists or status file could not be parsed or opened.

From then on every apt command on that host fails, installs from Debian's or Ubuntu's own repositories included. That lasts until the version is deleted and the client runs apt-get update again.

Reproduced with apt 2.8.3 against a repository holding one bad stanza and one good one. Each of these broke it:

  • Depends: libc6 libssl3 (missing comma);
  • Depends: a,,b;
  • Breaks: foo (<< 1;
  • Provides: foo bar;
  • the same in Pre-Depends, Recommends, Suggests, Conflicts and Replaces, and garbage in an architecture qualifier.

dpkg-deb --build checks these fields, but dpkg-deb --nocheck, fpm, nfpm and hand-built packages do not.

Scenario

  1. A writer uploads a .deb whose control has Depends: libc6 libssl3. Forge answers 201 and lists it.
  2. The next index generation includes the stanza.
  3. apt-get update fails on every client of the repository, and apt stops working on those hosts.

With package selectors, a writer limited to teama-* breaks every other team's consumers. An import from a source holding such a package does the same.

Expected

On publish and import, refuse with 400 a control whose relationship fields do not parse with dpkg's grammar:

  • fields: Depends, Pre-Depends, Recommends, Suggests, Enhances, Breaks, Conflicts, Replaces, Provides, Built-Using;
  • grammar: comma-separated clauses, | alternatives, name[:arch] [(op version)] [[arch …]] [<profile …>].

Tests: each of the inputs above is refused by Control::parse, and the upload answers 400.

New with #176 (#725). #761 is a different way for one writer to break the indexes, through Forge's own index limits. Found in the 2.2.0 release review.

Activity

  1. added this to the 2.3.0 milestone on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions