Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Examples by Mode

Quick visual guide: When to use StrictPath vs VirtualPath vs Path/PathBuf

This page provides quick, at-a-glance examples showing when to use each path type. For detailed guidance and decision matrices, see Best Practices: Security Philosophy.


🌐 VirtualPath - User Sandboxes & Multi-Tenant Systems

Philosophy: "Let things try to escape, but silently contain them"

Use when: Path escapes are expected but must be controlled

Archive Extraction (Safe Sandboxing)

#![allow(unused)]
fn main() {
use strict_path::VirtualPath;

// Extract ZIP files - hostile names get clamped, not rejected
let extract_root = VirtualPath::with_root_create("./extracted")?;

for entry_name in zip_entries {
    // "../../../etc/passwd" → "/etc/passwd" (safely clamped)
    let safe_path = extract_root.virtual_join(entry_name)?;
    safe_path.create_parent_dir_all()?;
    safe_path.write(entry.data())?; // Always safe within boundary
}
}

Multi-Tenant Cloud Storage

#![allow(unused)]
fn main() {
use strict_path::VirtualPath;

// Each user gets their own isolated filesystem view
let user_storage = VirtualPath::with_root_create(format!("storage/user_{user_id}"))?;

// User sees: "/documents/report.pdf"
// Actually stored: "./storage/user_42/documents/report.pdf"
let user_file = user_storage.virtual_join("documents/report.pdf")?;
user_file.write(uploaded_data)?;

// Show user-friendly paths
println!("Saved: {}", user_file.virtualpath_display()); // "/documents/report.pdf"
}

Key behavior:

  • ✅ Escape attempts are silently clamped to stay within boundary
  • ✅ Users see clean rooted paths (/file.txt) hiding real system structure
  • ✅ Symlinks to absolute paths are clamped to virtual root
  • 🎯 Perfect for: Multi-tenant systems, sandboxes, user isolation

Requires feature: virtual-path in Cargo.toml


⚔️ StrictPath - Security Boundaries & System Resources

Philosophy: "If something tries to escape, I want to know about it"

Use when: Path escapes indicate malicious intent

LLM Agent File Operations

#![allow(unused)]
fn main() {
use strict_path::PathBoundary;

// LLM generates file operations - validate everything
let workspace = PathBoundary::try_new_create("./agent_workspace")?;

let ai_request = llm.generate_filename(); // Could be ANYTHING
match workspace.strict_join(ai_request) {
    Ok(safe_path) => {
        safe_path.write(&ai_content)?;
        println!("✅ Saved: {}", safe_path.strictpath_display());
    },
    Err(e) => {
        eprintln!("🚨 Attack blocked: {e}");
        // Log the attack, alert security team
    }
}
}

File Upload Validation

#![allow(unused)]
fn main() {
use strict_path::PathBoundary;

struct UserUploads;

// Validate user-provided filenames
fn handle_upload(
    uploads_dir: &PathBoundary<UserUploads>,
    filename: &str,
    data: &[u8]
) -> Result<(), Box<dyn std::error::Error>> {
    // Reject malicious filenames like "../../../etc/passwd"
    let safe_file = uploads_dir.strict_join(filename)?; // Returns Err on escape
    safe_file.write(data)?;
    Ok(())
}
}

Configuration File Loading

#![allow(unused)]
fn main() {
use strict_path::PathBoundary;

// Load config files - reject traversal attempts
let config_dir = PathBoundary::try_new("./config")?;

match config_dir.strict_join(user_selected_config) {
    Ok(config_file) => {
        let content = config_file.read_to_string()?;
        // Parse and use safely
    },
    Err(_) => {
        // User tried to load "../../../etc/passwd" - reject!
        return Err("Invalid config file path");
    }
}
}

Key behavior:

  • ✅ Escape attempts return Err(PathEscapesBoundary)
  • ✅ Application can detect attacks, log, alert, and reject
  • ✅ Symlinks outside boundary return Error
  • 🎯 Perfect for: Archive extraction, file uploads, config loading, system resources

No feature required - always available


🔓 Path/PathBuf - Controlled/Known Paths

Philosophy: "I created this path, I control it"

Use when: You control the path source (hardcoded, generated by your code)

Application-Generated Paths

#![allow(unused)]
fn main() {
use std::path::{Path, PathBuf};

// ✅ SAFE - You control the timestamp
let log_file = PathBuf::from(format!("logs/app-{timestamp}.log"));
std::fs::write(&log_file, log_data)?;

// ✅ SAFE - Hardcoded path
let schema_file = Path::new("config/db-schema.sql");
let schema = std::fs::read_to_string(schema_file)?;

// ✅ SAFE - Environment variable from trusted source
let config_dir = std::env::var("APP_CONFIG_DIR")?;
let config = PathBuf::from(config_dir).join("settings.toml");
}

❌ NEVER with External Input

#![allow(unused)]
fn main() {
use std::path::Path;

// 🚨 DISASTER - User input directly to Path
let user_file = Path::new(user_input); // user_input = "../../../etc/passwd"
std::fs::write(user_file, data)?; // System compromised!

// ✅ CORRECT - Validate first with StrictPath
let uploads = PathBoundary::try_new("uploads")?;
let safe_file = uploads.strict_join(user_input)?; // Attack rejected
safe_file.write(data)?;
}

Key behavior:

  • ⚠️ No validation - trusts you completely
  • ⚠️ Can escape anywhere on the filesystem
  • 🎯 Perfect for: Hardcoded paths, app-generated filenames, trusted environment variables

Golden Rule: If you didn't create the path yourself, validate it first with StrictPath or VirtualPath!


📊 Quick Comparison Table

FeaturePath/PathBufStrictPathVirtualPath
SecurityNone 💥Validates & rejects ✅Clamps any input ✅
Escape attempts../../../etcSystem breach../../../etcError../../../etc/etc (safely clamped)
Symlink escapeslink -> /etcSystem breachlink -> /etcErrorlink -> /etc/etc (clamped to boundary)
DisplaySystem pathSystem pathVirtual rooted path (/file.txt)
Use caseKnown-safe, controlled pathsSecurity boundaries, detect attacksMulti-tenant isolation, sandboxes
Feature neededAlways availableAlways availableRequires virtual-path feature

🎯 Decision Flowchart

Is the path from external/untrusted input?
│
├─ NO (hardcoded/app-generated) ──> Path/PathBuf
│
└─ YES (user/config/LLM/archive) ──> Validate first!
    │
    ├─ Need to DETECT escape attempts? ──> StrictPath
    │   (file uploads, config, LLM agents)
    │
    └─ Need to CONTAIN escape attempts? ──> VirtualPath
        (multi-tenant, sandboxes, user isolation)

📚 Learn More