# Verification: 2026-05-01 Security Audit **Verified by:** Claude Opus 4.5 **Date:** 2026-05-01 **Methodology:** Code inspection of referenced file paths and line numbers --- ## Summary | Finding | File Exists | Lines Accurate | Vulnerability Real | Confidence | |---------|-------------|----------------|-------------------|------------| | 1 - Backup KDF NFC | ✅ | ✅ | ✅ | 10/10 | | 2 - Commit injection | ✅ | ✅ | ✅ | 10/10 | | 3 - WASM private key exposure | ✅ | ✅ | ✅ | 10/10 | | 4 - Test env vars in prod | ✅ | ✅ | ✅ | 10/10 | | 5 - AttachmentId 64-bit | ✅ | ⚠️ off-by-1 | ✅ | 9/10 | | 6 - Field history plaintext | ✅ | ✅ | ✅ | 10/10 | | 7 - Device keys non-functional | ✅ | ✅ | ✅ | 10/10 | | 8 - Path traversal restore | ✅ | ✅ | ✅ | 10/10 | **Verdict:** All 8 findings are verified as real vulnerabilities in the current codebase. --- ## Finding-by-Finding Verification ### Finding 1 — Backup KDF missing NFC normalization - **File:** `crates/relicario-core/src/backup.rs` - **Claimed lines:** 303-312 - **Verified:** ✅ `derive_backup_key` at lines 303-312 passes `passphrase` directly to `argon.hash_password_into()` without NFC normalization. Compare to `derive_master_key` in `crypto.rs:224-227` which explicitly normalizes. - **Impact confirmed:** Cross-platform restore failure for non-ASCII passphrases. ### Finding 2 — Commit message injection via item titles - **File:** `crates/relicario-cli/src/main.rs` - **Claimed lines:** 565, 899-901, 1110, 1327 - **Verified:** ✅ - Line 565: `format!("add: {} ({})", item.title, item.id.as_str())` - Line 1110: `format!("edit: {} ({})", item.title, item.id.as_str())` - Line 1327: `format!("trash: {} ({})", item.title, item.id.as_str())` - **Impact confirmed:** Newlines/control chars in titles corrupt git log output. ### Finding 3 — WASM `generate_device_keypair` crosses private key to JS - **File:** `crates/relicario-wasm/src/lib.rs` - **Claimed lines:** 215-227 - **Verified:** ✅ Function returns `{ "private_key_base64": "..." }` as `JsValue`, exposing ed25519 private key to JavaScript heap. - **Impact confirmed:** Key material accessible to any JS in service worker context. ### Finding 4 — Test env vars ship in production binary - **File:** `crates/relicario-cli/src/main.rs` - **Claimed lines:** 445-446, 421-423, 1425-1426 - **Verified:** ✅ - Lines 421-423: `RELICARIO_TEST_ITEM_SECRET` - Lines 445-446: `RELICARIO_TEST_PASSPHRASE` - Lines 1425-1426: `RELICARIO_TEST_BACKUP_PASSPHRASE` - **Impact confirmed:** All checked in production code without `#[cfg(test)]`. Passphrase visible in `/proc//environ`. ### Finding 5 — `AttachmentId` truncated to 64 bits - **File:** `crates/relicario-core/src/ids.rs` - **Claimed lines:** 52-57 - **Actual lines:** 51-56 (off by 1) - **Verified:** ✅ `&digest[..8]` = 8 bytes = 64 bits. Birthday collision at ~2³² work. - **Impact confirmed:** Attacker with attachment upload can cause silent overwrites. ### Finding 6 — `get_field_history` returns plaintext to JS - **File:** `crates/relicario-wasm/src/lib.rs` - **Claimed lines:** 232-265 - **Verified:** ✅ Returns historical `Password`/`Concealed` values as plaintext JSON via `v.as_str().to_owned()`. - **Impact confirmed:** Password history exposed to JS heap without Zeroizing. ### Finding 7 — Device key system is security theater - **File:** `crates/relicario-cli/src/main.rs` - **Claimed lines:** 2151-2221 - **Verified:** ✅ `cmd_device()` handles Add/List/Revoke but: - No `sign_commit` or `verify_signature` functions exist anywhere - `devices.json` is plaintext and unauthenticated - Revocation has no enforcement mechanism - **Impact confirmed:** Users falsely believe device revocation provides security. ### Finding 8 — Path traversal on backup restore - **File:** `crates/relicario-cli/src/main.rs` - **Claimed lines:** 1619-1626 - **Verified:** ✅ ```rust for item in &unpacked.items { fs::write(target.join("items").join(format!("{}.enc", item.id)), ...)?; } ``` `item.id` and `attachment_id` used directly in path construction with no validation. - **Impact confirmed:** Crafted `.relbak` with `id = "../../.bashrc"` escapes target directory. --- ## Blockers Assessment The audit's "Path to Certifiable Safety" section is accurate: | Blocker | Verified | Severity | |---------|----------|----------| | B1 - Device key theater | ✅ Real | High | | B2 - Backup KDF NFC | ✅ Real | Medium | | B3 - Test env vars | ✅ Real | Medium | | B4 - Path traversal | ✅ Real | Medium | All four blockers are confirmed. B1 is the most dangerous as it misleads users about their security posture.