(path: string)
| 37 | * @returns {boolean} True if path traversal detected, false otherwise |
| 38 | */ |
| 39 | export const isPathTraversal = (path: string): boolean => { |
| 40 | // PATH_TRAVERSAL_SAFETY defaults to true; must be explicitly set to 'false' to disable |
| 41 | if (process.env.PATH_TRAVERSAL_SAFETY === 'false') { |
| 42 | return false |
| 43 | } |
| 44 | |
| 45 | // Normalize %2e → . before checking for .. to catch mixed-encoding bypasses |
| 46 | // e.g. .%2e/, %2e./, %2e%2e all become ../ |
| 47 | if (/\.\./.test(path.replace(/%2e/gi, '.'))) { |
| 48 | return true |
| 49 | } |
| 50 | |
| 51 | const dangerousPatterns = [ |
| 52 | /%2f/i, // URL encoded / |
| 53 | /%5c/i, // URL encoded \ (Windows path) |
| 54 | /\0/, // Null bytes |
| 55 | /%00/i, // URL encoded null byte |
| 56 | /^\s*[a-zA-Z]:[/\\]/, // Windows absolute paths (C:\, C:/) with optional leading whitespace |
| 57 | /^\\\\[^\\]/, // UNC paths (\\server\) |
| 58 | /^\// // Absolute Unix paths (/etc, /data, /root, etc.) |
| 59 | ] |
| 60 | |
| 61 | return dangerousPatterns.some((pattern) => pattern.test(path)) |
| 62 | } |
| 63 | |
| 64 | /** |
| 65 | * Enhanced path validation for workspace-scoped file operations |
no test coverage detected