import { realpath } from "node:fs/promises"; import { isAbsolute } from "node:path"; import { fileURLToPath } from "node:url"; import { isPathWithinRoot } from "../domain/localPath.js"; /** Canonicalize operator roots before evaluating any Electron file target. */ export const canonicalElectronRoots = async ( roots: readonly string[], ): Promise => { const canonical: string[] = []; for (const root of roots) canonical.push(await realpath(root)); return [...new Set(canonical)].sort(); }; /** Resolve one file URL and reject host, encoding, and symlink root escapes. */ export const authorizedElectronFile = async ( value: string, roots: readonly string[], ): Promise => { if (value.length > 65_536 || /%(?:2f|5c)/iu.test(value)) return undefined; let url: URL; try { url = new URL(value); } catch { return undefined; } if ( url.protocol !== "file:" || url.hostname !== "" || url.username !== "" || url.password !== "" ) return undefined; let path: string; try { path = fileURLToPath(url); } catch { return undefined; } if (!isAbsolute(path) || path.includes("\0")) return undefined; let canonical: string; try { canonical = await realpath(path); } catch { return undefined; } return roots.some((root) => isPathWithinRoot(root, canonical)) ? canonical : undefined; };