Harden delete_files MCP tool: validate paths within repo root (#1636)

Mirror the path validation already performed by the commit_files tool.
delete_files previously only normalized absolute paths against CWD and
passed relative paths through unchecked; it now runs each path through
validatePathWithinRepo, rejecting "../" traversal and symlinked escapes
for consistency and defense-in-depth.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
gabrielonrails
2026-08-14 16:31:15 -07:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 9d7150bc8a
commit 05ee4b30d7
+11 -14
View File
@@ -432,21 +432,18 @@ server.tool(
throw new Error("GITHUB_TOKEN environment variable is required");
}
// Convert absolute paths to relative if they match CWD
const cwd = process.cwd();
const processedPaths = paths.map((filePath) => {
if (filePath.startsWith("/")) {
if (filePath.startsWith(cwd)) {
// Strip CWD from absolute path
return filePath.slice(cwd.length + 1);
} else {
throw new Error(
`Path '${filePath}' must be relative to repository root or within current working directory`,
// Validate all paths are within the repository root and normalize them to
// repo-relative paths for the git tree entries. This mirrors the validation
// already performed by the commit_files tool and rejects path traversal
// ("../") and symlinked escapes as defense-in-depth.
const resolvedRepoDir = resolve(REPO_DIR);
const processedPaths = await Promise.all(
paths.map(async (filePath) => {
await validatePathWithinRepo(filePath, REPO_DIR);
const normalizedPath = resolve(resolvedRepoDir, filePath);
return normalizedPath.slice(resolvedRepoDir.length + 1);
}),
);
}
}
return filePath;
});
// 1. Get the branch reference (create if doesn't exist)
const baseSha = await getOrCreateBranchRef(