greentic-dev 0.6.0-dev.25061653111

Developer CLI and local tooling for Greentic flows, packs, and components
Documentation
use std::path::{Path, PathBuf};

use anyhow::{Context, Result};

/// Normalize a user-supplied path and ensure it stays within an allowed root.
/// Reject absolute paths and any that escape via `..`.
pub fn normalize_under_root(root: &Path, candidate: &Path) -> Result<PathBuf> {
    let canonical_root = root
        .canonicalize()
        .with_context(|| format!("failed to canonicalize root {}", root.display()))?;

    let resolved = if candidate.is_absolute() {
        candidate.to_path_buf()
    } else {
        canonical_root.join(candidate)
    };

    let canon = resolved
        .canonicalize()
        .with_context(|| format!("failed to canonicalize {}", resolved.display()))?;

    if !canon.starts_with(&canonical_root) {
        anyhow::bail!(
            "path escapes root ({}): {}",
            canonical_root.display(),
            canon.display()
        );
    }

    Ok(canon)
}