59 lines
2.2 KiB
Markdown
59 lines
2.2 KiB
Markdown
# Path sanitisation
|
|
|
|
## Purpose
|
|
|
|
`sanitizePath` is the single boundary check every method that accepts a
|
|
filesystem path passes through before invoking `FsLike`. It enforces three
|
|
rules — non-empty strings, no null bytes, no `..` traversal outside a
|
|
configured `rootDir` — and turns every failure into a stable
|
|
`AudioEngineServerError` carrying code `AUDIO_ENGINE_SERVER.INVALID_PATH`.
|
|
Co-located helpers `isHttpUrl` (for URL inputs that bypass filesystem
|
|
sanitisation) and `checkAborted` (for `AbortSignal` short-circuits) keep
|
|
the I/O entry points small.
|
|
|
|
## Features
|
|
|
|
- Empty / null-byte / `..` traversal rejection with a single dotted code.
|
|
- Optional `rootDir` jail — when supplied, every path resolves under it
|
|
and absolute inputs outside the boundary are rejected.
|
|
- `isHttpUrl` lets `FileSourceAdapter.load` route URL inputs through
|
|
`fetch` without filesystem sanitisation.
|
|
- `checkAborted` short-circuits any operation whose `AbortSignal` is
|
|
already in the aborted state before any filesystem call is issued.
|
|
|
|
## Usage: Basic
|
|
|
|
```ts
|
|
import { sanitizePath } from "@suaveplan/audio-engine-server";
|
|
const safe = sanitizePath("./input.wav", "/var/uploads");
|
|
// safe === "/var/uploads/input.wav"
|
|
```
|
|
|
|
## Usage: Advanced
|
|
|
|
```ts
|
|
import { sanitizePath, isHttpUrl, checkAborted } from "@suaveplan/audio-engine-server";
|
|
|
|
function loadAny(input: string, signal?: AbortSignal) {
|
|
checkAborted(signal);
|
|
if (isHttpUrl(input)) return fetchAndDecode(input);
|
|
return readAndDecode(sanitizePath(input, process.env.AUDIO_ROOT));
|
|
}
|
|
```
|
|
|
|
## API Reference
|
|
|
|
- `sanitizePath(path: string, rootDir?: string): string` — returns the
|
|
resolved absolute path when `rootDir` is given, else the input unchanged.
|
|
- `isHttpUrl(value: string): boolean` — true for any `http`/`https` URL.
|
|
- `checkAborted(signal: AbortSignal | undefined): void` — throws
|
|
`AUDIO_ENGINE_SERVER.ABORTED` when `signal.aborted` is true.
|
|
|
|
## Implementation Notes
|
|
|
|
The traversal check resolves both `rootDir` and the candidate through
|
|
`node:path.resolve` so platform-specific separators (`/` and `\`) and
|
|
double-dot sequences are normalised before comparison. The `.startsWith`
|
|
guard uses a trailing separator so `"/var/uploads-evil"` cannot satisfy
|
|
the `"/var/uploads"` root.
|