* [PATCH proxmox-backup v3] fix #5247: relative paths in exclude patterns.
@ 2026-04-28 8:06 Manuel Federanko
2026-04-28 12:41 ` Wolfgang Bumiller
0 siblings, 1 reply; 2+ messages in thread
From: Manuel Federanko @ 2026-04-28 8:06 UTC (permalink / raw)
To: pbs-devel
Patterns which start with ./ or for that matter contain /../ or similar
constructs will never match, since they get compared to sanitized paths
from directory traversal, sanitize those patterns too. Implement this
for both .pxarexclude files and the --exclude command line option. Log
a warning if a path was sanitized.
Signed-off-by: Manuel Federanko <m.federanko@proxmox.com>
Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=5247
---
changed since v2:
- log a warning for the cli option and the exclude files
- simplify trailing slash detection
changed since v1:
- inline normalize_lexically helper
- bump log level from info to warn
pbs-client/src/pxar/create.rs | 14 +++++++++++++-
pbs-client/src/pxar/tools.rs | 29 +++++++++++++++++++++++++++++
proxmox-backup-client/src/main.rs | 16 ++++++++++++++--
3 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/pbs-client/src/pxar/create.rs b/pbs-client/src/pxar/create.rs
index 70b858092..b8fc94ab6 100644
--- a/pbs-client/src/pxar/create.rs
+++ b/pbs-client/src/pxar/create.rs
@@ -589,7 +589,19 @@ impl Archiver {
(line, MatchType::Exclude, false)
};
- match MatchEntry::parse_pattern(line, PatternFlag::PATH_NAME, mode) {
+ let line = OsStr::from_bytes(line);
+ let line_normalized = crate::pxar::tools::normalize_lexically(line);
+ if line_normalized.as_os_str() != line {
+ warn!(
+ "Sanitized exclude pattern. Exclude patterns are relative to the current backup root, \
+ not the current working directory and should not contain '.' or '..' as path segments"
+ );
+ }
+ match MatchEntry::parse_pattern(
+ line_normalized.as_path().as_os_str().as_bytes(),
+ PatternFlag::PATH_NAME,
+ mode,
+ ) {
Ok(pattern) => {
if anchored {
self.patterns.push(pattern.add_flags(MatchFlag::ANCHORED));
diff --git a/pbs-client/src/pxar/tools.rs b/pbs-client/src/pxar/tools.rs
index 475c08ad3..28f66801b 100644
--- a/pbs-client/src/pxar/tools.rs
+++ b/pbs-client/src/pxar/tools.rs
@@ -76,6 +76,35 @@ fn assert_single_path_component_do(path: &Path) -> Result<(), Error> {
Ok(())
}
+pub fn normalize_lexically<S: AsRef<OsStr> + ?Sized>(path: &S) -> PathBuf {
+ // FIXME: Once std::path::normalize_lexically is stabilized we can
+ // switch to that
+ use std::path::Component;
+
+ let path = Path::new(path);
+ let has_trailing_slash = path
+ .as_os_str()
+ .as_encoded_bytes()
+ .ends_with(std::path::MAIN_SEPARATOR_STR.as_bytes());
+ let mut new = PathBuf::new();
+ let iter = path.components();
+ for component in iter {
+ match component {
+ Component::RootDir => new.push(Component::RootDir),
+ Component::Prefix(p) => new.push(Component::Prefix(p)),
+ Component::CurDir => continue,
+ Component::ParentDir => {
+ new.pop();
+ }
+ Component::Normal(n) => new.push(n),
+ };
+ }
+ if has_trailing_slash {
+ new.push("");
+ }
+ new
+}
+
#[rustfmt::skip]
fn symbolic_mode(c: u64, special: bool, special_x: u8, special_no_x: u8) -> [u8; 3] {
[
diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index a1533b79b..fd8d6a61a 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -842,9 +842,21 @@ async fn create_backup(
let entry = entry
.as_str()
.ok_or_else(|| format_err!("Invalid pattern string slice"))?;
+ let entry_normalized = pbs_client::pxar::tools::normalize_lexically(entry);
+ if entry_normalized.as_os_str() != entry {
+ log::warn!(
+ "Sanitized exclude pattern. Exclude patterns are relative to backup root, \
+ not the current working directory and should not contain '.' or '..' as path \
+ segments"
+ );
+ }
pattern_list.push(
- MatchEntry::parse_pattern(entry, PatternFlag::PATH_NAME, MatchType::Exclude)
- .map_err(|err| format_err!("invalid exclude pattern entry: {}", err))?,
+ MatchEntry::parse_pattern(
+ entry_normalized.as_os_str().as_encoded_bytes(),
+ PatternFlag::PATH_NAME,
+ MatchType::Exclude,
+ )
+ .map_err(|err| format_err!("invalid exclude pattern entry: {}", err))?,
);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-04-28 12:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 8:06 [PATCH proxmox-backup v3] fix #5247: relative paths in exclude patterns Manuel Federanko
2026-04-28 12:41 ` Wolfgang Bumiller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.