Skip to content

Fix KDBX minor version mismatch warning after reading header - #13979

Open
tikipiya wants to merge 5 commits into
keepassxreboot:developfrom
tikipiya:fix/13974-kdbx-minor-version-warning
Open

tikipiya wants to merge 5 commits into
keepassxreboot:developfrom
tikipiya:fix/13974-kdbx-minor-version-warning

Conversation

@tikipiya

@tikipiya tikipiya commented Nov 1, 2026

Copy link
Copy Markdown

Fixes #13974

Summary

  • Keep the KDBX version from the file header when setKdf() runs during open.
  • Add testMinorVersionMismatchAfterSetKdf to prevent regressions.

Testing strategy

  • ctest -R testkdbx4 -V (includes new test; all 41 subtests passed in Docker Ubuntu 24.04)

Type of change

  • Bug fix (non-breaking change that fixes an issue)

Preserve the file format version when applying KDF parameters during
open so hasMinorVersionMismatch() can warn about newer KDBX files.
Fixes keepassxreboot#13974
@droidmonkey droidmonkey added this to the v2.8.1 milestone Nov 1, 2026
@droidmonkey droidmonkey added the pr: bugfix Pull request fixes a bug label Nov 1, 2026
Comment thread src/core/Database.cpp
m_data.kdf = std::move(kdf);
setFormatVersion(KeePass2Writer::kdbxVersionRequired(this, true, m_data.kdf.isNull()));
// Preserve the KDBX version from the file header when loading (see #13974).
setFormatVersion(KeePass2Writer::kdbxVersionRequired(this, false, m_data.kdf.isNull()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks converting a database to KDBX 3. Saving the encryption settings goes through changeKdf() to setKdf(), where ignoreCurrent = false keeps the version at 4.0. KeePass2Writer::writeDatabase() then sees AES-KDBX3 with version 4 and replaces the KDF with AES-KDBX4.

I tested it on Qt 6.4.2 with a small QTest that drives the settings widget (condensed):

// db was read from a KDBX 4 file
DatabaseSettingsWidgetEncryption widget;
widget.loadSettings(db);
widget.initialize();
widget.findChild<QTabWidget*>("encryptionSettingsTabWidget")->setCurrentWidget(widget.findChild<QWidget*>("advancedTab"));
widget.findChild<QComboBox*>("compatibilitySelection")->setCurrentIndex(1); // "KDBX 3"
widget.findChild<QSpinBox*>("transformRoundsSpinBox")->setValue(100000);
QVERIFY(widget.saveSettings());
// write db with KeePass2Writer, read it back with KeePass2Reader
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3_1);
File version KDF after reopening
develop 3.1 AES-KDF (KDBX 3)
this PR 4.0 AES-KDF (KDBX 4)
this PR + the line below 3.1 AES-KDF (KDBX 3)

Adding this after setKdf(kdf) in changeKdf() fixes it. This PR's new test, testkdbx3, testkdbx4 and testdatabase still pass with it:

setFormatVersion(KeePass2Writer::kdbxVersionRequired(this, true));

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I will make the corrections.

Recalculate format version in changeKdf() so encryption settings changes
are not pinned to the previous KDBX minor version from the file header.
@tikipiya

tikipiya commented Nov 1, 2026

Copy link
Copy Markdown
Author

I have completed the revisions requested by Grinv. Please take a look.

@tikipiya
tikipiya requested a review from Grinv November 1, 2026 14:46
@Grinv

Grinv commented Nov 1, 2026

Copy link
Copy Markdown

Thanks for the quick fix! With d74f768 the database saves as 3.1 with AES-KDF (KDBX 3). If you want a regression test for this bug, you can add the one below. It fails without the new line in changeKdf() and passes with it (Qt 6.4.2). It also needs void testChangeKdfDowngradesToKdbx3(); in tests/TestKdbx4.h.

void TestKdbx4Format::testChangeKdfDowngradesToKdbx3()
{
    auto key = QSharedPointer<CompositeKey>::create();
    key->addKey(QSharedPointer<PasswordKey>::create("test"));

    Database db;
    db.setKey(key, true, true);
    db.changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2D)));
    QCOMPARE(db.formatVersion(), KeePass2::FILE_VERSION_4);

    db.changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)));
    QCOMPARE(db.formatVersion(), KeePass2::FILE_VERSION_3_1);

    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    KeePass2Writer writer;
    QVERIFY(writer.writeDatabase(&buffer, &db));

    buffer.seek(0);
    KeePass2Reader reader;
    Database reopened;
    QVERIFY(reader.readDatabase(&buffer, key, &reopened));
    QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3_1);
    QCOMPARE(reopened.kdf()->uuid(), KeePass2::KDF_AES_KDBX3);
}

@droidmonkey

Copy link
Copy Markdown
Member

Let's add the test, its a good one to be in the inventory

@tikipiya

tikipiya commented Nov 1, 2026

Copy link
Copy Markdown
Author

May I ask if this is a task that I should handle?

@Grinv

Grinv commented Nov 1, 2026

Copy link
Copy Markdown

May I ask if this is a task that I should handle?

Yes, please add it to this PR :)

@tikipiya

tikipiya commented Nov 1, 2026

Copy link
Copy Markdown
Author

Understood. I would be glad to take this on. Since this is my first PR, I am unfamiliar with many things, so I am very grateful to be working with such a kind and supportive team on this project.

Covers the format version recalculation added for Grinv's review on keepassxreboot#13979.
@tikipiya

tikipiya commented Nov 1, 2026

Copy link
Copy Markdown
Author

I believe it is complete.

@tikipiya

tikipiya commented Nov 1, 2026

Copy link
Copy Markdown
Author

#13982
I accidentally pushed the changes from this PR to this branch.

@tikipiya

tikipiya commented Nov 1, 2026

Copy link
Copy Markdown
Author

Would it be acceptable to close the other PR (#13982) and include the grammar and typo fixes in this PR as additional changes?

@phoerious

Copy link
Copy Markdown
Member

Since it's just one or two string changes, you can add them here. But please remove all the other language files from the commit. Only commit the keepassxc_en.ts file that is generated when you run ./release-tool i18n lupdate.

Correct "affect to" in EditGroupWidgetBrowser and update keepassxc_en.ts
via lupdate scope; fix duplicated words in comments and "a non-existent"
in TestCli.

Co-authored-by: Cursor <cursoragent@cursor.com>
@tikipiya
tikipiya force-pushed the fix/13974-kdbx-minor-version-warning branch from cf19ef3 to f0ba0d4 Compare November 2, 2026 00:58
@tikipiya

tikipiya commented Nov 2, 2026

Copy link
Copy Markdown
Author

Please check this.
(It seems that when I made a commit from the Cursor terminal, Cursor tagged along... I mind it at least, but please don't mind it.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: bugfix Pull request fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The warning for databases with a newer KDBX minor version never shows

4 participants