@melihmucuk/leash 1.0.7 → 1.0.8
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/dist/claude-code/leash.js +29 -7
- package/dist/factory/leash.js +29 -7
- package/dist/opencode/leash.js +29 -7
- package/dist/pi/leash.js +38 -18
- package/package.json +3 -3
|
@@ -347,7 +347,11 @@ var CommandAnalyzer = class {
|
|
|
347
347
|
reason: `Command "${name}" targets path outside working directory: ${path}`
|
|
348
348
|
};
|
|
349
349
|
}
|
|
350
|
-
const result = this.checkProtectedPath(
|
|
350
|
+
const result = this.checkProtectedPath(
|
|
351
|
+
path,
|
|
352
|
+
`Command "${name}"`,
|
|
353
|
+
resolveBase
|
|
354
|
+
);
|
|
351
355
|
if (result.blocked) return result;
|
|
352
356
|
}
|
|
353
357
|
}
|
|
@@ -359,7 +363,10 @@ var CommandAnalyzer = class {
|
|
|
359
363
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
360
364
|
return {
|
|
361
365
|
blocked: true,
|
|
362
|
-
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
366
|
+
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
367
|
+
dest,
|
|
368
|
+
resolveBase
|
|
369
|
+
)}`
|
|
363
370
|
};
|
|
364
371
|
}
|
|
365
372
|
return this.checkProtectedPath(dest, 'Command "cp"', resolveBase);
|
|
@@ -371,7 +378,10 @@ var CommandAnalyzer = class {
|
|
|
371
378
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
372
379
|
return {
|
|
373
380
|
blocked: true,
|
|
374
|
-
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
381
|
+
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
382
|
+
dest,
|
|
383
|
+
resolveBase
|
|
384
|
+
)}`
|
|
375
385
|
};
|
|
376
386
|
}
|
|
377
387
|
return this.checkProtectedPath(dest, 'Command "dd"', resolveBase);
|
|
@@ -383,7 +393,10 @@ var CommandAnalyzer = class {
|
|
|
383
393
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
384
394
|
return {
|
|
385
395
|
blocked: true,
|
|
386
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
396
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
397
|
+
dest,
|
|
398
|
+
resolveBase
|
|
399
|
+
)}`
|
|
387
400
|
};
|
|
388
401
|
}
|
|
389
402
|
const destResult = this.checkProtectedPath(
|
|
@@ -396,7 +409,10 @@ var CommandAnalyzer = class {
|
|
|
396
409
|
if (!this.isPathAllowed(source, false, resolveBase)) {
|
|
397
410
|
return {
|
|
398
411
|
blocked: true,
|
|
399
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
412
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
413
|
+
source,
|
|
414
|
+
resolveBase
|
|
415
|
+
)}`
|
|
400
416
|
};
|
|
401
417
|
}
|
|
402
418
|
const sourceResult = this.checkProtectedPath(
|
|
@@ -413,7 +429,10 @@ var CommandAnalyzer = class {
|
|
|
413
429
|
if (!this.isPathAllowed(path, false, resolveBase)) {
|
|
414
430
|
return {
|
|
415
431
|
blocked: true,
|
|
416
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
432
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
433
|
+
path,
|
|
434
|
+
resolveBase
|
|
435
|
+
)}`
|
|
417
436
|
};
|
|
418
437
|
}
|
|
419
438
|
const result = this.checkProtectedPath(
|
|
@@ -431,7 +450,10 @@ var CommandAnalyzer = class {
|
|
|
431
450
|
if (!this.isPathAllowed(path, allowDevicePaths, resolveBase)) {
|
|
432
451
|
return {
|
|
433
452
|
blocked: true,
|
|
434
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
453
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
454
|
+
path,
|
|
455
|
+
resolveBase
|
|
456
|
+
)}`
|
|
435
457
|
};
|
|
436
458
|
}
|
|
437
459
|
const result = this.checkProtectedPath(
|
package/dist/factory/leash.js
CHANGED
|
@@ -347,7 +347,11 @@ var CommandAnalyzer = class {
|
|
|
347
347
|
reason: `Command "${name}" targets path outside working directory: ${path}`
|
|
348
348
|
};
|
|
349
349
|
}
|
|
350
|
-
const result = this.checkProtectedPath(
|
|
350
|
+
const result = this.checkProtectedPath(
|
|
351
|
+
path,
|
|
352
|
+
`Command "${name}"`,
|
|
353
|
+
resolveBase
|
|
354
|
+
);
|
|
351
355
|
if (result.blocked) return result;
|
|
352
356
|
}
|
|
353
357
|
}
|
|
@@ -359,7 +363,10 @@ var CommandAnalyzer = class {
|
|
|
359
363
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
360
364
|
return {
|
|
361
365
|
blocked: true,
|
|
362
|
-
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
366
|
+
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
367
|
+
dest,
|
|
368
|
+
resolveBase
|
|
369
|
+
)}`
|
|
363
370
|
};
|
|
364
371
|
}
|
|
365
372
|
return this.checkProtectedPath(dest, 'Command "cp"', resolveBase);
|
|
@@ -371,7 +378,10 @@ var CommandAnalyzer = class {
|
|
|
371
378
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
372
379
|
return {
|
|
373
380
|
blocked: true,
|
|
374
|
-
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
381
|
+
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
382
|
+
dest,
|
|
383
|
+
resolveBase
|
|
384
|
+
)}`
|
|
375
385
|
};
|
|
376
386
|
}
|
|
377
387
|
return this.checkProtectedPath(dest, 'Command "dd"', resolveBase);
|
|
@@ -383,7 +393,10 @@ var CommandAnalyzer = class {
|
|
|
383
393
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
384
394
|
return {
|
|
385
395
|
blocked: true,
|
|
386
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
396
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
397
|
+
dest,
|
|
398
|
+
resolveBase
|
|
399
|
+
)}`
|
|
387
400
|
};
|
|
388
401
|
}
|
|
389
402
|
const destResult = this.checkProtectedPath(
|
|
@@ -396,7 +409,10 @@ var CommandAnalyzer = class {
|
|
|
396
409
|
if (!this.isPathAllowed(source, false, resolveBase)) {
|
|
397
410
|
return {
|
|
398
411
|
blocked: true,
|
|
399
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
412
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
413
|
+
source,
|
|
414
|
+
resolveBase
|
|
415
|
+
)}`
|
|
400
416
|
};
|
|
401
417
|
}
|
|
402
418
|
const sourceResult = this.checkProtectedPath(
|
|
@@ -413,7 +429,10 @@ var CommandAnalyzer = class {
|
|
|
413
429
|
if (!this.isPathAllowed(path, false, resolveBase)) {
|
|
414
430
|
return {
|
|
415
431
|
blocked: true,
|
|
416
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
432
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
433
|
+
path,
|
|
434
|
+
resolveBase
|
|
435
|
+
)}`
|
|
417
436
|
};
|
|
418
437
|
}
|
|
419
438
|
const result = this.checkProtectedPath(
|
|
@@ -431,7 +450,10 @@ var CommandAnalyzer = class {
|
|
|
431
450
|
if (!this.isPathAllowed(path, allowDevicePaths, resolveBase)) {
|
|
432
451
|
return {
|
|
433
452
|
blocked: true,
|
|
434
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
453
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
454
|
+
path,
|
|
455
|
+
resolveBase
|
|
456
|
+
)}`
|
|
435
457
|
};
|
|
436
458
|
}
|
|
437
459
|
const result = this.checkProtectedPath(
|
package/dist/opencode/leash.js
CHANGED
|
@@ -345,7 +345,11 @@ var CommandAnalyzer = class {
|
|
|
345
345
|
reason: `Command "${name}" targets path outside working directory: ${path}`
|
|
346
346
|
};
|
|
347
347
|
}
|
|
348
|
-
const result = this.checkProtectedPath(
|
|
348
|
+
const result = this.checkProtectedPath(
|
|
349
|
+
path,
|
|
350
|
+
`Command "${name}"`,
|
|
351
|
+
resolveBase
|
|
352
|
+
);
|
|
349
353
|
if (result.blocked) return result;
|
|
350
354
|
}
|
|
351
355
|
}
|
|
@@ -357,7 +361,10 @@ var CommandAnalyzer = class {
|
|
|
357
361
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
358
362
|
return {
|
|
359
363
|
blocked: true,
|
|
360
|
-
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
364
|
+
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
365
|
+
dest,
|
|
366
|
+
resolveBase
|
|
367
|
+
)}`
|
|
361
368
|
};
|
|
362
369
|
}
|
|
363
370
|
return this.checkProtectedPath(dest, 'Command "cp"', resolveBase);
|
|
@@ -369,7 +376,10 @@ var CommandAnalyzer = class {
|
|
|
369
376
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
370
377
|
return {
|
|
371
378
|
blocked: true,
|
|
372
|
-
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
379
|
+
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
380
|
+
dest,
|
|
381
|
+
resolveBase
|
|
382
|
+
)}`
|
|
373
383
|
};
|
|
374
384
|
}
|
|
375
385
|
return this.checkProtectedPath(dest, 'Command "dd"', resolveBase);
|
|
@@ -381,7 +391,10 @@ var CommandAnalyzer = class {
|
|
|
381
391
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
382
392
|
return {
|
|
383
393
|
blocked: true,
|
|
384
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
394
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
395
|
+
dest,
|
|
396
|
+
resolveBase
|
|
397
|
+
)}`
|
|
385
398
|
};
|
|
386
399
|
}
|
|
387
400
|
const destResult = this.checkProtectedPath(
|
|
@@ -394,7 +407,10 @@ var CommandAnalyzer = class {
|
|
|
394
407
|
if (!this.isPathAllowed(source, false, resolveBase)) {
|
|
395
408
|
return {
|
|
396
409
|
blocked: true,
|
|
397
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
410
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
411
|
+
source,
|
|
412
|
+
resolveBase
|
|
413
|
+
)}`
|
|
398
414
|
};
|
|
399
415
|
}
|
|
400
416
|
const sourceResult = this.checkProtectedPath(
|
|
@@ -411,7 +427,10 @@ var CommandAnalyzer = class {
|
|
|
411
427
|
if (!this.isPathAllowed(path, false, resolveBase)) {
|
|
412
428
|
return {
|
|
413
429
|
blocked: true,
|
|
414
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
430
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
431
|
+
path,
|
|
432
|
+
resolveBase
|
|
433
|
+
)}`
|
|
415
434
|
};
|
|
416
435
|
}
|
|
417
436
|
const result = this.checkProtectedPath(
|
|
@@ -429,7 +448,10 @@ var CommandAnalyzer = class {
|
|
|
429
448
|
if (!this.isPathAllowed(path, allowDevicePaths, resolveBase)) {
|
|
430
449
|
return {
|
|
431
450
|
blocked: true,
|
|
432
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
451
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
452
|
+
path,
|
|
453
|
+
resolveBase
|
|
454
|
+
)}`
|
|
433
455
|
};
|
|
434
456
|
}
|
|
435
457
|
const result = this.checkProtectedPath(
|
package/dist/pi/leash.js
CHANGED
|
@@ -345,7 +345,11 @@ var CommandAnalyzer = class {
|
|
|
345
345
|
reason: `Command "${name}" targets path outside working directory: ${path}`
|
|
346
346
|
};
|
|
347
347
|
}
|
|
348
|
-
const result = this.checkProtectedPath(
|
|
348
|
+
const result = this.checkProtectedPath(
|
|
349
|
+
path,
|
|
350
|
+
`Command "${name}"`,
|
|
351
|
+
resolveBase
|
|
352
|
+
);
|
|
349
353
|
if (result.blocked) return result;
|
|
350
354
|
}
|
|
351
355
|
}
|
|
@@ -357,7 +361,10 @@ var CommandAnalyzer = class {
|
|
|
357
361
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
358
362
|
return {
|
|
359
363
|
blocked: true,
|
|
360
|
-
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
364
|
+
reason: `Command "cp" targets path outside working directory: ${this.resolvePath(
|
|
365
|
+
dest,
|
|
366
|
+
resolveBase
|
|
367
|
+
)}`
|
|
361
368
|
};
|
|
362
369
|
}
|
|
363
370
|
return this.checkProtectedPath(dest, 'Command "cp"', resolveBase);
|
|
@@ -369,7 +376,10 @@ var CommandAnalyzer = class {
|
|
|
369
376
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
370
377
|
return {
|
|
371
378
|
blocked: true,
|
|
372
|
-
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
379
|
+
reason: `Command "dd" targets path outside working directory: ${this.resolvePath(
|
|
380
|
+
dest,
|
|
381
|
+
resolveBase
|
|
382
|
+
)}`
|
|
373
383
|
};
|
|
374
384
|
}
|
|
375
385
|
return this.checkProtectedPath(dest, 'Command "dd"', resolveBase);
|
|
@@ -381,7 +391,10 @@ var CommandAnalyzer = class {
|
|
|
381
391
|
if (!this.isPathAllowed(dest, true, resolveBase)) {
|
|
382
392
|
return {
|
|
383
393
|
blocked: true,
|
|
384
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
394
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
395
|
+
dest,
|
|
396
|
+
resolveBase
|
|
397
|
+
)}`
|
|
385
398
|
};
|
|
386
399
|
}
|
|
387
400
|
const destResult = this.checkProtectedPath(
|
|
@@ -394,7 +407,10 @@ var CommandAnalyzer = class {
|
|
|
394
407
|
if (!this.isPathAllowed(source, false, resolveBase)) {
|
|
395
408
|
return {
|
|
396
409
|
blocked: true,
|
|
397
|
-
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
410
|
+
reason: `Command "mv" targets path outside working directory: ${this.resolvePath(
|
|
411
|
+
source,
|
|
412
|
+
resolveBase
|
|
413
|
+
)}`
|
|
398
414
|
};
|
|
399
415
|
}
|
|
400
416
|
const sourceResult = this.checkProtectedPath(
|
|
@@ -411,7 +427,10 @@ var CommandAnalyzer = class {
|
|
|
411
427
|
if (!this.isPathAllowed(path, false, resolveBase)) {
|
|
412
428
|
return {
|
|
413
429
|
blocked: true,
|
|
414
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
430
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
431
|
+
path,
|
|
432
|
+
resolveBase
|
|
433
|
+
)}`
|
|
415
434
|
};
|
|
416
435
|
}
|
|
417
436
|
const result = this.checkProtectedPath(
|
|
@@ -429,7 +448,10 @@ var CommandAnalyzer = class {
|
|
|
429
448
|
if (!this.isPathAllowed(path, allowDevicePaths, resolveBase)) {
|
|
430
449
|
return {
|
|
431
450
|
blocked: true,
|
|
432
|
-
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
451
|
+
reason: `Command "${baseCmd}" targets path outside working directory: ${this.resolvePath(
|
|
452
|
+
path,
|
|
453
|
+
resolveBase
|
|
454
|
+
)}`
|
|
433
455
|
};
|
|
434
456
|
}
|
|
435
457
|
const result = this.checkProtectedPath(
|
|
@@ -544,17 +566,15 @@ async function checkForUpdates() {
|
|
|
544
566
|
// packages/pi/leash.ts
|
|
545
567
|
function leash_default(pi) {
|
|
546
568
|
let analyzer = null;
|
|
547
|
-
pi.on("
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
);
|
|
557
|
-
}
|
|
569
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
570
|
+
analyzer = new CommandAnalyzer(ctx.cwd);
|
|
571
|
+
ctx.ui.notify("\u{1F512} Leash active", "info");
|
|
572
|
+
const update = await checkForUpdates();
|
|
573
|
+
if (update.hasUpdate) {
|
|
574
|
+
ctx.ui.notify(
|
|
575
|
+
`\u{1F504} Leash ${update.latestVersion} available. Run: leash --update (restart required)`,
|
|
576
|
+
"warning"
|
|
577
|
+
);
|
|
558
578
|
}
|
|
559
579
|
});
|
|
560
580
|
pi.on("tool_call", async (event, ctx) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@melihmucuk/leash",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Security guardrails for AI coding agents",
|
|
6
6
|
"bin": {
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"build:factory": "esbuild packages/factory/leash.ts --bundle --outfile=dist/factory/leash.js --platform=node --format=esm"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
53
|
-
"@opencode-ai/plugin": "^1.0.
|
|
52
|
+
"@mariozechner/pi-coding-agent": "^0.31.0",
|
|
53
|
+
"@opencode-ai/plugin": "^1.0.224",
|
|
54
54
|
"@types/node": "^22.19.3",
|
|
55
55
|
"esbuild": "^0.27.2",
|
|
56
56
|
"typescript": "^5.9.3"
|