@musashimiyamoto/agent-guard 0.2.2 β 0.3.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/README.md +1 -11
- package/package.json +1 -1
- package/src/cli.js +1 -1
- package/src/rules/index.js +67 -16
- package/src/scanner.js +17 -4
package/README.md
CHANGED
|
@@ -52,8 +52,7 @@ Every skill should include `skill.manifest.json`:
|
|
|
52
52
|
"metadata": {
|
|
53
53
|
"name": "my-skill",
|
|
54
54
|
"version": "1.0.0",
|
|
55
|
-
"author": "
|
|
56
|
-
"isnad_root": "human:owner"
|
|
55
|
+
"author": "developer-name"
|
|
57
56
|
},
|
|
58
57
|
"permissions": {
|
|
59
58
|
"network": {
|
|
@@ -73,15 +72,6 @@ Every skill should include `skill.manifest.json`:
|
|
|
73
72
|
}
|
|
74
73
|
```
|
|
75
74
|
|
|
76
|
-
## Trust Tiers (IsnΔd)
|
|
77
|
-
|
|
78
|
-
| Tier | Name | Meaning |
|
|
79
|
-
|------|------|---------|
|
|
80
|
-
| π₯ | Thiqah | Audited by 3+ trusted agents, signed |
|
|
81
|
-
| π₯ | Hasan | Reputable author, signed manifest |
|
|
82
|
-
| π₯ | Da'if | Unsigned/unaudited, sandbox required |
|
|
83
|
-
| π | Matruk | Confirmed malicious, blocked |
|
|
84
|
-
|
|
85
75
|
## Exit Codes
|
|
86
76
|
|
|
87
77
|
- `0` β No critical findings
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { resolve } from 'path';
|
|
|
8
8
|
|
|
9
9
|
import { createProxy } from './proxy/index.js';
|
|
10
10
|
|
|
11
|
-
const VERSION = '0.
|
|
11
|
+
const VERSION = '0.3.1';
|
|
12
12
|
|
|
13
13
|
const FEEDBACK_URL = 'https://github.com/MusashiMiyamoto1-cloud/agent-guard/issues/new';
|
|
14
14
|
const REPO_URL = 'https://github.com/MusashiMiyamoto1-cloud/agent-guard';
|
package/src/rules/index.js
CHANGED
|
@@ -74,10 +74,13 @@ export const rules = [
|
|
|
74
74
|
severity: 'critical',
|
|
75
75
|
description: 'Finds OpenAI API keys in agent files',
|
|
76
76
|
patterns: [
|
|
77
|
-
/sk-[a-zA-Z0-
|
|
78
|
-
/sk-
|
|
77
|
+
/sk-proj-[a-zA-Z0-9_-]{10,}/g,
|
|
78
|
+
/sk-live-[a-zA-Z0-9_-]{10,}/g,
|
|
79
|
+
/sk-test-[a-zA-Z0-9_-]{10,}/g,
|
|
80
|
+
/sk-[a-zA-Z0-9_-]{20,}/g,
|
|
81
|
+
/OPENAI_API_KEY\s*[:=]\s*["']?[a-zA-Z0-9_-]{10,}["']?/g
|
|
79
82
|
],
|
|
80
|
-
files: ['
|
|
83
|
+
files: ['*']
|
|
81
84
|
},
|
|
82
85
|
{
|
|
83
86
|
id: 'SEC-002',
|
|
@@ -89,7 +92,7 @@ export const rules = [
|
|
|
89
92
|
/gho_[a-zA-Z0-9]{36}/g,
|
|
90
93
|
/github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}/g
|
|
91
94
|
],
|
|
92
|
-
files: ['
|
|
95
|
+
files: ['*']
|
|
93
96
|
},
|
|
94
97
|
{
|
|
95
98
|
id: 'SEC-003',
|
|
@@ -120,11 +123,12 @@ export const rules = [
|
|
|
120
123
|
severity: 'high',
|
|
121
124
|
description: 'Finds generic hardcoded secrets',
|
|
122
125
|
patterns: [
|
|
123
|
-
/api[_-]?key\s*[:=]\s*["'][a-zA-Z0-
|
|
124
|
-
/secret\s*[:=]\s*["'][a-zA-Z0-
|
|
125
|
-
/token\s*[:=]\s*["'][a-zA-Z0-
|
|
126
|
+
/api[_-]?key\s*[:=]\s*["'][a-zA-Z0-9_-]{10,}["']/gi,
|
|
127
|
+
/secret\s*[:=]\s*["'][a-zA-Z0-9_-]{10,}["']/gi,
|
|
128
|
+
/token\s*[:=]\s*["'][a-zA-Z0-9_-]{10,}["']/gi,
|
|
129
|
+
/["']?apiKey["']?\s*[:=]\s*["'][a-zA-Z0-9_-]{10,}["']/gi
|
|
126
130
|
],
|
|
127
|
-
files: ['
|
|
131
|
+
files: ['*']
|
|
128
132
|
},
|
|
129
133
|
|
|
130
134
|
{
|
|
@@ -211,9 +215,11 @@ export const rules = [
|
|
|
211
215
|
severity: 'critical',
|
|
212
216
|
description: 'Finds Stripe API keys',
|
|
213
217
|
patterns: [
|
|
214
|
-
/sk_live_[0-9a-zA-Z]{
|
|
215
|
-
/sk_test_[0-9a-zA-Z]{
|
|
216
|
-
/rk_live_[0-9a-zA-Z]{
|
|
218
|
+
/sk_live_[0-9a-zA-Z]{8,}/g,
|
|
219
|
+
/sk_test_[0-9a-zA-Z]{8,}/g,
|
|
220
|
+
/rk_live_[0-9a-zA-Z]{8,}/g,
|
|
221
|
+
/pk_live_[0-9a-zA-Z]{8,}/g,
|
|
222
|
+
/pk_test_[0-9a-zA-Z]{8,}/g
|
|
217
223
|
],
|
|
218
224
|
files: ['*']
|
|
219
225
|
},
|
|
@@ -375,12 +381,57 @@ export const rules = [
|
|
|
375
381
|
severity: 'critical',
|
|
376
382
|
description: 'Tool allows unrestricted filesystem or network access',
|
|
377
383
|
patterns: [
|
|
378
|
-
/allow_all_tools
|
|
379
|
-
/tool_restrictions
|
|
380
|
-
/sandbox
|
|
381
|
-
/unrestricted
|
|
384
|
+
/allow_all_tools["']?\s*[:=]\s*true/gi,
|
|
385
|
+
/tool_restrictions["']?\s*[:=]\s*false/gi,
|
|
386
|
+
/["']?sandbox["']?\s*[:=]\s*["']?false["']?/gi,
|
|
387
|
+
/["']?unrestricted["']?\s*[:=]\s*["']?true["']?/gi
|
|
388
|
+
],
|
|
389
|
+
files: ['*.yaml', '*.yml', '*.json', 'config.*', 'AGENTS.md', 'openclaw.json']
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
// Wildcard Allowlist
|
|
393
|
+
{
|
|
394
|
+
id: 'TOOL-002',
|
|
395
|
+
name: 'Wildcard Allowlist',
|
|
396
|
+
severity: 'critical',
|
|
397
|
+
description: 'Tool or skill has wildcard allowlist permitting all operations',
|
|
398
|
+
patterns: [
|
|
399
|
+
/allowlist["']?\s*[:=]\s*\[\s*["']\*["']\s*\]/gi,
|
|
400
|
+
/allowlist["']?\s*[:=]\s*["']\*["']/gi,
|
|
401
|
+
/allow["']?\s*[:=]\s*\[\s*["']\*["']\s*\]/gi,
|
|
402
|
+
/permissions["']?\s*[:=]\s*["']\*["']/gi
|
|
403
|
+
],
|
|
404
|
+
files: ['*.yaml', '*.yml', '*.json', 'config.*', 'openclaw.json']
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
// Database URL with embedded credentials
|
|
408
|
+
{
|
|
409
|
+
id: 'SEC-017',
|
|
410
|
+
name: 'Database URL with Credentials',
|
|
411
|
+
severity: 'critical',
|
|
412
|
+
description: 'Database connection string with embedded password',
|
|
413
|
+
patterns: [
|
|
414
|
+
/(?:postgres|mysql|mongodb|redis|amqp)(?:ql)?:\/\/[^:]+:[^@]+@[^\s"']+/gi,
|
|
415
|
+
/DATABASE_URL\s*[:=]\s*["']?[^\s"']+:\/\/[^:]+:[^@]+@/gi
|
|
416
|
+
],
|
|
417
|
+
files: ['*']
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
// Prompt Injection Vulnerability
|
|
421
|
+
{
|
|
422
|
+
id: 'INJ-002',
|
|
423
|
+
name: 'Prompt Injection Risk',
|
|
424
|
+
severity: 'high',
|
|
425
|
+
description: 'System prompt contains patterns vulnerable to injection attacks',
|
|
426
|
+
patterns: [
|
|
427
|
+
/follow\s+(?:all|any)\s+instructions/gi,
|
|
428
|
+
/do\s+whatever\s+(?:the\s+)?(?:user|they|anyone)\s+asks/gi,
|
|
429
|
+
/obey\s+(?:all|any)\s+(?:commands|instructions|requests)/gi,
|
|
430
|
+
/no\s+restrictions/gi,
|
|
431
|
+
/ignore\s+(?:previous|prior|all)\s+(?:instructions|rules|guidelines)/gi,
|
|
432
|
+
/you\s+have\s+no\s+(?:limits|boundaries|restrictions)/gi
|
|
382
433
|
],
|
|
383
|
-
files: ['
|
|
434
|
+
files: ['SOUL.md', 'SYSTEM.md', '*.md', 'system_prompt.*']
|
|
384
435
|
}
|
|
385
436
|
];
|
|
386
437
|
|
package/src/scanner.js
CHANGED
|
@@ -105,6 +105,8 @@ export class Scanner {
|
|
|
105
105
|
if (pattern.startsWith('*.')) {
|
|
106
106
|
const ext = pattern.slice(1);
|
|
107
107
|
if (fileName.endsWith(ext)) return true;
|
|
108
|
+
} else if (pattern === '.env' && (fileName === '.env' || fileName.startsWith('.env.'))) {
|
|
109
|
+
return true;
|
|
108
110
|
} else if (fileName === pattern) {
|
|
109
111
|
return true;
|
|
110
112
|
} else if (pattern.includes('*')) {
|
|
@@ -175,6 +177,12 @@ export class Scanner {
|
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
|
|
180
|
+
// Deduplicate: skip if same rule+file+line already recorded
|
|
181
|
+
const isDuplicate = this.findings.some(f =>
|
|
182
|
+
f.rule === rule.id && f.file === filePath && f.line === lineNum
|
|
183
|
+
);
|
|
184
|
+
if (isDuplicate) return;
|
|
185
|
+
|
|
178
186
|
// Redact sensitive values
|
|
179
187
|
const redactedMatch = this.redactSensitive(match);
|
|
180
188
|
|
|
@@ -207,11 +215,16 @@ export class Scanner {
|
|
|
207
215
|
const low = this.findings.filter(f => f.severity === 'low');
|
|
208
216
|
|
|
209
217
|
// Calculate score (0-100)
|
|
210
|
-
// Weights: Critical=30, High=
|
|
211
|
-
//
|
|
218
|
+
// Weights: Critical=30, High=15, Medium=5, Low=2
|
|
219
|
+
// But multiple criticals compound: 2+ criticals = max 30, 4+ = max 10
|
|
220
|
+
const criticalPenalty = critical.length === 0 ? 0 :
|
|
221
|
+
critical.length === 1 ? 30 :
|
|
222
|
+
critical.length <= 3 ? 30 + (critical.length - 1) * 20 :
|
|
223
|
+
90 + (critical.length - 3) * 3; // 4+ criticals β near zero
|
|
224
|
+
|
|
212
225
|
const score = Math.max(0, 100 - (
|
|
213
|
-
|
|
214
|
-
high.length *
|
|
226
|
+
criticalPenalty +
|
|
227
|
+
high.length * 15 +
|
|
215
228
|
medium.length * 5 +
|
|
216
229
|
low.length * 2
|
|
217
230
|
));
|