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
Feature | Path/PathBuf | StrictPath | VirtualPath |
---|---|---|---|
Security | None 💥 | Validates & rejects ✅ | Clamps any input ✅ |
Escape attempts | ../../../etc → System breach | ../../../etc → Error | ../../../etc → /etc (safely clamped) |
Symlink escapes | link -> /etc → System breach | link -> /etc → Error | link -> /etc → /etc (clamped to boundary) |
Display | System path | System path | Virtual rooted path (/file.txt ) |
Use case | Known-safe, controlled paths | Security boundaries, detect attacks | Multi-tenant isolation, sandboxes |
Feature needed | Always available | Always available | Requires 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
- Best Practices: Full Decision Matrix - 15+ scenarios with detailed guidance
- Security Philosophy: Detect vs Contain - Deep dive into the fundamental distinction
- Real-World Examples - Complete, production-ready implementations
- Tutorial: Stage 5 - Virtual Paths - Understanding VirtualPath semantics