fix(fs): do not parse relative paths with a colon as URLs (#3632)

In plugins/fs/src/file_path.rs SafeFilePath::from_str, any string that
parsed as a URL with a scheme of 2+ characters was a URL, so a relative
path such as `notes:2024.txt` became a cannot-be-a-base URL and failed
with InvalidPathUrl.

Cannot-be-a-base URLs are now parsed as paths. The scheme-agnostic
url.to_file_path() stays: its result is scope checked (not a bypass).
Unit test for the parser; e2e spec writes and reads such a file (not on
Windows, where `:` is not allowed in file names).
This commit is contained in:
Lucas Fernandes Nogueira authored and GitHub committed 2026-10-10 16:06:02 -03:00
1 parent b6f39cc51c
commit 3b19ca096c
3 files changed
+65 -1

No files matched your search

+39 -1
View File
@@ -203,7 +203,9 @@ impl FromStr for SafeFilePath {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
if let Ok(url) = url::Url::from_str(s)
&& url.scheme().len() != 1
// single letter schemes are Windows drive letters, and URLs that cannot be a base
// (no `//` nor `/` after the scheme) are relative paths such as `notes:2024.txt`
&& url.scheme().len() != 1 && !url.cannot_be_a_base()
{
return Ok(Self::Url(url));
}
@@ -306,3 +308,39 @@ impl TryFrom<FilePath> for SafeFilePath {
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::SafeFilePath;
#[test]
fn safe_file_path_from_str() {
for url in [
"file:///C:/Users",
"file:///home/user/file.txt",
"content://com.android.providers/document/1",
"asset://localhost/file.txt",
] {
assert!(
matches!(SafeFilePath::from_str(url), Ok(SafeFilePath::Url(_))),
"{url}"
);
}
for path in [
"C:/Users",
"C:\\Users",
"notes:2024.txt",
"ab:c",
"dir/file.txt",
"/home/user/file.txt",
] {
assert!(
matches!(SafeFilePath::from_str(path), Ok(SafeFilePath::Path(_))),
"{path}"
);
}
}
}