diff options
| author | amankumarsingh77 <amankumarsingh7702@gmal.com> | 2026-05-02 15:33:27 +0530 |
|---|---|---|
| committer | amankumarsingh77 <amankumarsingh7702@gmal.com> | 2026-05-02 15:33:27 +0530 |
| commit | 64cb4c87978434f478227fa2ea97277ae50269aa (patch) | |
| tree | 96f2ee1c9403bab36c7a969803f2f25b1cb82082 | |
| parent | 310d0a7324477079022b178f1a83161e9e61fb1d (diff) | |
fix(util): preserve AbortSignal.reason; validate namespace in temp paths
| -rw-r--r-- | src/util/paths.ts | 20 | ||||
| -rw-r--r-- | src/util/time.ts | 10 |
2 files changed, 21 insertions, 9 deletions
diff --git a/src/util/paths.ts b/src/util/paths.ts index 8cd9961..30a1bbd 100644 --- a/src/util/paths.ts +++ b/src/util/paths.ts @@ -2,8 +2,20 @@ import { randomUUID } from "node:crypto"; import { tmpdir } from "node:os"; import { join } from "node:path"; -export const screenshotPath = (namespace: string, ext: "png" | "jpeg" = "png"): string => - join(tmpdir(), `pi-browser-screenshot-${namespace}-${randomUUID()}.${ext}`); +const NAMESPACE_RE = /^[a-zA-Z0-9_-]+$/; -export const pdfPath = (namespace: string): string => - join(tmpdir(), `pi-browser-pdf-${namespace}-${randomUUID()}.pdf`); +const requireValidNamespace = (namespace: string): void => { + if (!NAMESPACE_RE.test(namespace)) { + throw new Error(`Invalid namespace (must match ${NAMESPACE_RE}): ${JSON.stringify(namespace)}`); + } +}; + +export const screenshotPath = (namespace: string, ext: "png" | "jpeg" = "png"): string => { + requireValidNamespace(namespace); + return join(tmpdir(), `pi-browser-screenshot-${namespace}-${randomUUID()}.${ext}`); +}; + +export const pdfPath = (namespace: string): string => { + requireValidNamespace(namespace); + return join(tmpdir(), `pi-browser-pdf-${namespace}-${randomUUID()}.pdf`); +}; diff --git a/src/util/time.ts b/src/util/time.ts index 73990ad..d16435f 100644 --- a/src/util/time.ts +++ b/src/util/time.ts @@ -1,17 +1,17 @@ export const sleep = (ms: number, signal?: AbortSignal): Promise<void> => new Promise((resolve, reject) => { if (signal?.aborted) { - reject(new Error("aborted")); + reject(signal.reason ?? new Error("aborted")); return; } + const onAbort = (): void => { + clearTimeout(timer); + reject(signal?.reason ?? new Error("aborted")); + }; const timer = setTimeout(() => { signal?.removeEventListener("abort", onAbort); resolve(); }, ms); - const onAbort = (): void => { - clearTimeout(timer); - reject(new Error("aborted")); - }; signal?.addEventListener("abort", onAbort, { once: true }); }); |
