docker_backup: encryption settings passphrase stored double-encoded — UI passphrase ≠ effective key #55
Labels
No labels
blocked:gate-fetch
blocked:gate-fetch
blocked:gate-fetch
blocked:gate-fetch
blocked:lint-failed
blocked:needs-decision
blocked:no-changes
blocked:no-procedure
blocked:verify-failed
bug
feature-request
in-progress
needs-decompose
needs-triage
ops-task
quickfix
security/high
security/low
security/medium
test-coverage
triage-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/docker_backup#55
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Source: kanban card
t_c34f4bfb(findings from encryption-at-rest end-to-end verification, parentt_8112dd39). Empirically confirmed on the live system 2026-08-19.Problem
PUT /api/settingsstores each settings value viaJSON.stringify(value)per key; the encryption config readergetBackupEncryptionConfig()reads the storedencryptionKeywithString(lookup.get('encryptionKey') ?? '')and does notJSON.parseit. Net effect: the effective passphrase is the user's typed value wrapped in literal double quotes.Reproduction steps
PviaPUT /api/settings(as a user would type it in the UI, e.g.probe-passphrase-2026-08-16).Setting.encryptionKeyin/data/docker-backup.dbcontains the value with literal double quotes wrapped around it (e.g."\"probe-passphrase-2026-08-16\"").DOCKER_BACKUP_ENCmagic), using the unquoted passphrase the user actually typed.Unsupported state or unable to authenticate data(AES-GCM auth-tag failure).Empirical proof (live archive
/backups/full/cmswbp5f20006aq7x0k2kqhxv.tar.encon zsus):"probe-passphrase-2026-08-16"→ succeeds, yields a valid POSIX tar (hello.txt,sub/world.txt,sub/data.json).probe-passphrase-2026-08-16(what a user types in the UI) → fails with AES-GCM auth-tag error.Actual behavior
Expected behavior
PviaPUT /api/settings, the DB value should equalP(no extra quotes).Pshould succeed.Suggested fix
The settings store should
JSON.parsethe stored value on read (or store the string raw) so the UI passphrase is the effective passphrase. The crypto itself (magicDOCKER_BACKUP_ENC/ header / AES-256-GCM / PBKDF2 100k) is verified sound — this is purely a read-path quoting bug.Location
The #20 encryption settings wiring in the docker-backup-app settings handling (repo
Mark/docker_backup): backend settings route (PUT /api/settings=JSON.stringifyper key) and the backup config reader (readsencryptionKeywithString()without a parse).Verification
After fix: set passphrase
PviaPUT /api/settings; DB value should equalP(no extra quotes); tooling-side decrypt of a fresh archive withPshould succeed.Follow-up to the #20 encryption-at-rest verification (all acceptance criteria PASS there; this is a separate wiring defect).