fix(cli): validate IDs on backup restore (audit B4)
Crafted .relbak files with IDs like "../../.bashrc" could escape the target directory. Now validates that item/attachment IDs are hex-only via is_valid() before any fs::write. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1586,6 +1586,7 @@ fn tar_directory(dir: &std::path::Path) -> Result<Vec<u8>> {
|
|||||||
fn cmd_backup_restore(input: PathBuf, target: PathBuf) -> Result<()> {
|
fn cmd_backup_restore(input: PathBuf, target: PathBuf) -> Result<()> {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use relicario_core::backup;
|
use relicario_core::backup;
|
||||||
|
use relicario_core::{ItemId, AttachmentId};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
let target = if target.is_absolute() {
|
let target = if target.is_absolute() {
|
||||||
@@ -1634,9 +1635,18 @@ fn cmd_backup_restore(input: PathBuf, target: PathBuf) -> Result<()> {
|
|||||||
fs::write(target.join("settings.enc"), &unpacked.settings_enc)?;
|
fs::write(target.join("settings.enc"), &unpacked.settings_enc)?;
|
||||||
|
|
||||||
for item in &unpacked.items {
|
for item in &unpacked.items {
|
||||||
|
let item_id = ItemId(item.id.clone());
|
||||||
|
if !item_id.is_valid() {
|
||||||
|
anyhow::bail!("invalid item ID in backup: {} (path traversal blocked)", item.id);
|
||||||
|
}
|
||||||
fs::write(target.join("items").join(format!("{}.enc", item.id)), &item.ciphertext)?;
|
fs::write(target.join("items").join(format!("{}.enc", item.id)), &item.ciphertext)?;
|
||||||
}
|
}
|
||||||
for a in &unpacked.attachments {
|
for a in &unpacked.attachments {
|
||||||
|
let item_id = ItemId(a.item_id.clone());
|
||||||
|
let att_id = AttachmentId(a.attachment_id.clone());
|
||||||
|
if !item_id.is_valid() || !att_id.is_valid() {
|
||||||
|
anyhow::bail!("invalid attachment ID in backup (path traversal blocked)");
|
||||||
|
}
|
||||||
let dir = target.join("attachments").join(&a.item_id);
|
let dir = target.join("attachments").join(&a.item_id);
|
||||||
fs::create_dir_all(&dir)?;
|
fs::create_dir_all(&dir)?;
|
||||||
fs::write(dir.join(format!("{}.enc", a.attachment_id)), &a.ciphertext)?;
|
fs::write(dir.join(format!("{}.enc", a.attachment_id)), &a.ciphertext)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user