strict-path 0.1.0-beta.2

Stop path attacks before they happen. This crate makes sure file paths can't escape where you want them to go
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# strict-path


[![Crates.io](https://img.shields.io/crates/v/strict-path.svg)](https://crates.io/crates/strict-path)
[![Documentation](https://docs.rs/strict-path/badge.svg)](https://docs.rs/strict-path)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](https://github.com/DK26/strict-path-rs#license)
[![CI](https://github.com/DK26/strict-path-rs/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/DK26/strict-path-rs/actions/workflows/ci.yml)
[![Security Audit](https://github.com/DK26/strict-path-rs/actions/workflows/audit.yml/badge.svg?branch=main)](https://github.com/DK26/strict-path-rs/actions/workflows/audit.yml)
[![Type-State Police](https://img.shields.io/badge/protected%20by-Type--State%20Police-blue.svg)](https://github.com/DK26/strict-path-rs)

📚 **[Complete Guide & Examples]https://dk26.github.io/strict-path-rs/** | 📖 **[API Docs]https://docs.rs/strict-path**
| 🧭 **[Choosing Canonicalized vs Lexical Solution](https://dk26.github.io/strict-path-rs/ergonomics/choosing_canonicalized_vs_lexical_solution.html)**

Stop path attacks before they happen. This crate makes sure file paths can't escape where you want them to go.

> **Note:** Our doc comments and [LLM_API_REFERENCE.md]https://github.com/DK26/strict-path-rs/blob/main/LLM_API_REFERENCE.md are designed for LLMs with function calling—so an AI can use this crate safely and correctly for file and path operations. 
> 
> ### 🤖 LLM agent prompt (copy/paste)

> 
> ``` 
> Fetch and follow this reference (single source of truth):
> https://github.com/DK26/strict-path-rs/blob/main/LLM_API_REFERENCE.md
> ```

## What this crate does


- **Blocks path attacks**: Turn dangerous paths like `../../../etc/passwd` into either safe paths or clear errors
- **Handles the obscure edge cases**: Windows 8.3 short names, symlink cycles, NTFS streams, UNC paths, encoding tricks—the stuff you'd never think to test for
- **Compiler-enforced guarantees**: `StrictPath<Marker>` types prove at compile-time that paths stay within boundaries
- **Enables authorization architectures**: When you design markers to require authorization for construction, the compiler mathematically proves that any use of those markers went through authorization first
- **Safe builtin I/O operations**: Complete filesystem API (read, write, create_dir, metadata, rename, copy, etc.) that eliminates the need for `.interop_path()` calls in routine operations
- **Two modes to choose from**:
  - **StrictPath**: Rejects bad paths with an error (good for APIs and system access guarantees)  
  - **VirtualPath**: Clamps bad paths to safe ones (good for simulating virtual user spaces, extracting archives in isolation, etc.)
- **Built on battle-tested foundations**: Uses `soft-canonicalize` which has been validated against 19+ real-world path-related CVEs
- **Easy to use**: Drop-in replacement for standard file operations, same return values
- **Works everywhere**: Handles platform differences so you don't have to

## What this crate is NOT


- **Not just string checking**: We actually follow filesystem links and resolve paths properly
- **Not a simple wrapper**: Built from the ground up for security, not a thin layer over existing types  
- **Not just removing ".."**: Handles symlinks, Windows short names, and other escape tricks
- **Not a permission system**: Works with your existing file permissions, doesn't replace them
- **Not a sandbox**: We secure paths at the path level, not at the OS level

## Quick start


> "If you can read this, you passed the PathBoundary checkpoint."

```rust
use strict_path::{StrictPath, VirtualPath};

// Strict system path rooted at ./data
let alice_file = StrictPath::with_boundary("./data")?
    .strict_join("users/alice.txt")?;

// Virtual view rooted at ./public (displays as "/...")
let logo_file = VirtualPath::with_root("./public")?
    .virtual_join("assets/logo.png")?;
```

> 📖 **New to strict-path?** Start with the **[Tutorial: Stage 1 - The Basic Promise →]https://dk26.github.io/strict-path-rs/tutorial/stage1_basic_promise.html** to learn the core concepts step-by-step.

> *The Type-State Police have set up PathBoundary checkpoints*  
> *because your LLM is running wild*

## 🚨 **One Line of Code Away from Disaster**


> "One does not simply walk into /etc/passwd."

```rust
// ❌ This single line can destroy your server
std::fs::write(user_input, data)?;  // user_input = "../../../etc/passwd"

// ✅ This single line makes it mathematically impossible  
StrictPath::with_boundary("uploads")?
    .strict_join(user_input)?
    .write(data)?;
```

**The Reality**: Every web server, LLM agent, and file processor faces the same vulnerability. One unvalidated path from user input, config files, or AI responses can grant attackers full filesystem access.

**The Solution**: Comprehensive path security with mathematical guarantees — including symlink safety, Windows path quirks, and encoding pitfalls — not just string checks.

> Analogy: `StrictPath` is to paths what a prepared statement is to SQL.
>
> - The boundary/root you create is like preparing a statement: it encodes the policy (what’s allowed).
> - The untrusted filename or path segment is like a bound parameter: it’s validated/clamped safely via `strict_join`/`virtual_join`.
> - The API makes injection attempts inert: hostile inputs can’t escape the boundary, just like SQL parameters can’t change the query.

## 🛡️ **How We Solve The Entire Problem Class**


> "Symlinks: the ninja assassins of your filesystem."

**strict-path isn't just validation—it's a complete solution to path security that handles edge cases you'd never think to check:**

1. **🔧 [`soft-canonicalize`]https://github.com/DK26/soft-canonicalize-rs foundation**: Heavily tested against 19+ globally known path-related CVEs—the battle-tested work you don't want to reimplement
2. **🚫 Advanced pattern detection**: Catches encoding tricks, Windows 8.3 short names (`PROGRA~1`), UNC paths, NTFS Alternate Data Streams, and malformed inputs that simple string checks miss
3. **🔗 Full canonicalization pipeline**: Resolves symlinks, junctions, `.` and `..` components, and handles filesystem race conditions—the complex stuff that's easy to get wrong
4. **📐 Mathematical correctness**: Rust's type system provides compile-time proof of path boundaries
5. **🔐 Authorization architecture**: Enable compile-time authorization guarantees through marker types
6. **👁️ Explicit operations**: Method names like `strict_join()` make security violations visible in code review
7. **🛡️ Safe builtin I/O operations**: Complete filesystem API that reduces the need for `.interop_path()` calls in routine operations
8. **🤖 LLM-aware design**: Built specifically for untrusted AI-generated paths and modern threat models
9. **⚡ Dual protection modes**: Choose **Strict** (validate & reject) or **Virtual** (clamp & contain) based on your use case
10. **🏗️ Battle-tested architecture**: Prototyped and refined across real-world production systems
11. **🎯 Zero-allocation interop**: Seamless integration with existing `std::path` ecosystems when needed

> 📖 **[Read our complete security methodology →]https://dk26.github.io/strict-path-rs/security_methodology.html**  
> *Deep dive into our 7-layer security approach: from CVE research to comprehensive testing*

### **Recently Addressed CVEs**

- **CVE-2025-8088** (WinRAR ADS): NTFS Alternate Data Stream traversal prevention
- **CVE-2022-21658** (TOCTOU): Race condition protection during path resolution  
- **CVE-2019-9855, CVE-2020-12279, CVE-2017-17793**: Windows 8.3 short name vulnerabilities

**Your security audit becomes**: *"We use strict-path for comprehensive path security."* ✅

## **Get Secure in 30 Seconds**


```toml
[dependencies]
strict-path = "0.1.0-beta.2"
```

```rust
use strict_path::StrictPath;

// 1. Create a boundary (your security perimeter)
//    Use sugar for simple flows; switch to PathBoundary when you need reusable policy
let safe_root = StrictPath::with_boundary("uploads")?;

// 2. ANY external input becomes safe
let safe_path = safe_root.strict_join(dangerous_user_input)?;  // Attack = Error

// 3. Use normal file operations - guaranteed secure
safe_path.write(file_data)?;
let info = safe_path.metadata()?; // Inspect filesystem metadata when needed
safe_path.remove_file()?; // Remove when cleanup is required
```

**That's it.** No complex validation logic. No CVE research. No security expertise required.

## 🧬 **The Edge Cases You'd Never Think Of**


> "Security is hard because the edge cases are infinite—until now."

**What would you check for when validating a file path?** Most developers think: *"I'll block `../` and call it a day."* But real attackers use techniques you've probably never heard of:

- **Windows 8.3 short names**: `PROGRA~1``Program Files` (filesystem aliases that bypass string checks)
- **NTFS Alternate Data Streams**: `config.txt:hidden:$DATA` (secret channels in "normal" files)
- **Unicode normalization**: `..∕..∕etc∕passwd` (visually identical but different bytes)
- **Symlink time-bombs**: Links that resolve differently between validation and use (TOCTOU)
- **Mixed path separators**: `../\../etc/passwd` (exploiting parser differences)
- **UNC path shenanigans**: `\\?\C:\Windows\..\..\..\etc\passwd` (Windows extended paths)

**The reality**: You'd need months of research, testing across platforms, and deep filesystem knowledge to handle these correctly.

**Our approach**: We've already done the research. `strict-path` is built on `soft-canonicalize`, which has been battle-tested against 19+ real CVEs. You get comprehensive protection without becoming a path security expert.

## 🧠 **The Secret Weapon: `StrictPath<Marker>` Types**



> "Marker types: because your code deserves a secret identity."

**The most powerful feature** you haven't discovered yet: `StrictPath<Marker>` doesn't just prevent path attacks—the **`<Marker>` part unlocks secret superpowers** that make **wrong path usage a compile error**.

**StrictPath = Promise of path security**  
**`<Marker>` = Unlocks extra secret powers!** 

**Basic superpower**: Prevent cross-domain mix-ups forever.
**Advanced superpower**: Encode authorization requirements into the type system.

### **Level 1: Basic Domain Separation** 


```rust
use strict_path::{PathBoundary, StrictPath};

struct PublicAssets; // CSS, JS, images
struct UserUploads;  // User documents

let public_assets_dir: PathBoundary<PublicAssets> = PathBoundary::try_new("public")?;
let user_uploads_dir: PathBoundary<UserUploads> = PathBoundary::try_new("uploads")?;

let css_file: StrictPath<PublicAssets> = public_assets_dir.strict_join("style.css")?;
let user_doc: StrictPath<UserUploads> = user_uploads_dir.strict_join("report.pdf")?;

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

serve_public_asset(&css_file);    // ✅ Works
// serve_public_asset(&user_doc); // ❌ Compile error: wrong domain!
```

**The power**: Mix up user uploads with public assets? **Impossible**. The compiler catches domain violations.

> 📖 **[Tutorial: Stage 3 - Markers →]https://dk26.github.io/strict-path-rs/tutorial/stage3_markers.html** explains marker fundamentals and domain separation patterns.

### **Level 2: Authorization Architecture**


```rust
// Marker describes the user's home directory inside a shared filesystem
struct UserHome { _proof: () }

impl UserHome {
    pub fn authenticate_home_access(token: &Token) -> Result<Self, AuthError> {
        verify_token(token)?;  // Real authentication here
        Ok(UserHome { _proof: () })
    }
}

// Functions work with pre-authorized paths
fn read_home_file(path: &StrictPath<UserHome>) -> io::Result<String> {
    // Guaranteed: path is safe AND user passed authentication
    path.read_to_string()
}
```

**The power**: Access user home directories without authentication? **Impossible**. The compiler mathematically proves authorization happened first.

### **Level 3: Permission Matrix** 


```rust
use strict_path::{PathBoundary, StrictPath};

// Resource types (what) + Permission levels (how)
struct SystemFiles;
struct ReadOnly { _proof: () }
struct AdminPermission { _proof: () }

fn view_system_file(path: &StrictPath<(SystemFiles, ReadOnly)>) -> io::Result<String> {
    path.read_to_string() // Can read, but not modify
}

fn manage_system_file(path: &StrictPath<(SystemFiles, AdminPermission)>) -> io::Result<()> {
    path.write("admin changes") // Full control
}

// Authentication returns the complete tuple
let (system_access, readonly_perm) = authenticate_user(&credentials)?;
let system_files_dir: PathBoundary<SystemFiles> = PathBoundary::try_new("system")?;
let system_file: StrictPath<(SystemFiles, ReadOnly)> = 
    system_files_dir.strict_join("config.txt")?;

view_system_file(&system_file)?;    // ✅ Has ReadOnly permission  
// manage_system_file(&system_file)?; // ❌ Needs AdminPermission!
```

**The power**: Create authorization matrices at compile-time. Wrong permission level? **Impossible**. The type system enforces your security model.

### **Why This Changes Everything**


- **Zero runtime cost**: All marker logic erased at compile time
- **Refactoring safety**: Change authorization requirements → get compile errors everywhere affected  
- **Self-documenting**: Function signatures show exactly what permissions are needed
- **Impossible to bypass**: No runtime checks to forget or skip

**Bottom line**: Turn authorization bugs from "runtime disasters" into "won't compile" problems.

> 📚 **[Learn Authorization Patterns →]https://dk26.github.io/strict-path-rs/tutorial/stage4_authorization.html**: Step-by-step tutorial on encoding authorization in the type system with `change_marker()`, tuple markers, and capability-based patterns.

##  Where This Makes Sense


> "LLMs: great at generating paths, terrible at keeping secrets."

- Usefulness for LLM agents: LLMs can produce arbitrary paths; `StrictPath`/`VirtualPath` make those suggestions safe by validation (strict) or clamping (virtual) before any I/O.
- `PathBoundary`/`VirtualRoot`: When you want the compiler to enforce that a value is anchored to the initial root/boundary. Keeping the policy type separate from path values prevents helpers from “picking a root” silently. With features enabled, you also get ergonomic, policy‑aware constructors (e.g., `dirs`, `tempfile`, `app-path`).
- Marker types: Add domain context for the compiler and reviewers (e.g., `PublicAssets`, `UserUploads`). They read like documentation and prevent cross‑domain mix‑ups at compile time.

Trade‑offs you can choose explicitly:

- Zero‑trust, CVE‑aware approach: Prefer canonicalized solutions (this crate) to resolve to absolute, normalized system paths with symlink handling and platform quirks addressed. This defends against entire classes of traversal and aliasing attacks.
- Lexical approach (performance‑first, limited scope): If you’re absolutely certain there are no symlinks, junctions, mounts, or platform‑specific aliases and your inputs are already normalized, a lexical solution from another crate may be faster. Use this only when the invariants are guaranteed by your environment and tests.

## 🎯 **Decision Guide: When to Use What**


> Golden Rule: If you didn't create the path yourself, secure it first.

| Source/Input                                                                                              | Choose         | Why                                            | Notes                                            |
| --------------------------------------------------------------------------------------------------------- | -------------- | ---------------------------------------------- | ------------------------------------------------ |
| HTTP/CLI args/config/LLM/DB (untrusted segments)                                                          | `StrictPath`   | Reject attacks explicitly before I/O           | Validate with `PathBoundary.strict_join(...)`    |
| Archive contents, user uploads (user-facing UX)                                                           | `VirtualPath`  | Clamp hostile paths safely; rooted "/" display | Per-user `VirtualRoot`; use `.virtual_join(...)` |
| UI-only path display                                                                                      | `VirtualPath`  | Show clean rooted paths                        | `virtualpath_display()`; no system leakage       |
| Your own code/hardcoded paths                                                                             | `Path/PathBuf` | You control the value                          | Never for untrusted input                        |
| External APIs/webhooks/inter-service messages                                                             | `StrictPath`   | System-facing interop/I/O requires validation  | Validate on consume before touching FS           |
| *(See the [full decision matrix]https://dk26.github.io/strict-path-rs/best_practices.html in the book)* |                |                                                |                                                  |

Notes that matter:
- This isn’t StrictPath vs VirtualPath. `VirtualPath` conceptually extends `StrictPath` with a virtual "/" view; both support I/O and interop. Choose based on whether you need virtual, user-facing semantics (VirtualPath) or raw system-facing validation (StrictPath).
- Unified helpers: Prefer dimension-specific signatures. When sharing a helper across both, accept `&StrictPath<_>` and call with `vpath.as_unvirtual()` as needed.

### At‑a‑glance: API Modes


| Feature            | `Path`/`PathBuf`                            | `StrictPath`                        | `VirtualPath`                                      |
| ------------------ | ------------------------------------------- | ----------------------------------- | -------------------------------------------------- |
| **Security**       | None 💥                                      | Validates & rejects ✅               | Clamps any input ✅                                 |
| **Join safety**    | Unsafe (can escape)                         | Boundary-checked                    | Boundary-clamped                                   |
| **Example attack** | `"../../../etc/passwd"`**System breach** | `"../../../etc/passwd"`**Error** | `"../../../etc/passwd"`**`/etc/passwd`** (safe) |
| **Best for**       | Known-safe paths                            | System boundaries                   | User interfaces                                    |

📚 **Further Reading in the Complete Guide:**
- **[Tutorial Series]https://dk26.github.io/strict-path-rs/tutorial/overview.html** - 6-stage progressive guide from basics to advanced patterns
- **[Best Practices]https://dk26.github.io/strict-path-rs/best_practices.html** - Full decision matrix and design rationale
- **[Anti-Patterns]https://dk26.github.io/strict-path-rs/anti_patterns.html** - What not to do, with fixes
- **[Real-World Examples]https://dk26.github.io/strict-path-rs/examples/overview.html** - End-to-end realistic scenarios
- **[Type-System Guarantees]https://dk26.github.io/strict-path-rs/type_system_guarantees.html** - How markers prevent bugs at compile-time

## 🛡️ **Core Security Foundation**


> "StrictPath: the vault door, not just a velvet rope."

At the heart of this crate is **`StrictPath`** - the fundamental security primitive that provides our ironclad guarantee: **every `StrictPath` is mathematically proven to be within its boundary**. 

Everything in this crate builds upon `StrictPath`:
- `PathBoundary` creates and validates `StrictPath` instances
- `VirtualPath` extends `StrictPath` with user-friendly virtual root semantics  
- `VirtualRoot` provides a root context for creating `VirtualPath` instances

**The core promise:** If you have a `StrictPath<Marker>`, it is impossible for it to reference anything outside its designated boundary. This isn't just validation - it's a type-level guarantee backed by cryptographic-grade path canonicalization.

**Unique capability:** By making markers authorization-aware, strict-path becomes the foundation for **compile-time authorization architectures** - where the compiler mathematically proves that any path with an authorization-requiring marker went through proper authorization during construction.


**Core Security Principle: Secure Every External Path**

Any path from untrusted sources (HTTP, CLI, config, DB, LLMs, archives) must be validated into a boundary‑enforced type (`StrictPath` or `VirtualPath`) before I/O.

## 🧪 Examples by Mode


> "Choose wisely: not all paths lead to safety."

### 🌐 **VirtualPath** - User Sandboxes & Cloud Storage

*"Give users their own private universe"*

```rust
use strict_path::VirtualPath;

// Archive extraction - hostile names get clamped, not rejected
let extract_root = VirtualPath::with_root("./extracted")?;
for entry_name in malicious_zip_entries {
    let safe_path = extract_root.virtual_join(entry_name)?; // "../../../etc" → "/etc"  
    safe_path.write(entry.data())?; // Always safe
}

// User cloud storage - users see friendly paths
let doc = VirtualPath::with_root(format!("users/{user_id}"))?
    .virtual_join("My Documents/report.pdf")?;
println!("Saved to: {}", doc.virtualpath_display()); // Shows "/My Documents/report.pdf"
```

> 📖 **Learn more:** **[Tutorial: Stage 5 - Virtual Paths →]https://dk26.github.io/strict-path-rs/tutorial/stage5_virtual_paths.html** explains user sandboxing and virtual root semantics.

### ⚔️ **StrictPath** - LLM Agents & System Boundaries  

*"Validate everything, trust nothing"*

```rust
use strict_path::PathBoundary;

// LLM Agent file operations
let ai_workspace_dir = PathBoundary::try_new("ai_sandbox")?;
let ai_request = llm.generate_path(); // Could be anything malicious
let safe_path = ai_workspace_dir.strict_join(ai_request)?; // ✅ Attack = Explicit Error
safe_path.write(&ai_generated_content)?;

// Limited system access with clear boundaries
struct ConfigFiles; 
let app_config_dir = PathBoundary::<ConfigFiles>::try_new("./config")?;
let user_config = app_config_dir.strict_join(user_selected_config)?; // ✅ Validated
```

### 🔓 **Path/PathBuf** - Controlled Access

*"When you control the source"*

```rust
use std::path::PathBuf;

// ✅ You control the input - no validation needed
let log_file = PathBuf::from(format!("logs/{}.log", timestamp));
let app_config = Path::new("config/app.toml"); // Hardcoded = safe

// ❌ NEVER with external input
let user_file = Path::new(user_input); // 🚨 SECURITY DISASTER
```


## 🚀 **Real-World Examples**


> "Every example here survived a close encounter with an LLM."

### LLM Agent File Manager

```rust
use strict_path::PathBoundary;

// Encode guarantees in signature: pass workspace directory boundary and untrusted request
async fn llm_file_operation(workspace_dir: &PathBoundary, request: &LlmRequest) -> Result<String> {
    // LLM could suggest anything: "../../../etc/passwd", "C:/Windows/System32", etc.
    let safe_path = workspace_dir.strict_join(&request.filename)?; // ✅ Attack = Error

    match request.operation.as_str() {
        "write" => safe_path.write(&request.content)?,
        "read" => return Ok(safe_path.read_to_string()?),
        _ => return Err("Invalid operation".into()),
    }
    Ok(format!("File {} processed safely", safe_path.strictpath_display()))
}
```

### Zip Extraction (Zip Slip Prevention)

```rust
use strict_path::VirtualPath;

// Encode guarantees in signature: construct a root once; pass untrusted entry names
fn extract_zip(zip_entries: impl IntoIterator<Item=(String, Vec<u8>)>) -> std::io::Result<()> {
    let extract_root = VirtualPath::with_root("./extracted")?;
    for (name, data) in zip_entries {
        // Hostile names like "../../../etc/passwd" get clamped to "/etc/passwd"
        let vpath = extract_root.virtual_join(&name)?; // ✅ Zip slip impossible
        vpath.create_parent_dir_all()?;
        vpath.write(&data)?;
    }
    Ok(())
}
```

### Web File Server

```rust
use strict_path::PathBoundary;

struct StaticFiles;

async fn serve_static(static_dir: &PathBoundary<StaticFiles>, path: &str) -> Result<Response> {
    let safe_path = static_dir.strict_join(path)?; // ✅ "../../../" → Error
    Ok(Response::new(safe_path.read()?))
}

// Function signature prevents bypass - no validation needed inside!
async fn serve_file(safe_path: &strict_path::StrictPath<StaticFiles>) -> Response {
    Response::new(safe_path.read().unwrap_or_default())
}
```

### Configuration Manager

```rust
use strict_path::PathBoundary;

struct UserConfigs;

fn load_user_config(config_dir: &PathBoundary<UserConfigs>, config_name: &str) -> Result<Config> {
    let config_file = config_dir.strict_join(config_name)?;
    Ok(serde_json::from_str(&config_file.read_to_string()?)?)
}
```

## ⚠️ **Security Scope**


> "If your attacker has root, strict-path can't save you—but it can make them work for it."

**What this protects against (99% of attacks)—including edge cases most developers miss:**
- **Basic path traversal**: `../../../etc/passwd`
- **Symlink escapes**: Following links outside boundaries, including directory bombs and cycle detection
- **Archive extraction attacks**: Zip slip and similar archive-based traversal attempts
- **Encoding bypass attempts**: Unicode normalization attacks, null bytes, and other encoding tricks
- **Windows platform-specific attacks**:
  - 8.3 short name aliasing (`PROGRA~1``Program Files`)
  - UNC path manipulation (`\\?\C:\` and `\\server\share\`)
  - NTFS Alternate Data Streams (`file.txt:hidden`)
  - Drive-relative path forms and junction points
- **Race conditions**: TOCTOU (Time-of-Check-Time-of-Use) during path resolution
- **Canonicalization edge cases**: Mixed separators, redundant separators, current/parent directory references

**The reality**: These aren't theoretical attacks—they're real vulnerabilities found in production systems. Instead of researching each CVE and implementing custom defenses, you get comprehensive protection from day one.

**What requires system-level privileges (rare):**
- **Hard links**: Multiple filesystem entries to same file data
- **Mount points**: Admin/root can redirect paths via filesystem mounts

**Bottom line**: If attackers have root/admin access, they've already won. This library stops the 99% of practical attacks that don't require special privileges—and handles all the edge cases you'd probably forget to check.


## 🔐 **Advanced: Type-Safe Context Separation**


> "Type safety: because mixing up user files and web assets is so 2005."

Use markers to prevent mixing different storage contexts at compile time:

```rust
use strict_path::{PathBoundary, StrictPath, VirtualRoot, VirtualPath};

struct WebAssets;    // CSS, JS, images  
struct UserFiles;    // Uploaded documents

// Functions enforce context via type system
fn serve_asset(web_asset_file: &StrictPath<WebAssets>) -> Response { /* ... */ }
fn process_upload(user_file: &StrictPath<UserFiles>) -> Result<()> { /* ... */ }

// Create context-specific roots
let public_assets_root: VirtualRoot<WebAssets> = VirtualRoot::try_new("public")?;
let user_uploads_root: VirtualRoot<UserFiles> = VirtualRoot::try_new("uploads")?;

let css_file: VirtualPath<WebAssets> = public_assets_root.virtual_join("app.css")?;
let report_file: VirtualPath<UserFiles> = user_uploads_root.virtual_join("report.pdf")?;

// Type system prevents context mixing
serve_asset(css_file.as_unvirtual());         // ✅ Correct context
// serve_asset(report_file.as_unvirtual());   // ❌ Compile error!
```

**Your IDE and compiler become security guards.**

**App Configuration with `app_path`:**
```rust
// ❌ Vulnerable - app dirs + user paths
use app_path::AppPath;
let app_dir = AppPath::new("MyApp").get_app_dir();
let config_file = app_dir.join(user_config_name); // 🚨 Potential escape
fs::write(config_file, settings)?;

// ✅ Protected - bounded app directories  
use strict_path::PathBoundary;
let app_config_dir = PathBoundary::try_new_create(AppPath::new("MyApp").get_app_dir())?;
let safe_config = app_config_dir.strict_join(user_config_name)?; // ✅ Validated
safe_config.write(&settings)?;
```

## ⚠️ Anti-Patterns (Tell‑offs and Fixes)


> "Don't be that developer: use the right display method."

### DON'T Mix Interop with Display


```rust
use strict_path::PathBoundary;
let user_uploads_dir = PathBoundary::try_new("./uploads")?; // user uploads directory boundary

// ❌ ANTI-PATTERN: Wrong method for display
println!("Path: {}", user_uploads_dir.interop_path().to_string_lossy());

// ✅ CORRECT: Use proper display methods
println!("Path: {}", user_uploads_dir.strictpath_display());

// For virtual flows, prefer `VirtualPath` and borrow strict view when needed:
use strict_path::VirtualPath;
let user_uploads_vroot = VirtualPath::with_root("./uploads")?; // user uploads root
let profile_avatar_file = user_uploads_vroot.virtual_join("profile/avatar.png")?; // file by domain role
println!("Virtual: {}", profile_avatar_file.virtualpath_display());
println!("System: {}", profile_avatar_file.as_unvirtual().strictpath_display());
```

**Why this matters:**
- `interop_path()` is designed solely for unavoidable third-party API interop (`AsRef<Path>`)
- `*_display()` methods are designed for human-readable output
- Mixing concerns makes code harder to understand and maintain

### Web Server File Serving

```rust
struct StaticFiles; // Marker for static assets

async fn serve_static_file(safe_path: &StrictPath<StaticFiles>) -> Result<Response> {
    // Function signature enforces safety - no validation needed inside!
    Ok(Response::new(safe_path.read()?))
}

// Caller handles validation once:
let static_files_dir = PathBoundary::<StaticFiles>::try_new("./static")?;
let safe_path = static_files_dir.strict_join(&user_requested_path)?; // ✅ Validated
serve_static_file(&safe_path).await?;
```

### Archive Extraction (Zip Slip Prevention)


📘 **[Complete Archive Extraction Guide →](https://dk26.github.io/strict-path-rs/examples/archive_extraction.html)** - Full patterns for ZIP/TAR handling, security rationale, and anti-patterns

### Cloud Storage API  


```rust
// User chooses any path - always safe
let user_cloud_root = VirtualPath::with_root(format!("/cloud/user_{id}"))?;
let user_cloud_file = user_cloud_root.virtual_join(&user_requested_path)?; // ✅ Always safe
user_cloud_file.write(upload_data)?;
```

### Configuration Files

```rust
use strict_path::PathBoundary;

// Encode guarantees via the signature: pass the boundary and an untrusted name
fn load_config(config_dir: &PathBoundary, name: &str) -> Result<String> {
    config_dir.strict_join(name)?.read_to_string() // ✅ Validated
}
```

### LLM/AI File Operations

```rust
// AI suggests file operations - always validated
let ai_workspace_dir = PathBoundary::try_new("ai_workspace")?;
let ai_suggested_path = llm_generate_filename(); // Could be anything!
let safe_ai_path = ai_workspace_dir.strict_join(ai_suggested_path)?; // ✅ Guaranteed safe
safe_ai_path.write(&ai_generated_content)?;
```

## 📚 **Documentation & Resources**


> "If you read the docs, you get +10 security points."

- **📖 [Complete API Reference]https://docs.rs/strict-path** - Comprehensive API documentation
- **📚 [User Guide & Examples]https://dk26.github.io/strict-path-rs/** - In-depth tutorials and patterns
    - Best Practices (detailed decision matrix): https://dk26.github.io/strict-path-rs/best_practices.html
    - Anti-Patterns (don’t-do list with fixes): https://dk26.github.io/strict-path-rs/anti_patterns.html
    - Examples (copy/pasteable scenarios): https://dk26.github.io/strict-path-rs/examples.html
- **🔧 [LLM_API_REFERENCE.md]LLM_API_REFERENCE.md** - Quick reference for all methods (LLM-focused)
- **🛠️ [`soft-canonicalize`]https://github.com/DK26/soft-canonicalize-rs** - The underlying path resolution engine

## 🔌 **Integrations**


> "Integrate like a pro: strict-path plays nice with everyone except attackers."

- **🗂️ OS Directories** (`dirs` feature): `PathBoundary::try_new_os_config()`, `try_new_os_downloads()`, etc. - **[Full Guide]https://dk26.github.io/strict-path-rs/os_directories.html**
- **📄 Serde** (`serde` feature): Safe serialization/deserialization of path types - **[Tutorial: Stage 6 Feature Integration]https://dk26.github.io/strict-path-rs/tutorial/stage6_features.html**
- **🌐 Axum**: Custom extractors for web servers - **[Complete Tutorial]https://dk26.github.io/strict-path-rs/axum_tutorial/overview.html**
- **📦 Archive Handling**: Safe ZIP/TAR extraction - **[Extractor Guide]https://dk26.github.io/strict-path-rs/examples/archive_extraction.html**

## 📄 **License**


MIT OR Apache-2.0