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: Chapter 5 - Virtual Paths - Understanding VirtualPath semantics