skilllite_core/
path_validation.rs1use crate::error::PathValidationError;
6use std::path::{Path, PathBuf};
7
8pub fn get_allowed_root() -> Result<PathBuf, PathValidationError> {
10 let allowed_root = crate::config::PathsConfig::from_env()
11 .skills_root
12 .map(PathBuf::from)
13 .unwrap_or_else(|| std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")));
14 allowed_root
15 .canonicalize()
16 .map_err(PathValidationError::InvalidRoot)
17}
18
19pub fn validate_path_under_root(
21 path: &str,
22 path_type: &str,
23) -> Result<PathBuf, PathValidationError> {
24 let allowed_root = get_allowed_root()?;
25 let input = Path::new(path);
26 let full = if input.is_absolute() {
27 input.to_path_buf()
28 } else {
29 allowed_root.join(input)
30 };
31 let canonical = full
32 .canonicalize()
33 .map_err(|_| PathValidationError::NotFound {
34 path_type: path_type.to_string(),
35 path: path.to_string(),
36 })?;
37 if !canonical.starts_with(&allowed_root) {
38 return Err(PathValidationError::PathEscape {
39 path_type: path_type.to_string(),
40 path: path.to_string(),
41 });
42 }
43 Ok(canonical)
44}
45
46pub fn validate_skill_path(skill_dir: &str) -> Result<PathBuf, PathValidationError> {
48 validate_path_under_root(skill_dir, "Skill path")
49}