Security Functions
Security-focused path resolution and validation functions
Security Functions
The security functions in @ucdjs/path-utils provide robust protection against path traversal attacks, encoding exploits, and boundary violations.
resolveSafePath
Resolves a path safely within a defined base directory boundary, preventing traversal attacks and malicious inputs.
Signature
function resolveSafePath(basePath: string, inputPath: string): stringParameters
basePath(string) - The base directory that acts as the virtual filesystem root. Must be a non-empty string.inputPath(string) - The path to resolve, which can be relative, absolute, or URL-encoded.
Returns
- (string) - The safely resolved absolute path within the base directory boundary.
Throws
PathTraversalError- If the resolved path would escape the base directoryWindowsDriveMismatchError- If attempting to access a different drive letter on WindowsUNCPathNotSupportedError- If a UNC path is providedIllegalCharacterInPathError- If the path contains null bytes or control charactersFailedToDecodePathError- If the path cannot be safely decoded
Behavior
The function implements a virtual filesystem boundary model:
-
Absolute Paths - Treated as relative to the boundary root:
resolveSafePath('/home/user', '/config.json') // → '/home/user/config.json' -
Root Reference - The root
/points to the boundary root:resolveSafePath('/home/user', '/') // → '/home/user' -
Current Directory - References point to the base path:
resolveSafePath('/home/user', '.') // → '/home/user'
Security Features
- Path Traversal Prevention - Blocks attempts to escape the boundary
- Encoding Attack Prevention - Detects and blocks encoded traversal
- Control Character Filtering - Rejects null bytes and control chars
- UNC Path Rejection - Blocks Windows UNC network paths
Examples
Basic Usage
import { resolveSafePath } from '@ucdjs/path-utils';
const boundary = '/var/www/html';
// Relative paths
resolveSafePath(boundary, 'assets/style.css');
// → '/var/www/html/assets/style.css'
// Absolute paths (treated as relative to boundary)
resolveSafePath(boundary, '/images/logo.png');
// → '/var/www/html/images/logo.png'
// Current directory
resolveSafePath(boundary, './index.html');
// → '/var/www/html/index.html'
// Empty input
resolveSafePath(boundary, '');
// → '/var/www/html'Windows Paths
const boundary = 'C:\\Projects\\MyApp';
// Windows-style paths
resolveSafePath(boundary, 'src\\index.ts');
// → 'C:/Projects/MyApp/src/index.ts'
// Mixed separators
resolveSafePath(boundary, 'src/components\\Button.tsx');
// → 'C:/Projects/MyApp/src/components/Button.tsx'
// Absolute Windows path within boundary
resolveSafePath(boundary, 'C:\\Projects\\MyApp\\data\\db.json');
// → 'C:/Projects/MyApp/data/db.json'
// Different drive letter
resolveSafePath(boundary, 'D:\\external.txt');
// ❌ WindowsDriveMismatchErrorURL-Encoded Paths
// Standard encoding
resolveSafePath('/base', 'file%20name.txt');
// → '/base/file name.txt'
// Path encoding
resolveSafePath('/base', 'path%2Fto%2Ffile.txt');
// → '/base/path/to/file.txt'
// Nested encoding
resolveSafePath('/base', '%252Fconfig%252Fjson');
// → '/base/config/json'decodePathSafely
Safely decodes a URL-encoded path with protection against infinite loops and malicious nested encodings.
Signature
function decodePathSafely(encodedPath: string): stringParameters
encodedPath(string) - The URL-encoded path to decode.
Returns
- (string) - The fully decoded path.
Throws
MaximumDecodingIterationsExceededError- If decoding exceeds 10 iterations (malicious input protection)TypeError- If the input is not a string
Behavior
The function decodes paths iteratively until no more encoding is detected:
- Attempts
decodeURIComponent() - Manually decodes common encodings:
%2e→.(dots)%2f→/(forward slashes)%5c→\(backslashes)
- Repeats up to 10 iterations maximum
- Throws error if limit exceeded (prevents infinite loops from malicious inputs)
Examples
import { decodePathSafely } from '@ucdjs/path-utils';
// Standard URL encoding
decodePathSafely('path%20with%20spaces');
// → 'path with spaces'
// Path separators
decodePathSafely('folder%2Ffile.txt');
// → 'folder/file.txt'
// Nested encoding
decodePathSafely('%252e%252e'); // %25 = %, so %252e = %2e = .
// → '..'
// Mixed encoding
decodePathSafely('file%2Ename%20with%20spaces');
// → 'file.name with spaces'
// Malformed encoding (handled gracefully)
decodePathSafely('%XY%ZZ');
// → '%XY%ZZ'
// Excessive nesting (protection)
decodePathSafely(maliciouslyNestedInput);
// ❌ MaximumDecodingIterationsExceededErrorisWithinBase
Checks if a resolved path is within a specified base path, considering case sensitivity and platform-specific behavior.
Signature
function isWithinBase(basePath: string, resolvedPath: string): booleanParameters
basePath(string) - The base directory boundary to check against.resolvedPath(string) - The path to validate.
Returns
- (boolean) -
trueif the resolved path is within the base path,falseotherwise.
Behavior
- Normalization - Both paths are normalized before comparison to resolve
.and..segments. - Case Sensitivity - Respects filesystem case sensitivity:
- Linux: case-sensitive
- Windows/macOS: case-insensitive
- Partial Match Prevention - Prevents partial directory matches:
isWithinBase('/root', '/root2/file') // → false (not /root/*)
Examples
import { isWithinBase } from '@ucdjs/path-utils';
// Exact match
isWithinBase('/home/user', '/home/user');
// → true
// Within boundary
isWithinBase('/home/user', '/home/user/documents/file.txt');
// → true
// Outside boundary
isWithinBase('/home/user', '/home/other/file.txt');
// → false
// Partial match prevention
isWithinBase('/var/log', '/var/log2/file.txt');
// → false
// Normalized paths
isWithinBase('/home/user', '/home/user/../user/docs/file.txt');
// → true
// Windows paths
isWithinBase('C:\\Users\\John', 'C:\\Users\\John\\Documents\\file.txt');
// → true
// Case sensitivity (on case-sensitive systems)
isWithinBase('/home/user', '/home/User/file.txt');
// → false (on Linux)
// → true (on Windows/macOS)Best Practices
:::info
Always use resolveSafePath as your primary function for user-provided paths. It handles decoding, validation, and boundary enforcement automatically.
:::
:::warning
Never trust user input - Always resolve paths through resolveSafePath before using them in file operations, even if they appear safe.
:::
:::success Use try-catch blocks to handle errors gracefully and provide appropriate user feedback for security violations. :::