@vtstech/pi-diag 1.1.9 → 1.2.1
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/diag.js +83 -17
- package/package.json +3 -3
package/diag.js
CHANGED
|
@@ -46,6 +46,11 @@ function redactValue(key, value) {
|
|
|
46
46
|
return value;
|
|
47
47
|
}
|
|
48
48
|
function diag_temp_default(pi) {
|
|
49
|
+
let cachedSystemPrompt = null;
|
|
50
|
+
let cachedPayload = null;
|
|
51
|
+
pi.on("before_provider_request", (event) => {
|
|
52
|
+
cachedPayload = event.payload;
|
|
53
|
+
});
|
|
49
54
|
const branding = [
|
|
50
55
|
` \u26A1 Pi Diagnostics v${EXTENSION_VERSION}`,
|
|
51
56
|
` Written by VTSTech`,
|
|
@@ -310,21 +315,21 @@ function diag_temp_default(pi) {
|
|
|
310
315
|
lines.push(section("SECURITY"));
|
|
311
316
|
const secMode = getSecurityMode();
|
|
312
317
|
lines.push(info(`Security mode: ${secMode.toUpperCase()}`));
|
|
313
|
-
const effectiveCmds = secMode === "max" ? BLOCKED_COMMANDS : CRITICAL_COMMANDS;
|
|
318
|
+
const effectiveCmds = secMode === "off" ? /* @__PURE__ */ new Set() : secMode === "max" ? BLOCKED_COMMANDS : CRITICAL_COMMANDS;
|
|
314
319
|
const blockedCmdList = Array.from(effectiveCmds).sort();
|
|
315
|
-
lines.push(info(`Command blocklist: ${blockedCmdList.length} commands blocked (${CRITICAL_COMMANDS.size} critical` + (secMode === "max" ? ` + ${EXTENDED_COMMANDS.size} extended)` : ")")));
|
|
320
|
+
lines.push(info(`Command blocklist: ${blockedCmdList.length} commands blocked (${CRITICAL_COMMANDS.size} critical` + (secMode === "max" ? ` + ${EXTENDED_COMMANDS.size} extended)` : secMode === "off" ? " (disabled in off mode)" : ")")));
|
|
316
321
|
const exampleCmds = blockedCmdList.filter((c) => ["rm", "sudo", "chmod", "curl", "wget", "eval"].includes(c));
|
|
317
322
|
if (exampleCmds.length > 0) {
|
|
318
323
|
lines.push(info(` Examples: ${exampleCmds.join(", ")}`));
|
|
319
324
|
}
|
|
320
325
|
check(
|
|
321
|
-
blockedCmdList.length > 0,
|
|
322
|
-
`Command blocklist active (${blockedCmdList.length} rules)`,
|
|
323
|
-
`Command blocklist is EMPTY \u2014 security risk!`
|
|
326
|
+
secMode === "off" ? true : blockedCmdList.length > 0,
|
|
327
|
+
secMode === "off" ? "Security disabled in off mode" : `Command blocklist active (${blockedCmdList.length} rules)`,
|
|
328
|
+
secMode === "off" ? "" : `Command blocklist is EMPTY \u2014 security risk!`
|
|
324
329
|
);
|
|
325
|
-
const effectivePatterns = secMode === "max" ? BLOCKED_URL_PATTERNS : BLOCKED_URL_ALWAYS;
|
|
330
|
+
const effectivePatterns = secMode === "off" ? /* @__PURE__ */ new Set() : secMode === "max" ? BLOCKED_URL_PATTERNS : BLOCKED_URL_ALWAYS;
|
|
326
331
|
const blockedPatterns = Array.from(effectivePatterns).sort();
|
|
327
|
-
lines.push(info(`SSRF protection: ${blockedPatterns.length} hostname patterns blocked (${BLOCKED_URL_ALWAYS.size} always` + (secMode === "max" ? ` + ${BLOCKED_URL_MAX_ONLY.size} max-only)` : ")")));
|
|
332
|
+
lines.push(info(`SSRF protection: ${blockedPatterns.length} hostname patterns blocked (${BLOCKED_URL_ALWAYS.size} always` + (secMode === "max" ? ` + ${BLOCKED_URL_MAX_ONLY.size} max-only)` : secMode === "off" ? " (disabled in off mode)" : ")")));
|
|
328
333
|
const examplePatterns = blockedPatterns.filter(
|
|
329
334
|
(p) => ["localhost", "127.0.0.1", "169.254.169.254", "10.", "192.168.", "internal."].includes(p)
|
|
330
335
|
);
|
|
@@ -332,19 +337,19 @@ function diag_temp_default(pi) {
|
|
|
332
337
|
lines.push(info(` Examples: ${examplePatterns.join(", ")}`));
|
|
333
338
|
}
|
|
334
339
|
check(
|
|
335
|
-
blockedPatterns.length > 0,
|
|
336
|
-
`SSRF protection active (${blockedPatterns.length} patterns)`,
|
|
337
|
-
`SSRF blocklist is EMPTY \u2014 vulnerability risk!`
|
|
340
|
+
secMode === "off" ? true : blockedPatterns.length > 0,
|
|
341
|
+
secMode === "off" ? "SSRF protection disabled in off mode" : `SSRF protection active (${blockedPatterns.length} patterns)`,
|
|
342
|
+
secMode === "off" ? "" : `SSRF blocklist is EMPTY \u2014 vulnerability risk!`
|
|
338
343
|
);
|
|
339
344
|
lines.push(info("SSRF validation tests:"));
|
|
340
345
|
const ssrfTests = [
|
|
341
|
-
{ url: "http://localhost:8080/api", expectBlocked: secMode === "max" },
|
|
342
|
-
{ url: "http://169.254.169.254/latest/meta-data/", expectBlocked:
|
|
343
|
-
{ url: "http://192.168.1.1/admin", expectBlocked:
|
|
346
|
+
{ url: "http://localhost:8080/api", expectBlocked: secMode !== "off" && secMode === "max" },
|
|
347
|
+
{ url: "http://169.254.169.254/latest/meta-data/", expectBlocked: secMode !== "off" },
|
|
348
|
+
{ url: "http://192.168.1.1/admin", expectBlocked: secMode !== "off" },
|
|
344
349
|
{ url: "https://api.example.com/data", expectBlocked: false }
|
|
345
350
|
];
|
|
346
351
|
for (const test of ssrfTests) {
|
|
347
|
-
const result = isSafeUrl(test.url);
|
|
352
|
+
const result = isSafeUrl(test.url, true, secMode);
|
|
348
353
|
if (test.expectBlocked && !result.safe) {
|
|
349
354
|
lines.push(ok(` BLOCKED: ${test.url} \u2192 ${result.error}`));
|
|
350
355
|
} else if (!test.expectBlocked && result.safe) {
|
|
@@ -376,9 +381,9 @@ function diag_temp_default(pi) {
|
|
|
376
381
|
}
|
|
377
382
|
lines.push(info("Command injection tests:"));
|
|
378
383
|
const cmdTests = [
|
|
379
|
-
{ cmd: "ls; rm -rf /", expectSafe:
|
|
380
|
-
{ cmd: "sudo chmod 777 /etc/passwd", expectSafe:
|
|
381
|
-
{ cmd: "curl http://localhost/secret", expectSafe: secMode !== "max" },
|
|
384
|
+
{ cmd: "ls; rm -rf /", expectSafe: secMode === "off" },
|
|
385
|
+
{ cmd: "sudo chmod 777 /etc/passwd", expectSafe: secMode === "off" },
|
|
386
|
+
{ cmd: "curl http://localhost/secret", expectSafe: secMode !== "max" && secMode !== "off" },
|
|
382
387
|
{ cmd: "ls -la", expectSafe: true },
|
|
383
388
|
{ cmd: "cat README.md", expectSafe: true },
|
|
384
389
|
{ cmd: "echo hello", expectSafe: true }
|
|
@@ -449,6 +454,67 @@ function diag_temp_default(pi) {
|
|
|
449
454
|
}
|
|
450
455
|
const thinking = pi.getThinkingLevel();
|
|
451
456
|
lines.push(info(`Thinking level: ${thinking}`));
|
|
457
|
+
lines.push(section("SYSTEM PROMPT"));
|
|
458
|
+
let systemPromptText = null;
|
|
459
|
+
try {
|
|
460
|
+
if (typeof ctx.getSystemPrompt === "function") {
|
|
461
|
+
systemPromptText = ctx.getSystemPrompt();
|
|
462
|
+
if (systemPromptText) {
|
|
463
|
+
debugLog("diag", `system prompt retrieved via getSystemPrompt(): ${systemPromptText.length} chars`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
} catch (err) {
|
|
467
|
+
debugLog("diag", "getSystemPrompt() not available", err);
|
|
468
|
+
}
|
|
469
|
+
if (!systemPromptText && cachedPayload) {
|
|
470
|
+
try {
|
|
471
|
+
const messages = cachedPayload.messages;
|
|
472
|
+
if (messages?.length) {
|
|
473
|
+
const sysMsg = messages.find((m) => m.role === "system") ?? messages[0];
|
|
474
|
+
if (sysMsg?.content) {
|
|
475
|
+
systemPromptText = sysMsg.content;
|
|
476
|
+
debugLog("diag", `system prompt extracted from payload: ${systemPromptText.length} chars`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
} catch (err) {
|
|
480
|
+
debugLog("diag", "failed to extract system prompt from payload", err);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (systemPromptText) {
|
|
484
|
+
const charCount = systemPromptText.length;
|
|
485
|
+
const wordCount = systemPromptText.split(/\s+/).filter(Boolean).length;
|
|
486
|
+
const lineCount = systemPromptText.split("\n").length;
|
|
487
|
+
lines.push(info(`Size: ${charCount} chars, ~${wordCount} words, ${lineCount} lines`));
|
|
488
|
+
const preview = systemPromptText.split("\n")[0]?.slice(0, 80) || "(empty first line)";
|
|
489
|
+
lines.push(info(`Opening line: ${preview}${preview.length >= 80 ? "..." : ""}`));
|
|
490
|
+
const TRUNCATE_AT = 2e3;
|
|
491
|
+
if (charCount <= TRUNCATE_AT) {
|
|
492
|
+
lines.push("");
|
|
493
|
+
lines.push(" \u250C\u2500\u2500\u2500 SYSTEM PROMPT \u2500\u2500\u2500");
|
|
494
|
+
for (const line of systemPromptText.split("\n")) {
|
|
495
|
+
lines.push(` \u2502 ${line}`);
|
|
496
|
+
}
|
|
497
|
+
lines.push(" \u2514" + "\u2500".repeat(Math.min("\u2500\u2500\u2500 SYSTEM PROMPT \u2500\u2500\u2500".length + 4, 50)));
|
|
498
|
+
check(true, "System prompt retrieved successfully");
|
|
499
|
+
} else {
|
|
500
|
+
const truncated = systemPromptText.slice(0, 1500);
|
|
501
|
+
const remaining = charCount - 1500;
|
|
502
|
+
lines.push("");
|
|
503
|
+
lines.push(" \u250C\u2500\u2500\u2500 SYSTEM PROMPT (truncated) \u2500\u2500\u2500");
|
|
504
|
+
for (const line of truncated.split("\n")) {
|
|
505
|
+
lines.push(` \u2502 ${line}`);
|
|
506
|
+
}
|
|
507
|
+
lines.push(` \u2502 ... (${remaining} more chars not shown)`);
|
|
508
|
+
lines.push(" \u2514" + "\u2500".repeat(Math.min("\u2500\u2500\u2500 SYSTEM PROMPT (truncated) \u2500\u2500\u2500".length + 4, 50)));
|
|
509
|
+
check(true, `System prompt retrieved (${charCount} chars, showing first 1500)`);
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
lines.push(warn("System prompt not available"));
|
|
513
|
+
lines.push(info(" Possible reasons:"));
|
|
514
|
+
lines.push(info(" \u2022 No provider request has been made yet in this session"));
|
|
515
|
+
lines.push(info(" \u2022 ctx.getSystemPrompt() is not supported by your Pi version"));
|
|
516
|
+
lines.push(info(" \u2022 The provider payload does not contain a messages array"));
|
|
517
|
+
}
|
|
452
518
|
lines.push(section("SUMMARY"));
|
|
453
519
|
lines.push(info(`Passed: ${passCount} Failed: ${failCount} Warnings: ${warnCount}`));
|
|
454
520
|
if (failCount === 0) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vtstech/pi-diag",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Diagnostics extension for Pi Coding Agent",
|
|
5
5
|
"main": "diag.js",
|
|
6
|
-
"keywords": ["pi-extensions"],
|
|
6
|
+
"keywords": ["pi-package", "pi", "pi-coding-agent", "pi-extensions"],
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"access": "public",
|
|
9
9
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "https://github.com/VTSTech/pi-coding-agent"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@vtstech/pi-shared": "1.1
|
|
17
|
+
"@vtstech/pi-shared": "1.2.1"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@mariozechner/pi-coding-agent": ">=0.66"
|