Skip to content

stop validating untrusted/persisted data with assert #10019

Description

@ThomasWaldmann

From a global code review of the borg2 codebase (2026-08). Original scope corrected in the comments below: the -O startup guard already exists (#8649), so this issue is now only about not using assert to validate untrusted/persisted data.

Near-duplicate of #8649 ("review assert usage") — same policy, this issue just names the concrete untrusted-data places. See also the pending draft PR #8682. Close as duplicate if you prefer to track it all in #8649.

Already done (not part of this issue)

src/borg/archiver/__init__.py refuses to start when assertions are disabled (13b7e1f, #8649): it probes assert False at import time and exits with rc 2. That covers -O, -OO and PYTHONOPTIMIZE, for the borg/borgfs scripts, python -m borg and the PyInstaller binary — and, since -OO implies -O, it also covers the docstring-derived error messages (helpers/errors.py: get_message() formats type(self).__doc__) and argparse descriptions built from do_*.__doc__.

Problem

Non-test code contains ~175 assert statements. Some of them are not internal invariants but validation of persisted/untrusted data:

  • the fix_* converters in src/borg/item.pyx (checking types/shapes of unpacked msgpack data),
  • the key-length check in item.pyx (assert len(k) in (32 + 32, 32 + 128)),
  • the size check in DownloadPipeline.fetch_many.

With the startup guard in place these no longer vanish silently, so this is not a safety-net hole anymore — but corrupt or malicious repo data still surfaces as a bare AssertionError traceback instead of a proper borg error with a sensible exit code.

Proposed direction

  1. Convert asserts that check untrusted/persisted data (item decoding, envelope parsing, sizes from the repo) into real exceptions (IntegrityError/ValueError); keep assert for genuine internal invariants.
  2. Add a test for the startup guard so it cannot be removed unnoticed.
  3. Optionally: the guard lives in borg.archiver, so importing e.g. borg.item alone under -O is unguarded — only relevant for library-style use.
  4. Optionally: move error message templates from docstrings to a normal class attribute so -OO has one less failure mode in principle.

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