Found while fixing protected attachments for 3.1.2 (see BinaryProperties.md). In the KDBX implementation
(KdbxDatabase, KdbxEntry, KdbxSerializableDatabase):
-
Unused attachment content is kept. Replacing an attachment (setBinaryProperty with an existing name)
or removing one (removeBinaryProperty) removes the entry's reference, but the content stays in the binary
pool (Meta/Binaries in KDBX 3.1, the inner header in KDBX 4) and is written on every save. KeePass drops
pool items that nothing refers to (entries or their history) when it saves. As it is, files grow, and content
the user removed is still in the file.
-
Attachments are looked up both by ID and by position. Entries refer to pool items by ID (Ref), but
SerializableDatabase.getBinary(index) and isBinaryProtected(index) use the position in the pool
(the existing TODO in KdbxSerializableDatabase.getBinary). They agree for files that are read, where IDs are
assigned in order, but nothing guarantees it, e.g. after fixing 1. Writing should renumber the pool and the
references together.
-
Inline attachment content isn't read. KeePass also reads an entry's <Binary><Value> holding the content
itself (Base64, with Compressed or Protected), not a Ref into the pool, which some older files have.
KeePassJava2 reads such an entry without its attachment.
-
The database's compression setting isn't followed for attachments. Unprotected attachments in
Meta/Binaries are always gzipped (Compressed="True") unless they were read uncompressed; KeePass compresses
them only if the database uses compression. Every reader accepts either, so this is about matching KeePass.
Related, not about attachments: there's no way to choose the property value strategy when reading a database
(KdbxDatabase.read). Values read use the default strategy; a strategy set afterwards applies only to values
created later. This affects attachments too, from 3.1.2, since protected ones are held by the strategy's
protected factory.
Found while fixing protected attachments for 3.1.2 (see
BinaryProperties.md). In the KDBX implementation(
KdbxDatabase,KdbxEntry,KdbxSerializableDatabase):Unused attachment content is kept. Replacing an attachment (
setBinaryPropertywith an existing name)or removing one (
removeBinaryProperty) removes the entry's reference, but the content stays in the binarypool (
Meta/Binariesin KDBX 3.1, the inner header in KDBX 4) and is written on every save. KeePass dropspool items that nothing refers to (entries or their history) when it saves. As it is, files grow, and content
the user removed is still in the file.
Attachments are looked up both by ID and by position. Entries refer to pool items by ID (
Ref), butSerializableDatabase.getBinary(index)andisBinaryProtected(index)use the position in the pool(the existing TODO in
KdbxSerializableDatabase.getBinary). They agree for files that are read, where IDs areassigned in order, but nothing guarantees it, e.g. after fixing 1. Writing should renumber the pool and the
references together.
Inline attachment content isn't read. KeePass also reads an entry's
<Binary><Value>holding the contentitself (Base64, with
CompressedorProtected), not aRefinto the pool, which some older files have.KeePassJava2 reads such an entry without its attachment.
The database's compression setting isn't followed for attachments. Unprotected attachments in
Meta/Binariesare always gzipped (Compressed="True") unless they were read uncompressed; KeePass compressesthem only if the database uses compression. Every reader accepts either, so this is about matching KeePass.
Related, not about attachments: there's no way to choose the property value strategy when reading a database
(
KdbxDatabase.read). Values read use the default strategy; a strategy set afterwards applies only to valuescreated later. This affects attachments too, from 3.1.2, since protected ones are held by the strategy's
protected factory.