@guava-parity/guard-scanner 15.0.0 → 16.0.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/README.md +208 -42
- package/README_ja.md +252 -0
- package/SKILL.md +40 -11
- package/dist/cli.cjs +5997 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +6003 -0
- package/dist/index.cjs +4825 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.mjs +4798 -0
- package/dist/mcp-server.cjs +4756 -0
- package/dist/mcp-server.d.mts +1 -0
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.mjs +4767 -0
- package/dist/openclaw-plugin.cjs +4863 -0
- package/dist/openclaw-plugin.d.mts +11 -0
- package/dist/openclaw-plugin.d.ts +11 -0
- package/dist/openclaw-plugin.mjs +4847 -34
- package/dist/types.cjs +18 -0
- package/dist/types.d.mts +215 -0
- package/dist/types.d.ts +215 -0
- package/dist/types.mjs +1 -0
- package/docs/data/benchmark-ledger.json +1428 -0
- package/docs/data/corpus-metrics.json +3 -3
- package/docs/data/fp-ledger.json +18 -0
- package/docs/data/quality-contract.json +36 -0
- package/docs/generated/openclaw-upstream-status.json +13 -13
- package/docs/openclaw-compatibility-audit.md +3 -2
- package/docs/openclaw-continuous-compatibility-plan.md +2 -1
- package/docs/spec/capabilities.json +137 -5
- package/docs/spec/plugin-trust.json +11 -0
- package/hooks/{context.js → context.ts} +1 -0
- package/openclaw-plugin.mts +21 -5
- package/openclaw.plugin.json +2 -2
- package/package.json +58 -20
- package/src/asset-auditor.js +0 -508
- package/src/ci-reporter.js +0 -135
- package/src/cli.js +0 -434
- package/src/core/content-loader.js +0 -42
- package/src/core/inventory.js +0 -73
- package/src/core/report-adapters.js +0 -171
- package/src/core/risk-engine.js +0 -93
- package/src/core/rule-registry.js +0 -73
- package/src/core/semantic-validators.js +0 -85
- package/src/finding-schema.js +0 -191
- package/src/hooks/context.ts +0 -49
- package/src/html-template.js +0 -239
- package/src/ioc-db.js +0 -54
- package/src/mcp-server.js +0 -653
- package/src/openclaw-upstream.js +0 -128
- package/src/patterns.js +0 -629
- package/src/policy-engine.js +0 -32
- package/src/quarantine.js +0 -41
- package/src/runtime-guard.js +0 -384
- package/src/scanner.js +0 -1042
- package/src/skill-crawler.js +0 -254
- package/src/threat-model.js +0 -50
- package/src/validation-layer.js +0 -39
- package/src/vt-client.js +0 -202
- package/src/watcher.js +0 -170
package/src/watcher.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* guard-scanner v8 — Real-time File Watcher
|
|
3
|
-
*
|
|
4
|
-
* @security-manifest
|
|
5
|
-
* env-read: []
|
|
6
|
-
* env-write: []
|
|
7
|
-
* network: none
|
|
8
|
-
* fs-read: [watched directory]
|
|
9
|
-
* fs-write: []
|
|
10
|
-
* exec: none
|
|
11
|
-
* purpose: Real-time file system monitoring for security threats
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const fs = require('fs');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const { GuardScanner } = require('./scanner.js');
|
|
17
|
-
const EventEmitter = require('events');
|
|
18
|
-
|
|
19
|
-
class GuardWatcher extends EventEmitter {
|
|
20
|
-
constructor(options = {}) {
|
|
21
|
-
super();
|
|
22
|
-
this.verbose = options.verbose || false;
|
|
23
|
-
this.strict = options.strict || false;
|
|
24
|
-
this.soulLock = options.soulLock || false;
|
|
25
|
-
this.debounceMs = options.debounceMs || 300;
|
|
26
|
-
this.quiet = options.quiet || false;
|
|
27
|
-
this._watchers = [];
|
|
28
|
-
this._debounceTimers = new Map();
|
|
29
|
-
this._running = false;
|
|
30
|
-
this._scanCount = 0;
|
|
31
|
-
this._alertCount = 0;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
watch(directory) {
|
|
35
|
-
if (!directory) throw new Error('Watch directory is required');
|
|
36
|
-
if (!fs.existsSync(directory)) throw new Error(`Directory not found: ${directory}`);
|
|
37
|
-
if (!fs.statSync(directory).isDirectory()) throw new Error(`Not a directory: ${directory}`);
|
|
38
|
-
|
|
39
|
-
this._running = true;
|
|
40
|
-
|
|
41
|
-
if (!this.quiet) {
|
|
42
|
-
console.log(`\n🛡️ guard-scanner watch mode`);
|
|
43
|
-
console.log(`👁️ Watching: ${path.resolve(directory)}`);
|
|
44
|
-
console.log(`⚡ Strict: ${this.strict ? 'ON' : 'OFF'}`);
|
|
45
|
-
console.log(`🔒 Soul Lock: ${this.soulLock ? 'ON' : 'OFF'}`);
|
|
46
|
-
console.log('───────────────────────────────');
|
|
47
|
-
console.log('Press Ctrl+C to stop\n');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const watcher = fs.watch(directory, { recursive: true }, (eventType, filename) => {
|
|
52
|
-
if (!filename || !this._running) return;
|
|
53
|
-
const fullPath = path.join(directory, filename);
|
|
54
|
-
|
|
55
|
-
// Debounce
|
|
56
|
-
if (this._debounceTimers.has(fullPath)) {
|
|
57
|
-
clearTimeout(this._debounceTimers.get(fullPath));
|
|
58
|
-
}
|
|
59
|
-
this._debounceTimers.set(fullPath, setTimeout(() => {
|
|
60
|
-
this._debounceTimers.delete(fullPath);
|
|
61
|
-
this._onFileChange(directory, filename, eventType);
|
|
62
|
-
}, this.debounceMs));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
this._watchers.push(watcher);
|
|
66
|
-
this.emit('watching', { directory: path.resolve(directory) });
|
|
67
|
-
} catch (e) {
|
|
68
|
-
this.emit('error', e);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return this;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
_onFileChange(baseDir, filename, eventType) {
|
|
75
|
-
if (!this._running) return;
|
|
76
|
-
|
|
77
|
-
// Skip hidden files, node_modules, .git
|
|
78
|
-
if (filename.startsWith('.') || filename.includes('node_modules') || filename.includes('.git')) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Skip non-code files
|
|
83
|
-
const ext = path.extname(filename).toLowerCase();
|
|
84
|
-
const codeExts = ['.js', '.ts', '.py', '.sh', '.md', '.json', '.yaml', '.yml', '.toml'];
|
|
85
|
-
if (!codeExts.includes(ext)) return;
|
|
86
|
-
|
|
87
|
-
const fullPath = path.join(baseDir, filename);
|
|
88
|
-
if (!fs.existsSync(fullPath)) {
|
|
89
|
-
this.emit('deleted', { file: filename });
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
this._scanCount++;
|
|
94
|
-
const scanner = new GuardScanner({
|
|
95
|
-
summaryOnly: true,
|
|
96
|
-
strict: this.strict,
|
|
97
|
-
soulLock: this.soulLock,
|
|
98
|
-
quiet: true,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Find the skill directory (parent directory of the changed file)
|
|
102
|
-
const skillDir = path.dirname(fullPath);
|
|
103
|
-
const skillName = path.basename(skillDir);
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
scanner.scanSkill(skillDir, skillName);
|
|
107
|
-
const findings = scanner.findings[0];
|
|
108
|
-
|
|
109
|
-
if (findings && findings.findings.length > 0) {
|
|
110
|
-
this._alertCount += findings.findings.length;
|
|
111
|
-
const result = {
|
|
112
|
-
file: filename,
|
|
113
|
-
skill: skillName,
|
|
114
|
-
eventType,
|
|
115
|
-
verdict: findings.verdict,
|
|
116
|
-
risk: findings.risk,
|
|
117
|
-
findingCount: findings.findings.length,
|
|
118
|
-
findings: findings.findings,
|
|
119
|
-
timestamp: new Date().toISOString(),
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
this.emit('alert', result);
|
|
123
|
-
|
|
124
|
-
if (!this.quiet) {
|
|
125
|
-
const icon = findings.verdict === 'MALICIOUS' ? '🚨' :
|
|
126
|
-
findings.verdict === 'SUSPICIOUS' ? '⚠️' : '🔶';
|
|
127
|
-
console.log(`${icon} [${new Date().toLocaleTimeString()}] ${findings.verdict} — ${filename}`);
|
|
128
|
-
console.log(` Risk: ${findings.risk} | Findings: ${findings.findings.length}`);
|
|
129
|
-
if (this.verbose) {
|
|
130
|
-
for (const f of findings.findings.slice(0, 5)) {
|
|
131
|
-
console.log(` → [${f.severity}] ${f.id}: ${f.desc}`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
} else {
|
|
136
|
-
this.emit('clean', { file: filename, skill: skillName });
|
|
137
|
-
if (this.verbose && !this.quiet) {
|
|
138
|
-
console.log(`✅ [${new Date().toLocaleTimeString()}] CLEAN — ${filename}`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
} catch (e) {
|
|
142
|
-
this.emit('error', { file: filename, error: e.message });
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
stop() {
|
|
147
|
-
this._running = false;
|
|
148
|
-
for (const w of this._watchers) {
|
|
149
|
-
try { w.close(); } catch (e) { /* ignore */ }
|
|
150
|
-
}
|
|
151
|
-
this._watchers = [];
|
|
152
|
-
for (const t of this._debounceTimers.values()) {
|
|
153
|
-
clearTimeout(t);
|
|
154
|
-
}
|
|
155
|
-
this._debounceTimers.clear();
|
|
156
|
-
this.emit('stopped', { scanCount: this._scanCount, alertCount: this._alertCount });
|
|
157
|
-
return { scanCount: this._scanCount, alertCount: this._alertCount };
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
getStats() {
|
|
161
|
-
return {
|
|
162
|
-
running: this._running,
|
|
163
|
-
scanCount: this._scanCount,
|
|
164
|
-
alertCount: this._alertCount,
|
|
165
|
-
watcherCount: this._watchers.length,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
module.exports = { GuardWatcher };
|