mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 06:29:42 +02:00
Merge pull request #314 from aakhter/fix/symlink-safe-workspace-confinement
fix(routes): canonicalize the workspace before comparing it to a resolved path
This commit is contained in:
@@ -63,19 +63,29 @@ export async function readJsonConfig<T>(filePath: string, logLabel: string, defa
|
||||
* Validates that a file path (possibly containing symlinks) resolves to a location
|
||||
* within the given session working directory. Returns the resolved and relative paths,
|
||||
* or null if the path escapes the directory or doesn't exist.
|
||||
*
|
||||
* BOTH sides are realpath-resolved before they are compared. Resolving only the
|
||||
* candidate leaves the two paths in different namespaces whenever the workspace
|
||||
* itself is reached through a symlink, and `relative()` then reports a spurious
|
||||
* `../` for a file that is genuinely inside it — refusing every read and write in
|
||||
* that session. A symlinked workspace is ordinary: `os.tmpdir()` returns one on
|
||||
* macOS (`/tmp` -> `/private/tmp`), as do symlinked project dirs and bind-mounted
|
||||
* case paths. Canonicalizing the base only makes the comparison honest; escapes
|
||||
* are still refused, since the candidate keeps its own realpath.
|
||||
*/
|
||||
export function validateSessionFilePath(
|
||||
sessionWorkingDir: string,
|
||||
filePath: string
|
||||
): { resolvedPath: string; relativePath: string } | null {
|
||||
const fullPath = resolve(sessionWorkingDir, filePath);
|
||||
let resolvedWorkingDir: string;
|
||||
let resolvedPath: string;
|
||||
try {
|
||||
resolvedPath = realpathSync(fullPath);
|
||||
resolvedWorkingDir = realpathSync(sessionWorkingDir);
|
||||
resolvedPath = realpathSync(resolve(sessionWorkingDir, filePath));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
const relativePath = relative(sessionWorkingDir, resolvedPath);
|
||||
const relativePath = relative(resolvedWorkingDir, resolvedPath);
|
||||
if (relativePath.startsWith('..') || isAbsolute(relativePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user