* Sanitize zip entry path to ensure it's relative and safe under pluginDir * - Normalizes separators to '/' * - Strips leading slashes and Windows drive prefixes (e.g., C:/) * - Resolves '.' and '..' segments * - Preserves trailing slash for directory entries * @param {string} p * @param {bool
(p, isDir)
| 337 | * @returns {string} sanitized relative path |
| 338 | */ |
| 339 | function sanitizeZipPath(p, isDir) { |
| 340 | if (!p) return ""; |
| 341 | let path = String(p); |
| 342 | // Normalize separators |
| 343 | path = path.replace(/\\/g, "/"); |
| 344 | // Remove URL-like scheme if present accidentally |
| 345 | path = path.replace(/^[a-zA-Z]+:\/\//, ""); |
| 346 | // Strip leading slashes |
| 347 | path = path.replace(/^\/+/, ""); |
| 348 | // Strip Windows drive letter, e.g., C:/ |
| 349 | path = path.replace(/^[A-Za-z]:\//, ""); |
| 350 | |
| 351 | const parts = path.split("/"); |
| 352 | const stack = []; |
| 353 | for (const part of parts) { |
| 354 | if (!part || part === ".") continue; |
| 355 | if (part === "..") { |
| 356 | if (stack.length) stack.pop(); |
| 357 | continue; |
| 358 | } |
| 359 | stack.push(part); |
| 360 | } |
| 361 | let safe = stack.join("/"); |
| 362 | if (isDir && safe && !safe.endsWith("/")) safe += "/"; |
| 363 | return safe; |
| 364 | } |
| 365 | |
| 366 | /** |
| 367 | * Detects unsafe absolute paths in zip entries that should be ignored. |
no test coverage detected