Skip to content

Commit 96c0401

Browse files
committed
fix: prevent path traversal in downloadJobArtifacts local_path
downloadJobArtifacts() joined the caller-controlled local_path argument (download_job_artifacts MCP tool) directly into the filesystem save path with no validation, allowing an absolute path or ../ traversal sequence to write the artifact zip anywhere the process has permission to write. Apply the same normalize/validate check already used by downloadAttachment() for its localPath parameter: reject absolute paths, "..", and any path escaping the intended base directory.
1 parent 926d42c commit 96c0401

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7486,7 +7486,21 @@ async function downloadJobArtifacts(
74867486
await handleGitLabError(response);
74877487
74887488
const filename = `artifacts_job_${encodeGitLabPathSegment(jobId)}.zip`;
7489-
const savePath = localPath ? path.join(localPath, filename) : filename;
7489+
let savePath: string;
7490+
if (localPath) {
7491+
const normalizedLocalPath = path.normalize(localPath);
7492+
if (
7493+
path.isAbsolute(normalizedLocalPath) ||
7494+
normalizedLocalPath === ".." ||
7495+
normalizedLocalPath.startsWith(".." + path.sep) ||
7496+
normalizedLocalPath.includes(path.sep + ".." + path.sep)
7497+
) {
7498+
throw new Error("Invalid local_path: directory traversal is not allowed.");
7499+
}
7500+
savePath = path.join(normalizedLocalPath, filename);
7501+
} else {
7502+
savePath = filename;
7503+
}
74907504
fs.mkdirSync(path.dirname(savePath), { recursive: true });
74917505
74927506
if (!response.body) {

0 commit comments

Comments
 (0)