@grainulation/silo 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/serve-mcp.js +34 -3
- package/package.json +1 -1
package/lib/serve-mcp.js
CHANGED
|
@@ -108,7 +108,14 @@ function toolPull(dir, args) {
|
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const targetFile = into
|
|
111
|
+
const targetFile = into ? path.resolve(dir, into) : path.join(dir, "claims.json");
|
|
112
|
+
// Prevent path traversal — target must stay within workspace
|
|
113
|
+
if (targetFile !== dir && !targetFile.startsWith(dir + path.sep)) {
|
|
114
|
+
return {
|
|
115
|
+
status: "error",
|
|
116
|
+
message: `Target path escapes workspace directory.`,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
112
119
|
if (!fs.existsSync(targetFile)) {
|
|
113
120
|
return {
|
|
114
121
|
status: "error",
|
|
@@ -135,7 +142,14 @@ function toolStore(dir, args) {
|
|
|
135
142
|
return { status: "error", message: "Required field: name" };
|
|
136
143
|
}
|
|
137
144
|
|
|
138
|
-
const sourceFile = from
|
|
145
|
+
const sourceFile = from ? path.resolve(dir, from) : path.join(dir, "claims.json");
|
|
146
|
+
// Prevent path traversal — source must stay within workspace
|
|
147
|
+
if (sourceFile !== dir && !sourceFile.startsWith(dir + path.sep)) {
|
|
148
|
+
return {
|
|
149
|
+
status: "error",
|
|
150
|
+
message: `Source path escapes workspace directory.`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
139
153
|
if (!fs.existsSync(sourceFile)) {
|
|
140
154
|
return { status: "error", message: `Source file not found: ${sourceFile}` };
|
|
141
155
|
}
|
|
@@ -247,7 +261,14 @@ function toolConfluence(dir, args) {
|
|
|
247
261
|
case "publish": {
|
|
248
262
|
const { title, from, spaceKey, parentId, pageId } = args;
|
|
249
263
|
if (!title) return { status: "error", message: "Required field: title" };
|
|
250
|
-
const sourceFile = from
|
|
264
|
+
const sourceFile = from ? path.resolve(dir, from) : path.join(dir, "claims.json");
|
|
265
|
+
// Prevent path traversal — source must stay within workspace
|
|
266
|
+
if (sourceFile !== dir && !sourceFile.startsWith(dir + path.sep)) {
|
|
267
|
+
return {
|
|
268
|
+
status: "error",
|
|
269
|
+
message: `Source path escapes workspace directory.`,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
251
272
|
if (!fs.existsSync(sourceFile))
|
|
252
273
|
return {
|
|
253
274
|
status: "error",
|
|
@@ -269,6 +290,16 @@ function toolConfluence(dir, args) {
|
|
|
269
290
|
const target = pid || searchTitle;
|
|
270
291
|
if (!target)
|
|
271
292
|
return { status: "error", message: "Required: pageId or title" };
|
|
293
|
+
// Prevent path traversal — target must stay within workspace
|
|
294
|
+
if (into) {
|
|
295
|
+
const checkPath = path.resolve(dir, into);
|
|
296
|
+
if (checkPath !== dir && !checkPath.startsWith(dir + path.sep)) {
|
|
297
|
+
return {
|
|
298
|
+
status: "error",
|
|
299
|
+
message: `Target path escapes workspace directory.`,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
272
303
|
return confluence
|
|
273
304
|
.pull(target, { spaceKey })
|
|
274
305
|
.then((result) => {
|