{"record":{"id":"08f1c302e5623e8f","repo":"tinyhumansai/openhuman","slug":"encrypted-value-too-short-missing-nonce","errorCode":null,"errorMessage":"Encrypted value too short (missing nonce)","messagePattern":"Encrypted value too short \\(missing nonce\\)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/security/keyring/encrypted_store.rs","lineNumber":147,"sourceCode":"            let plaintext = self.decrypt_legacy_xor(hex_str)?;\n            let migrated = self.encrypt(&plaintext)?;\n            Ok((plaintext, Some(migrated)))\n        } else {\n            // Plaintext — no migration needed\n            Ok((value.to_string(), None))\n        }\n    }\n\n    /// Check if a value uses the legacy `enc:` format that should be migrated.\n    pub fn needs_migration(value: &str) -> bool {\n        value.starts_with(\"enc:\")\n    }\n\n    /// Decrypt using ChaCha20-Poly1305 (current secure format).\n    fn decrypt_chacha20(&self, hex_str: &str) -> Result<String> {\n        let blob =\n            hex_decode(hex_str).context(\"Failed to decode encrypted secret (corrupt hex)\")?;\n        anyhow::ensure!(\n            blob.len() > NONCE_LEN,\n            \"Encrypted value too short (missing nonce)\"\n        );\n\n        let (nonce_bytes, ciphertext) = blob.split_at(NONCE_LEN);\n        let nonce = Nonce::from_slice(nonce_bytes);\n        let key_bytes = self.load_or_create_key()?;\n        let key = Key::from_slice(&key_bytes);\n        let cipher = ChaCha20Poly1305::new(key);\n\n        let plaintext_bytes = cipher\n            .decrypt(nonce, ciphertext)\n            .map_err(|_| anyhow::anyhow!(\"Decryption failed — wrong key or tampered data\"))?;\n\n        String::from_utf8(plaintext_bytes)\n            .context(\"Decrypted secret is not valid UTF-8 — corrupt data\")\n    }\n","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/security/keyring/encrypted_store.rs#L129-L165","documentation":"A value carrying the `enc2:` prefix decoded to a blob shorter than the 12-byte nonce alone. The decryptor splits nonce from ciphertext at a fixed offset; a too-short blob means the stored ciphertext is truncated or corrupt — the size guard fires before any decryption is attempted.","triggerScenarios":"Thrown at src/openhuman/security/keyring/encrypted_store.rs:147 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check whether the stored value was truncated (column limits, manual edit)","Restore the secret from its original source and re-store it","If the record is unrecoverable, delete and re-create the credential"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}