first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user