@panguard-ai/panguard 1.4.9 → 1.4.10
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.
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* panguard up - One-command start
|
|
3
|
-
* pg up - 一行指令啟動防護 + 儀表板
|
|
2
|
+
* panguard up - One-command start: scan → protect → dashboard
|
|
4
3
|
*
|
|
5
|
-
*
|
|
4
|
+
* Flow: scan installed skills → warn about threats → start Guard → open dashboard
|
|
6
5
|
*/
|
|
7
6
|
import { Command } from 'commander';
|
|
8
7
|
export declare function upCommand(): Command;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/up.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/up.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,wBAAgB,SAAS,IAAI,OAAO,CAgJnC"}
|
package/dist/cli/commands/up.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* panguard up - One-command start
|
|
3
|
-
* pg up - 一行指令啟動防護 + 儀表板
|
|
2
|
+
* panguard up - One-command start: scan → protect → dashboard
|
|
4
3
|
*
|
|
5
|
-
*
|
|
4
|
+
* Flow: scan installed skills → warn about threats → start Guard → open dashboard
|
|
6
5
|
*/
|
|
7
6
|
import { existsSync, readFileSync } from 'node:fs';
|
|
8
7
|
import { join } from 'node:path';
|
|
@@ -10,21 +9,19 @@ import { homedir, platform } from 'node:os';
|
|
|
10
9
|
import { execFile } from 'node:child_process';
|
|
11
10
|
import { Command } from 'commander';
|
|
12
11
|
import { runCLI } from '@panguard-ai/panguard-guard';
|
|
13
|
-
import { c,
|
|
12
|
+
import { c, symbols, setLogLevel, } from '@panguard-ai/core';
|
|
14
13
|
const DASHBOARD_URL = 'http://127.0.0.1:3100';
|
|
15
|
-
/** Open URL in default browser (cross-platform) */
|
|
16
14
|
function openBrowser(url) {
|
|
17
15
|
const cmd = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open';
|
|
18
16
|
execFile(cmd, [url], () => { });
|
|
19
17
|
}
|
|
20
|
-
/** Check if Guard is already running via PID file */
|
|
21
18
|
function isGuardRunning() {
|
|
22
19
|
const pidPath = join(homedir(), '.panguard-guard', 'panguard-guard.pid');
|
|
23
20
|
if (!existsSync(pidPath))
|
|
24
21
|
return false;
|
|
25
22
|
try {
|
|
26
23
|
const pid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10);
|
|
27
|
-
process.kill(pid, 0);
|
|
24
|
+
process.kill(pid, 0);
|
|
28
25
|
return true;
|
|
29
26
|
}
|
|
30
27
|
catch {
|
|
@@ -33,11 +30,14 @@ function isGuardRunning() {
|
|
|
33
30
|
}
|
|
34
31
|
export function upCommand() {
|
|
35
32
|
return new Command('up')
|
|
36
|
-
.description('
|
|
37
|
-
.option('--no-dashboard', 'Skip
|
|
38
|
-
.option('--verbose', 'Verbose output
|
|
33
|
+
.description('Scan skills → start protection → open dashboard')
|
|
34
|
+
.option('--no-dashboard', 'Skip opening dashboard in browser')
|
|
35
|
+
.option('--verbose', 'Verbose output', false)
|
|
36
|
+
.option('--skip-scan', 'Skip initial skill scan', false)
|
|
39
37
|
.action(async (opts) => {
|
|
40
|
-
//
|
|
38
|
+
// Suppress JSON logs for clean output
|
|
39
|
+
if (!opts.verbose)
|
|
40
|
+
setLogLevel('silent');
|
|
41
41
|
const configPath1 = join(homedir(), '.panguard', 'config.json');
|
|
42
42
|
const configPath2 = join(homedir(), '.panguard-guard', 'config.json');
|
|
43
43
|
const isFirstRun = !existsSync(configPath1) && !existsSync(configPath2);
|
|
@@ -50,23 +50,111 @@ export function upCommand() {
|
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
catch {
|
|
53
|
-
//
|
|
53
|
+
// continue anyway
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
//
|
|
57
|
-
if (
|
|
58
|
-
console.log(c.sage(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
// ── Step 1: Open dashboard immediately ───────────────────
|
|
57
|
+
if (opts.dashboard) {
|
|
58
|
+
console.log(` ${c.sage(`Opening dashboard: ${DASHBOARD_URL}`)}\n`);
|
|
59
|
+
openBrowser(DASHBOARD_URL);
|
|
60
|
+
}
|
|
61
|
+
// ── Step 2: Scan installed skills ────────────────────────
|
|
62
|
+
if (!opts.skipScan) {
|
|
63
|
+
console.log(`\n ${symbols.scan} ${c.bold('Scanning installed skills...')}\n`);
|
|
64
|
+
try {
|
|
65
|
+
const pkg = '@panguard-ai/panguard-mcp';
|
|
66
|
+
let skills = [];
|
|
67
|
+
try {
|
|
68
|
+
const mcp = (await import(pkg));
|
|
69
|
+
skills = await mcp.discoverAllSkills();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Monorepo fallback
|
|
73
|
+
const { resolve } = await import('node:path');
|
|
74
|
+
const { pathToFileURL } = await import('node:url');
|
|
75
|
+
const mcpDist = resolve(process.cwd(), 'packages/panguard-mcp/dist/config/index.js');
|
|
76
|
+
const mcp = (await import(pathToFileURL(mcpDist).href));
|
|
77
|
+
skills = await mcp.discoverAllSkills();
|
|
78
|
+
}
|
|
79
|
+
if (skills.length === 0) {
|
|
80
|
+
console.log(` ${c.dim('No skills found. Install some MCP skills and run again.')}\n`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Load whitelist
|
|
84
|
+
const whitelistPath = join(homedir(), '.panguard-guard', 'skill-whitelist.json');
|
|
85
|
+
const safeNames = new Set();
|
|
86
|
+
if (existsSync(whitelistPath)) {
|
|
87
|
+
try {
|
|
88
|
+
const wl = JSON.parse(readFileSync(whitelistPath, 'utf-8'));
|
|
89
|
+
for (const s of wl.whitelist ?? []) {
|
|
90
|
+
safeNames.add(s.name.toLowerCase());
|
|
91
|
+
if (s.normalizedName)
|
|
92
|
+
safeNames.add(s.normalizedName.toLowerCase());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch { /* ignore */ }
|
|
96
|
+
}
|
|
97
|
+
const safe = skills.filter(s => safeNames.has(s.name.toLowerCase()));
|
|
98
|
+
const unknown = skills.filter(s => !safeNames.has(s.name.toLowerCase()));
|
|
99
|
+
console.log(` ${c.safe(String(safe.length))} safe ${c.dim('|')} ${unknown.length > 0 ? c.caution(String(unknown.length)) : c.dim('0')} unscanned`);
|
|
100
|
+
// If there are unscanned skills, run audit on them
|
|
101
|
+
if (unknown.length > 0) {
|
|
102
|
+
console.log(`\n ${symbols.warn} ${c.bold(`${unknown.length} unscanned skill(s) found. Auditing...`)}\n`);
|
|
103
|
+
const threats = [];
|
|
104
|
+
try {
|
|
105
|
+
const { auditSkill } = await import('@panguard-ai/panguard-skill-auditor');
|
|
106
|
+
for (const skill of unknown.slice(0, 20)) {
|
|
107
|
+
try {
|
|
108
|
+
// Find skill directory
|
|
109
|
+
const skillDir = join(homedir(), '.claude', 'skills', skill.name);
|
|
110
|
+
if (!existsSync(skillDir))
|
|
111
|
+
continue;
|
|
112
|
+
const report = await auditSkill(skillDir);
|
|
113
|
+
if (report.riskLevel === 'HIGH' || report.riskLevel === 'CRITICAL') {
|
|
114
|
+
threats.push({
|
|
115
|
+
name: skill.name,
|
|
116
|
+
platform: skill.platformId,
|
|
117
|
+
riskLevel: report.riskLevel,
|
|
118
|
+
riskScore: report.riskScore,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Skip skills that can't be audited
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Skill auditor not available
|
|
129
|
+
}
|
|
130
|
+
if (threats.length > 0) {
|
|
131
|
+
console.log(` ${c.critical(c.bold(`${threats.length} threat(s) detected:`))}\n`);
|
|
132
|
+
for (const t of threats) {
|
|
133
|
+
const icon = t.riskLevel === 'CRITICAL' ? c.critical('!!') : c.caution('!');
|
|
134
|
+
console.log(` [${icon}] ${c.bold(t.name)} (${t.platform}) — ${t.riskLevel} (${t.riskScore}/100)`);
|
|
135
|
+
}
|
|
136
|
+
console.log(`\n ${c.bold('Recommended action:')} Remove or disable these skills.`);
|
|
137
|
+
console.log(` ${c.dim('Run: pga audit skill <name> for details on each threat.')}\n`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
console.log(` ${c.safe(`${symbols.pass} No threats found in unscanned skills.`)}\n`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
console.log(` ${c.safe(`${symbols.pass} All ${skills.length} skills verified safe.`)}\n`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
console.log(` ${c.dim('Skill scan skipped (discovery unavailable).')}\n`);
|
|
62
150
|
}
|
|
63
|
-
return;
|
|
64
151
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
152
|
+
// ── Step 3: Start Guard ────────────────────────────────
|
|
153
|
+
if (isGuardRunning()) {
|
|
154
|
+
console.log(` ${c.safe(`${symbols.pass} Guard is already running.`)}\n`);
|
|
155
|
+
return;
|
|
69
156
|
}
|
|
157
|
+
console.log(` ${symbols.info} ${c.bold('Starting protection...')}\n`);
|
|
70
158
|
const args = ['start'];
|
|
71
159
|
if (opts.dashboard)
|
|
72
160
|
args.push('--dashboard');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"up.js","sourceRoot":"","sources":["../../../src/cli/commands/up.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"up.js","sourceRoot":"","sources":["../../../src/cli/commands/up.ts"],"names":[],"mappings":"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"}
|