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
- 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.
- Add a test for the startup guard so it cannot be removed unnoticed.
- Optionally: the guard lives in
borg.archiver, so importing e.g. borg.item alone under -O is unguarded — only relevant for library-style use.
- Optionally: move error message templates from docstrings to a normal class attribute so
-OO has one less failure mode in principle.
From a global code review of the borg2 codebase (2026-08). Original scope corrected in the comments below: the
-Ostartup guard already exists (#8649), so this issue is now only about not usingassertto validate untrusted/persisted data.Near-duplicate of #8649 ("review
assertusage") — 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__.pyrefuses to start when assertions are disabled (13b7e1f, #8649): it probesassert Falseat import time and exits with rc 2. That covers-O,-OOandPYTHONOPTIMIZE, for theborg/borgfsscripts,python -m borgand the PyInstaller binary — and, since-OOimplies-O, it also covers the docstring-derived error messages (helpers/errors.py: get_message()formatstype(self).__doc__) and argparse descriptions built fromdo_*.__doc__.Problem
Non-test code contains ~175
assertstatements. Some of them are not internal invariants but validation of persisted/untrusted data:fix_*converters insrc/borg/item.pyx(checking types/shapes of unpacked msgpack data),item.pyx(assert len(k) in (32 + 32, 32 + 128)),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
AssertionErrortraceback instead of a proper borg error with a sensible exit code.Proposed direction
IntegrityError/ValueError); keepassertfor genuine internal invariants.borg.archiver, so importing e.g.borg.itemalone under-Ois unguarded — only relevant for library-style use.-OOhas one less failure mode in principle.