No check for duplicate group UUID causes crash
Summary
A malformed KDBX file can reuse an ancestor’s UUID to create parent/child group cycles, causing the KeePassXC GUI to hang when the victim selects the attacker-controlled group (default build, no special config).
Details
KdbxXmlReader::parseGroup() reuses the first-seen UUID via getGroup(uuid) and then attaches children with child->setParent(group) without validating ancestry (src/format/KdbxXmlReader.cpp:596-626, 1168-1192).
Group::setParent() only asserts this != parent in debug and never checks ancestors for cycles (src/core/Group.cpp:461-514), so duplicate ancestor UUIDs create A→B→A loops in release builds.
UI paths assume parent chains terminate, e.g., entry->group()->fullPath() (src/gui/entry/EntryModel.cpp:139-142) and group->isRecycled() (src/gui/DatabaseWidget.cpp:2715-2729, invoked from src/gui/MainWindow.cpp:937); traversal on a cyclic group loops indefinitely on the UI thread.
PoC
- Export any valid KDBX to XML.
- In the XML, set an inner <Group>’s UUID to match one of its ancestor groups (keep nested structure).
- Repack/import and open in stock KeePassXC.
- Click the malicious group (or an entry within it). The UI becomes unresponsive (infinite loop/recursion).
Originally reported by @0xkato