mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 11:21:23 +00:00
refactor: unify boundary hardening for file reads
This commit is contained in:
@@ -181,6 +181,9 @@ async function resolveAgentWorkspaceFilePath(params: {
|
||||
if (!targetStat.isFile()) {
|
||||
return { kind: "invalid", requestPath, reason: "symlink target is not a file" };
|
||||
}
|
||||
if (targetStat.nlink > 1) {
|
||||
return { kind: "invalid", requestPath, reason: "hardlinked file target not allowed" };
|
||||
}
|
||||
} catch (err) {
|
||||
if (isNotFoundPathError(err) && params.allowMissing) {
|
||||
return { kind: "missing", requestPath, ioPath: targetReal, workspaceReal };
|
||||
@@ -193,6 +196,9 @@ async function resolveAgentWorkspaceFilePath(params: {
|
||||
if (!candidateLstat.isFile()) {
|
||||
return { kind: "invalid", requestPath, reason: "path is not a regular file" };
|
||||
}
|
||||
if (candidateLstat.nlink > 1) {
|
||||
return { kind: "invalid", requestPath, reason: "hardlinked file path not allowed" };
|
||||
}
|
||||
|
||||
const candidateReal = await fs.realpath(candidatePath).catch(() => candidatePath);
|
||||
if (!isPathInside(workspaceReal, candidateReal)) {
|
||||
@@ -207,6 +213,9 @@ async function statFileSafely(filePath: string): Promise<FileMeta | null> {
|
||||
if (lstat.isSymbolicLink() || !stat.isFile()) {
|
||||
return null;
|
||||
}
|
||||
if (stat.nlink > 1) {
|
||||
return null;
|
||||
}
|
||||
if (!sameFileIdentity(stat, lstat)) {
|
||||
return null;
|
||||
}
|
||||
@@ -226,6 +235,9 @@ async function writeFileSafely(filePath: string, content: string): Promise<void>
|
||||
if (lstat.isSymbolicLink() || !stat.isFile()) {
|
||||
throw new Error("unsafe file path");
|
||||
}
|
||||
if (stat.nlink > 1) {
|
||||
throw new Error("hardlinked file path is not allowed");
|
||||
}
|
||||
if (!sameFileIdentity(stat, lstat)) {
|
||||
throw new Error("path changed during write");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user