{"record":{"id":"73df06cdb09c8743","repo":"ruvnet/RuView","slug":"refusing-to-use-data-dir-with-traversal-compo","errorCode":null,"errorMessage":"refusing to use data dir with `..` traversal component: {raw}","messagePattern":"refusing to use data dir with `\\.\\.` traversal component: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"v2/crates/wifi-densepose-pointcloud/src/training.rs","lineNumber":24,"sourceCode":"//! 2. **CSI occupancy training**: capture CSI with known occupancy ground truth →\n//!    train the tomography weights for this room geometry\n//! 3. **Brain integration**: store spatial observations as brain memories for\n//!    DPO training — \"this depth estimate was correct\" vs \"this was wrong\"\n\nuse crate::fusion::OccupancyVolume;\nuse anyhow::{anyhow, Result};\nuse serde::{Deserialize, Serialize};\nuse std::path::{Path, PathBuf};\n\n/// Reject a user-supplied path that contains `..` components (path traversal\n/// attempt) and return a normalised [`PathBuf`]. We only reject `..`; other\n/// components (including relative prefixes and `~`) are accepted verbatim —\n/// the caller is responsible for tilde expansion if needed.\npub fn sanitize_data_path(raw: &str) -> Result<PathBuf> {\n    let p = PathBuf::from(raw);\n    for comp in p.components() {\n        if matches!(comp, std::path::Component::ParentDir) {\n            return Err(anyhow!(\n                \"refusing to use data dir with `..` traversal component: {raw}\"\n            ));\n        }\n    }\n    Ok(p)\n}\n\n/// Ensure `child` (after joining to `base`) stays inside the canonicalised\n/// `base` directory. Returns the canonical child path on success. Used by\n/// every filesystem write site in this module to prevent path-traversal\n/// through user-supplied names.\nfn safe_join(base: &Path, child: &str) -> Result<PathBuf> {\n    // Reject absolute children and any `..` components up front.\n    let child_path = Path::new(child);\n    if child_path.is_absolute() {\n        return Err(anyhow!(\"child path must be relative: {child}\"));\n    }\n    for comp in child_path.components() {","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/v2/crates/wifi-densepose-pointcloud/src/training.rs#L6-L42","documentation":"`sanitize_data_path` is the explicit path-traversal guard applied to every user-supplied `--data-dir` before a `TrainingSession` is created: it walks the path's components and refuses the value outright if any component is `..` (ParentDir). This is an intentional security refusal for CLI/API input, not an incidental failure, and the message says so.","triggerScenarios":"`--data-dir ../outside`; `--data-dir captures/../../tmp/evil`; any caller that concatenates untrusted fragments into the data dir string and happens to embed `..`.","commonSituations":"Automation passing `$HOME/../shared`; an HTTP API reusing this crate whose clients send relative parent references; config values authored on a different machine with `..` shortcuts.","solutions":["Resolve the path first (`realpath -m ../shared`) and pass the resulting absolute path, which contains no `..` components.","If a parent directory is genuinely intended, name it explicitly by its canonical absolute location.","Audit callers that build the string from untrusted input before it reaches `TrainingSession::new`."],"exampleFix":"# before\nruview-train --data-dir ../runs/session7\n# after\nruview-train --data-dir /home/op/runs/session7","handlingStrategy":"validation","validationCode":"fn contains_parent_dir(raw: &str) -> bool {\n    std::path::Path::new(raw)\n        .components()\n        .any(|c| matches!(c, std::path::Component::ParentDir))\n}\n\nfn sanitized(raw: &str) -> Option<std::path::PathBuf> {\n    (!contains_parent_dir(raw)).then(|| std::path::PathBuf::from(raw))\n}","typeGuard":"fn is_sanitizable_data_dir(raw: &str) -> bool {\n    !std::path::Path::new(raw)\n        .components()\n        .any(|c| matches!(c, std::path::Component::ParentDir))\n}","tryCatchPattern":null,"preventionTips":["Canonicalize user-supplied paths (`realpath -m`, `std::fs::canonicalize` after creation) before passing them in.","Treat this error as a security signal from the API — never work around it by string surgery on the input.","In HTTP front-ends, reject `..` before the value ever reaches TrainingSession::new."],"tags":["rust","security","path-traversal","validation","filesystem"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}