@juspay/neurolink 9.88.0 → 9.88.2
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/CHANGELOG.md +12 -0
- package/dist/agent/directTools.d.ts +6 -0
- package/dist/agent/directTools.js +46 -22
- package/dist/browser/neurolink.min.js +321 -321
- package/dist/cli/commands/config.js +2 -2
- package/dist/lib/agent/directTools.d.ts +6 -0
- package/dist/lib/agent/directTools.js +46 -22
- package/dist/lib/types/multimodal.js +19 -11
- package/dist/types/multimodal.js +19 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [9.88.2](https://github.com/juspay/neurolink/compare/v9.88.1...v9.88.2) (2026-07-15)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **(security):** harden isMultimodalInput guard + remove hardcoded AWS account ID ([b9d140f](https://github.com/juspay/neurolink/commit/b9d140fadcc09349a90389bf93f98167583b5d7b)), closes [#278](https://github.com/juspay/neurolink/issues/278)
|
|
6
|
+
|
|
7
|
+
## [9.88.1](https://github.com/juspay/neurolink/compare/v9.88.0...v9.88.1) (2026-07-15)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **(tools):** sandbox built-in file tools to the working directory ([4fc8520](https://github.com/juspay/neurolink/commit/4fc8520dbc024dec826a69a5f8264af7a25ff0e1))
|
|
12
|
+
|
|
1
13
|
## [9.88.0](https://github.com/juspay/neurolink/compare/v9.87.4...v9.88.0) (2026-07-15)
|
|
2
14
|
|
|
3
15
|
### Features
|
|
@@ -56,6 +56,12 @@ export declare const directAgentTools: {
|
|
|
56
56
|
path: string;
|
|
57
57
|
includeHidden: boolean;
|
|
58
58
|
}, {
|
|
59
|
+
success: boolean;
|
|
60
|
+
error: string;
|
|
61
|
+
path?: undefined;
|
|
62
|
+
items?: undefined;
|
|
63
|
+
count?: undefined;
|
|
64
|
+
} | {
|
|
59
65
|
success: boolean;
|
|
60
66
|
path: string;
|
|
61
67
|
items: {
|
|
@@ -14,6 +14,28 @@ function truncateOutput(output) {
|
|
|
14
14
|
}
|
|
15
15
|
return output;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Contain a built-in file tool to the process working directory.
|
|
19
|
+
*
|
|
20
|
+
* Returns the resolved absolute path when it lies inside `process.cwd()`, or an
|
|
21
|
+
* `error` string otherwise. This is the sandbox for the default-enabled
|
|
22
|
+
* `readFile` / `writeFile` / `listDirectory` / `analyzeCSV` tools: without it an
|
|
23
|
+
* agent can pass an absolute path (`/etc/passwd`) or `../` traversal and reach
|
|
24
|
+
* arbitrary files. The previous guard (`!resolvedPath.startsWith(cwd) &&
|
|
25
|
+
* !path.isAbsolute(filePath)`) was always false for absolute paths, so it never
|
|
26
|
+
* fired. The `cwd + path.sep` suffix prevents a sibling-prefix bypass
|
|
27
|
+
* (`/home/app` vs `/home/app-evil`).
|
|
28
|
+
*/
|
|
29
|
+
function resolveWithinCwd(filePath) {
|
|
30
|
+
const resolvedPath = path.resolve(filePath);
|
|
31
|
+
const cwd = path.resolve(process.cwd());
|
|
32
|
+
if (resolvedPath !== cwd && !resolvedPath.startsWith(cwd + path.sep)) {
|
|
33
|
+
return {
|
|
34
|
+
error: `Access denied: "${filePath}" resolves outside the working directory`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { path: resolvedPath };
|
|
38
|
+
}
|
|
17
39
|
// Runtime Google Search tool creation - bypasses TypeScript strict typing
|
|
18
40
|
function createGoogleSearchTools() {
|
|
19
41
|
const searchTool = {};
|
|
@@ -71,15 +93,13 @@ export const directAgentTools = {
|
|
|
71
93
|
}),
|
|
72
94
|
execute: async ({ path: filePath }) => {
|
|
73
95
|
try {
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
78
|
-
return {
|
|
79
|
-
success: false,
|
|
80
|
-
error: `Access denied: Cannot read files outside current directory`,
|
|
81
|
-
};
|
|
96
|
+
// Sandbox: contain reads to the working directory (blocks absolute-path
|
|
97
|
+
// escape and ../ traversal).
|
|
98
|
+
const guard = resolveWithinCwd(filePath);
|
|
99
|
+
if ("error" in guard) {
|
|
100
|
+
return { success: false, error: guard.error };
|
|
82
101
|
}
|
|
102
|
+
const resolvedPath = guard.path;
|
|
83
103
|
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
84
104
|
const stats = fs.statSync(resolvedPath);
|
|
85
105
|
return {
|
|
@@ -113,7 +133,12 @@ export const directAgentTools = {
|
|
|
113
133
|
}),
|
|
114
134
|
execute: async ({ path: dirPath, includeHidden }) => {
|
|
115
135
|
try {
|
|
116
|
-
|
|
136
|
+
// Sandbox: contain directory listing to the working directory.
|
|
137
|
+
const guard = resolveWithinCwd(dirPath);
|
|
138
|
+
if ("error" in guard) {
|
|
139
|
+
return { success: false, error: guard.error };
|
|
140
|
+
}
|
|
141
|
+
const resolvedPath = guard.path;
|
|
117
142
|
const items = fs.readdirSync(resolvedPath);
|
|
118
143
|
const filteredItems = includeHidden
|
|
119
144
|
? items
|
|
@@ -229,15 +254,13 @@ export const directAgentTools = {
|
|
|
229
254
|
}),
|
|
230
255
|
execute: async ({ path: filePath, content, mode }) => {
|
|
231
256
|
try {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (
|
|
236
|
-
return {
|
|
237
|
-
success: false,
|
|
238
|
-
error: `Access denied: Cannot write files outside current directory`,
|
|
239
|
-
};
|
|
257
|
+
// Sandbox: contain writes to the working directory (blocks absolute-path
|
|
258
|
+
// escape and ../ traversal).
|
|
259
|
+
const guard = resolveWithinCwd(filePath);
|
|
260
|
+
if ("error" in guard) {
|
|
261
|
+
return { success: false, error: guard.error };
|
|
240
262
|
}
|
|
263
|
+
const resolvedPath = guard.path;
|
|
241
264
|
// Check if file exists for create mode
|
|
242
265
|
if (mode === "create" && fs.existsSync(resolvedPath)) {
|
|
243
266
|
return {
|
|
@@ -326,11 +349,12 @@ export const directAgentTools = {
|
|
|
326
349
|
try {
|
|
327
350
|
// Resolve file path
|
|
328
351
|
logger.debug(`[analyzeCSV] Resolving file: ${filePath}`);
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
352
|
+
// Sandbox: contain CSV reads to the working directory.
|
|
353
|
+
const guard = resolveWithinCwd(filePath);
|
|
354
|
+
if ("error" in guard) {
|
|
355
|
+
return { success: false, error: guard.error };
|
|
356
|
+
}
|
|
357
|
+
const resolvedPath = guard.path;
|
|
334
358
|
logger.debug(`[analyzeCSV] Resolved path: ${resolvedPath}`);
|
|
335
359
|
// Parse CSV using streaming from disk (memory efficient)
|
|
336
360
|
logger.info(`[analyzeCSV] Starting CSV parsing (max ${maxRows} rows)...`);
|