mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 12:52:11 +03:00
v3.8.40 cycle integration → main. All test gates green (Unit/Integration/Coverage/Node-compat/Quality-Ratchet). The only red check, 'PR Test Policy', is the test-masking heuristic firing on the cumulative ~57-commit release diff (legitimate assert consolidations already reviewed per-PR — Gemini CLI removal #5246, retired GPT models #5280, provider catalog refreshes); overridden with --admin per the documented release-PR convention. CodeQL/SonarQube advisory scans non-blocking; #5278's code already passed CodeQL on main. Homologated on VPS 192.168.0.15 (v3.8.40 healthy).
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import path from "node:path";
|
|
|
|
// A locale or slug segment may only contain ASCII letters, digits and dashes.
|
|
// This blocks `..`, `/`, `\0`, and absolute paths before any filesystem access.
|
|
const SEGMENT_RE = /^[a-z0-9-]+$/i;
|
|
|
|
/**
|
|
* Resolve the i18n section directory for a docs slug under `<docsRoot>/i18n`, or
|
|
* return `null` when the locale/slug contain anything but `[a-z0-9-]` or the
|
|
* resolved path escapes `<docsRoot>/i18n`.
|
|
*
|
|
* Pure path math — no filesystem access — so it is directly unit-testable and
|
|
* is the single chokepoint guarding the i18n docs fallback against path
|
|
* traversal (the `locale` comes from a user-controllable cookie). The prefix
|
|
* check uses `i18nRoot + path.sep` (not a bare `startsWith`) so a sibling like
|
|
* `…/i18n-evil` cannot satisfy it.
|
|
*/
|
|
export function resolveSafeI18nSectionDir(
|
|
docsRoot: string,
|
|
locale: string,
|
|
slug: string[]
|
|
): string | null {
|
|
if (!locale || !SEGMENT_RE.test(locale)) return null;
|
|
if (!slug.length || !slug.every((s) => SEGMENT_RE.test(s))) return null;
|
|
|
|
const i18nRoot = path.join(docsRoot, "i18n");
|
|
const sectionDir = path.resolve(i18nRoot, locale, "docs", ...slug.slice(0, -1));
|
|
|
|
if (sectionDir !== i18nRoot && !sectionDir.startsWith(i18nRoot + path.sep)) {
|
|
return null;
|
|
}
|
|
return sectionDir;
|
|
}
|