Crate strict_path

Crate strict_path 

Source
Expand description

Β§strict-path

Strictly enforce path boundaries to prevent directory traversal attacks.

This crate performs full normalization/canonicalization and boundary enforcement with:

  • Safe symlink/junction handling (including cycle detection)
  • Windows-specific quirks (8.3 short names, UNC and verbatim prefixes, ADS)
  • Robust Unicode normalization and mixed-separator handling across platforms
  • Canonicalized path proofs encoded in the type system

If a StrictPath<Marker> value exists, it is already proven to be inside its designated boundary by construction β€” not by best-effort string checks.

πŸ“š Complete Guide & Examples | πŸ“– API Reference

Β§Quick Start

let temp = tempfile::tempdir()?;
let safe: StrictPath = StrictPath::with_boundary(temp.path())?
    .strict_join("users/alice.txt")?;  // Validated, stays inside boundary

safe.create_parent_dir_all()?;
safe.write("hello")?;
safe.metadata()?;
safe.remove_file()?;

Β§Core Types

  • StrictPath β€” The fundamental security primitive. Every StrictPath is mathematically proven to be within its designated boundary via canonicalization and type-level guarantees.
  • PathBoundary β€” Creates and validates StrictPath instances from external input.
  • VirtualPath (feature virtual-path) β€” Extends StrictPath with user-friendly virtual root semantics (treating the boundary as β€œ/”).
  • VirtualRoot (feature virtual-path) β€” Creates VirtualPath instances with containment semantics.

β†’ Read the security methodology

Β§When to Use Which Type

StrictPath (default) β€” Detect & reject path escapes (90% of use cases):

  • Archive extraction, file uploads, config loading
  • Returns Err(PathEscapesBoundary) on escape attempts

VirtualPath (opt-in) β€” Contain & redirect path escapes (10% of use cases):

  • Multi-tenant systems, malware sandboxes, security research
  • Silently clamps escapes within the virtual boundary
  • Requires features = ["virtual-path"] in Cargo.toml

β†’ Read the detailed comparison

Β§Type-System Guarantees

Use marker types to encode policy directly in your APIs:

struct PublicAssets;
struct UserUploads;

let assets = PathBoundary::<PublicAssets>::try_new("./assets")?;
let uploads = PathBoundary::<UserUploads>::try_new("./uploads")?;

let css: StrictPath<PublicAssets> = assets.strict_join("style.css")?;
let avatar: StrictPath<UserUploads> = uploads.strict_join("avatar.jpg")?;

fn serve_public_asset(file: &StrictPath<PublicAssets>) { /* ... */ }

serve_public_asset(&css);       // βœ… OK
// serve_public_asset(&avatar); // ❌ Compile error (wrong marker)

Β§Security Foundation

Built on soft-canonicalize, this crate protects against:

  • CVE-2025-8088 (NTFS ADS path traversal)
  • CVE-2022-21658 (TOCTOU attacks)
  • CVE-2019-9855, CVE-2020-12279 (Windows 8.3 short names)
  • Path traversal, symlink attacks, Unicode normalization bypasses, race conditions

β†’ Read attack surface analysis

Β§Interop with External APIs

Use .interop_path() to pass paths to external APIs expecting AsRef<Path>:

let restriction: PathBoundary = PathBoundary::try_new_create("./safe")?;
let jp = restriction.strict_join("file.txt")?;

// βœ… Preferred: borrow as &OsStr (implements AsRef<Path>)
external_api(jp.interop_path());

// Escape hatches (use sparingly):
let owned: std::path::PathBuf = jp.clone().unstrict();

β†’ Read the anti-patterns guide

Β§Critical Anti-Patterns

  • NEVER wrap our types in Path::new() or PathBuf::from() β€” defeats all security
  • NEVER use std Path::join on leaked paths β€” can escape boundaries
  • Use .interop_path() directly for external APIs β€” no need for .as_ref()
  • Use proper display methods β€” .strictpath_display() not .interop_path().to_string_lossy()

β†’ See full anti-patterns list

Β§Feature Flags

  • virtual-path β€” Enables VirtualRoot/VirtualPath for containment scenarios
  • serde β€” Serialization support (deserialization requires context; see serde_ext module)
  • dirs β€” OS directory discovery (PathBoundary::from_home_dir(), etc.)
  • tempfile β€” RAII constructors for temporary boundaries
  • app-path β€” Application-specific directory patterns with env var overrides

β†’ Read the getting started guide

Β§Additional Resources

Re-exportsΒ§

pub use error::StrictPathError;
pub use path::strict_path::StrictPath;
pub use validator::path_boundary::PathBoundary;
pub use path::virtual_path::VirtualPath;
pub use validator::virtual_root::VirtualRoot;

ModulesΒ§

error
SUMMARY: Define error types and helpers for boundary creation and strict/virtual path validation.
path
serde_ext
Serde helpers and notes.
validator

Type AliasesΒ§

Result
Result type alias for this crate’s operations.