safename
Filename and path validation for security hardening, inspired by David A. Wheeler's proposed Linux safename LSM.
Problem
Unix/Linux filesystems allow almost any bytes in filenames, which creates security vulnerabilities:
- Command injection: Filenames like
-rfor--helpare interpreted as flags - Shell expansion:
~user,$HOME,*.txtexpand unexpectedly - Terminal attacks: Control characters can inject escape sequences
- Path traversal: Backslashes normalize to forward slashes on some systems
- Delimiter injection: Colons in PATH, semicolons in scripts
This library validates and sanitizes filenames to prevent these attacks.
Usage
use ;
// Check if a filename is safe
assert!;
assert!; // Leading dash
assert!; // Control character
// Get detailed error information
match validate_file
// Sanitize unsafe filenames (returns Result)
let safe = sanitize_file.unwrap; // Returns b"_rf"
Path validation
use ;
assert!;
assert!; // Component starts with dash
Custom options
use ;
let opts = FileValidationOptions ;
assert!;
Default Rules
Always blocked:
| Bytes | Description |
|---|---|
0x00-0x1F |
Control characters (NUL, tab, newline, escape, etc.) |
/ |
Path separator (cannot appear in filename) |
0x7F |
DEL control character |
0xFF |
Invalid UTF-8 leading byte |
Position-dependent:
| Position | Blocked | Reason |
|---|---|---|
| Initial | - |
Interpreted as command-line option |
| Initial | ~ |
Shell home directory expansion |
| Initial | space | Quoting bugs, argument splitting |
| Final | space | Quoting bugs, argument splitting |
Feature Flags
Features are organized into tiers:
low (default)
Cross-platform safety. Includes:
block-colon- Blocks:(PATH injection, /etc/passwd formats)block-backslash- Blocks\(path traversal via normalization)
require-utf8 (default)
Requires valid UTF-8 encoding. Enabled by default alongside low.
require-ascii
Alternative to require-utf8 for ASCII-only environments. Blocks all bytes >= 0x80.
Note: require-utf8 and require-ascii are mutually exclusive (compile error if both enabled).
medium
Shell safety without breaking common filenames. Includes low plus:
block-quotes- Blocks"and'block-chaining- Blocks&,;,|(for&&,;,||)block-redirection- Blocks|,>,<block-expansion- Blocks$,%,*,?,`
high
Maximum restriction. Includes medium plus:
block-brackets- Blocks(,),[,]block-space- Blocks spaces everywhere (not just leading/trailing)
Note: These features may break common filenames like file (copy).txt or my document.pdf.
Cargo.toml
[]
= "0.1" # low (default)
= { = "0.1", = ["medium"] }
= { = "0.1", = ["high"] }
= { = "0.1", = false } # minimal
= { = "0.1", = false, = ["require-ascii"] } # ASCII-only
Background
Inspired by David A. Wheeler's work on safe filenames:
License
Copyright 2025 Adam Mill
Licensed under the Apache License, Version 2.0. See LICENSE.txt for details.