| 1 | import * as Effect from "effect/Effect"; |
| 2 | |
| 3 | /** Validate an untrusted bundler output path before writing it to disk. */ |
| 4 | export const normalizeBundleFilePath = (input: string) => |
| 5 | Effect.gen(function* () { |
| 6 | const normalized = input.replaceAll("\\", "/"); |
| 7 | if ( |
| 8 | normalized.length === 0 || |
| 9 | normalized.startsWith("/") || |
| 10 | /^[a-zA-Z]:\//.test(normalized) |
| 11 | ) { |
| 12 | return yield* Effect.fail( |
| 13 | new Error(`Invalid Compute bundle output path: ${input}`), |
| 14 | ); |
| 15 | } |
| 16 | const segments = normalized.split("/"); |
| 17 | if ( |
| 18 | segments.some( |
| 19 | (segment) => |
| 20 | segment.length === 0 || segment === "." || segment === "..", |
| 21 | ) |
| 22 | ) { |
| 23 | return yield* Effect.fail( |
| 24 | new Error(`Invalid Compute bundle output path: ${input}`), |
| 25 | ); |
| 26 | } |
| 27 | return segments.join("/"); |
| 28 | }); |