Improve path cleaning and tests

This commit is contained in:
Jake Howard 2024-02-16 18:12:53 +00:00
parent ec09ec1b78
commit fd138ac2f7
No known key found for this signature in database
GPG Key ID: 57AFB45680EDD477
3 changed files with 20 additions and 8 deletions

7
Cargo.lock generated
View File

@ -1938,6 +1938,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "path-clean"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef"
[[package]]
name = "pathdiff"
version = "0.2.1"
@ -2425,6 +2431,7 @@ dependencies = [
"infer",
"lazy-regex",
"mime",
"path-clean",
"petname",
"rand",
"regex",

View File

@ -48,6 +48,7 @@ tokio = { version = "1.35.1", optional = true }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
uts2ts = "0.4.1"
path-clean = "1.0.1"
[dependencies.config]
version = "0.13.4"

View File

@ -2,6 +2,7 @@ use crate::paste::PasteType;
use actix_web::{error, Error as ActixError};
use glob::glob;
use lazy_regex::{lazy_regex, Lazy, Regex};
use path_clean::PathClean;
use ring::digest::{Context, SHA256};
use std::fmt::Write;
use std::io::{BufReader, Read};
@ -108,15 +109,12 @@ pub fn sha256_digest<R: Read>(input: R) -> Result<String, ActixError> {
})?)
}
/// Joins the paths whilst ensuring the path doesn't drastically change
/// Joins the paths whilst ensuring the path doesn't drastically change.
/// `base` is assumed to be a trusted value.
pub fn safe_path_join<B: AsRef<Path>, P: AsRef<Path>>(base: B, part: P) -> Option<PathBuf> {
if part.as_ref().to_string_lossy().contains("..") {
return None;
}
let new_path = base.as_ref().join(part).clean();
let new_path = base.as_ref().join(part);
if !new_path.starts_with(base) {
if !new_path.starts_with(base.as_ref().clean()) {
return None;
}
@ -188,11 +186,17 @@ mod tests {
#[test]
fn test_safe_join_path() {
assert!(safe_path_join("/foo", "bar").is_some());
assert_eq!(safe_path_join("/foo", "bar"), Some("/foo/bar".into()));
assert_eq!(safe_path_join("/", "bar"), Some("/bar".into()));
assert_eq!(safe_path_join("/", "././bar"), Some("/bar".into()));
assert_eq!(
safe_path_join("/foo/bar", "baz/"),
Some("/foo/bar/baz/".into())
);
assert_eq!(
safe_path_join("/foo/bar/../", "baz"),
Some("/foo/baz".into())
);
assert!(safe_path_join("/foo", "/foobar").is_none());
assert!(safe_path_join("/foo", "/bar").is_none());