@soulofzephir/pi-skill-pentesting 1.0.1 → 1.0.2
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/package.json
CHANGED
|
@@ -43,6 +43,8 @@ This skill auto-loads when user mentions:
|
|
|
43
43
|
- exposed files, .env, .git exposed
|
|
44
44
|
- CORS, JWT, GraphQL security
|
|
45
45
|
- "test keamanan", "cek security", "audit keamanan"
|
|
46
|
+
- **"test skill", "check skill", "validate skill"**
|
|
47
|
+
- **"skill health", "skill status", "skill diagnostics"**
|
|
46
48
|
|
|
47
49
|
---
|
|
48
50
|
|
|
@@ -208,6 +210,17 @@ skills/pentesting/
|
|
|
208
210
|
|
|
209
211
|
## 🚀 QUICK COMMANDS
|
|
210
212
|
|
|
213
|
+
### Skill Health Check 🔴 **NEW**
|
|
214
|
+
```bash
|
|
215
|
+
# Windows PowerShell
|
|
216
|
+
.\tools\test-skill.ps1
|
|
217
|
+
.\tools\test-skill.ps1 -Verbose
|
|
218
|
+
|
|
219
|
+
# Linux/Mac
|
|
220
|
+
chmod +x tools/test-skill.sh
|
|
221
|
+
./tools/test-skill.sh
|
|
222
|
+
```
|
|
223
|
+
|
|
211
224
|
### Security Headers
|
|
212
225
|
```bash
|
|
213
226
|
# Linux/Mac
|
|
@@ -308,6 +321,8 @@ F (0-29): Critical
|
|
|
308
321
|
- "test CORS" → Load CORS checklist
|
|
309
322
|
- "test JWT" → Load JWT checklist
|
|
310
323
|
- "test GraphQL" → Load GraphQL checklist
|
|
324
|
+
- **"test skill" / "check skill" / "validate skill"** → Run skill health check
|
|
325
|
+
- **"skill status" / "skill health"** → Show skill installation status
|
|
311
326
|
|
|
312
327
|
---
|
|
313
328
|
|
|
@@ -331,6 +346,12 @@ User: "audit JWT security"
|
|
|
331
346
|
|
|
332
347
|
User: "GraphQL security check"
|
|
333
348
|
→ Run GraphQL security tests
|
|
349
|
+
|
|
350
|
+
User: "test skill"
|
|
351
|
+
→ Run skill health check → Show test results
|
|
352
|
+
|
|
353
|
+
User: "validate skill installation"
|
|
354
|
+
→ Verify all files exist → Show skill status
|
|
334
355
|
```
|
|
335
356
|
|
|
336
357
|
---
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# Skill Test Suite v1.0
|
|
2
|
+
# Tests if the pentesting skill is properly installed
|
|
3
|
+
|
|
4
|
+
# Get skill root from script location
|
|
5
|
+
$ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
6
|
+
$SkillRoot = Split-Path -Parent $ScriptRoot
|
|
7
|
+
|
|
8
|
+
$ErrorActionPreference = "Continue"
|
|
9
|
+
|
|
10
|
+
$PASS = 0
|
|
11
|
+
$FAIL = 0
|
|
12
|
+
$WARN = 0
|
|
13
|
+
|
|
14
|
+
# ═══════════════════════════════════════════════════════════
|
|
15
|
+
# BANNER
|
|
16
|
+
# ═══════════════════════════════════════════════════════════
|
|
17
|
+
|
|
18
|
+
Write-Host ""
|
|
19
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
20
|
+
Write-Host " SKILL TEST SUITE v1.0" -ForegroundColor Cyan
|
|
21
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
22
|
+
Write-Host ""
|
|
23
|
+
|
|
24
|
+
# ═══════════════════════════════════════════════════════════
|
|
25
|
+
# PHASE 1: FILE STRUCTURE
|
|
26
|
+
# ═══════════════════════════════════════════════════════════
|
|
27
|
+
|
|
28
|
+
Write-Host "Phase 1: File Structure" -ForegroundColor Yellow
|
|
29
|
+
|
|
30
|
+
$testPass = { param($n,$m) Write-Host " PASS: $m" -ForegroundColor Green; $script:PASS++ }
|
|
31
|
+
$testFail = { param($n,$m) Write-Host " FAIL: $m" -ForegroundColor Red; $script:FAIL++ }
|
|
32
|
+
$testWarn = { param($n,$m) Write-Host " WARN: $m" -ForegroundColor Yellow; $script:WARN++ }
|
|
33
|
+
|
|
34
|
+
if (Test-Path "$SkillRoot\SKILL.md") {
|
|
35
|
+
& $testPass "SKILL.md" "SKILL.md exists"
|
|
36
|
+
} else {
|
|
37
|
+
& $testFail "SKILL.md" "SKILL.md missing"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (Test-Path "$SkillRoot\checklists") {
|
|
41
|
+
$c = (Get-ChildItem "$SkillRoot\checklists\*.md" -ErrorAction SilentlyContinue).Count
|
|
42
|
+
& $testPass "checklists" "Checklists dir: $c files"
|
|
43
|
+
} else {
|
|
44
|
+
& $testFail "checklists" "Checklists dir missing"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Test-Path "$SkillRoot\tools") {
|
|
48
|
+
$t = (Get-ChildItem "$SkillRoot\tools" -File -ErrorAction SilentlyContinue).Count
|
|
49
|
+
& $testPass "tools" "Tools dir: $t files"
|
|
50
|
+
} else {
|
|
51
|
+
& $testFail "tools" "Tools dir missing"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (Test-Path "$SkillRoot\reports") {
|
|
55
|
+
& $testPass "reports" "Reports dir exists"
|
|
56
|
+
} else {
|
|
57
|
+
& $testFail "reports" "Reports dir missing"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# ═══════════════════════════════════════════════════════════
|
|
61
|
+
# PHASE 2: SKILL.MD VALIDATION
|
|
62
|
+
# ═══════════════════════════════════════════════════════════
|
|
63
|
+
|
|
64
|
+
Write-Host ""
|
|
65
|
+
Write-Host "Phase 2: SKILL.md Validation" -ForegroundColor Yellow
|
|
66
|
+
|
|
67
|
+
$skillContent = Get-Content "$SkillRoot\SKILL.md" -Raw -ErrorAction SilentlyContinue
|
|
68
|
+
|
|
69
|
+
if ($skillContent -match "^---") {
|
|
70
|
+
& $testPass "frontmatter" "Frontmatter found"
|
|
71
|
+
} else {
|
|
72
|
+
& $testFail "frontmatter" "Frontmatter missing"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if ($skillContent -match "(?m)^name:\s") {
|
|
76
|
+
$name = [regex]::Match($skillContent, "(?m)^name:\s*(.+)$").Groups[1].Value.Trim()
|
|
77
|
+
& $testPass "name" "Name: $name"
|
|
78
|
+
} else {
|
|
79
|
+
& $testFail "name" "Name field missing"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if ($skillContent -match "(?m)^description:\s") {
|
|
83
|
+
& $testPass "description" "Description found"
|
|
84
|
+
} else {
|
|
85
|
+
& $testFail "description" "Description missing"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if ($skillContent -match "(?i)auto-load|triggers|pentest|security") {
|
|
89
|
+
& $testPass "triggers" "Auto-load triggers defined"
|
|
90
|
+
} else {
|
|
91
|
+
& $testWarn "triggers" "Auto-load triggers unclear"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# ═══════════════════════════════════════════════════════════
|
|
95
|
+
# PHASE 3: CHECKLISTS
|
|
96
|
+
# ═══════════════════════════════════════════════════════════
|
|
97
|
+
|
|
98
|
+
Write-Host ""
|
|
99
|
+
Write-Host "Phase 3: Checklists" -ForegroundColor Yellow
|
|
100
|
+
|
|
101
|
+
$required = @("headers.md","owasp.md","ports.md","injection.md")
|
|
102
|
+
$recommended = @("exposed-files.md","cors.md","jwt.md","graphql.md")
|
|
103
|
+
|
|
104
|
+
foreach ($f in $required) {
|
|
105
|
+
if (Test-Path "$SkillRoot\checklists\$f") {
|
|
106
|
+
& $testPass $f "$f found"
|
|
107
|
+
} else {
|
|
108
|
+
& $testFail $f "$f missing (REQUIRED)"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
foreach ($f in $recommended) {
|
|
113
|
+
if (Test-Path "$SkillRoot\checklists\$f") {
|
|
114
|
+
& $testPass $f "$f found"
|
|
115
|
+
} else {
|
|
116
|
+
& $testWarn $f "$f not found (recommended)"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# ═══════════════════════════════════════════════════════════
|
|
121
|
+
# PHASE 4: TOOLS
|
|
122
|
+
# ═══════════════════════════════════════════════════════════
|
|
123
|
+
|
|
124
|
+
Write-Host ""
|
|
125
|
+
Write-Host "Phase 4: Tools" -ForegroundColor Yellow
|
|
126
|
+
|
|
127
|
+
$requiredTools = @("header-scan.ps1","header-scan.sh")
|
|
128
|
+
$recommendedTools = @("exposed-files-scan.ps1","exposed-files-scan.sh","full-scan.ps1","full-scan.sh","test-skill.ps1","test-skill.sh")
|
|
129
|
+
|
|
130
|
+
foreach ($t in $requiredTools) {
|
|
131
|
+
if (Test-Path "$SkillRoot\tools\$t") {
|
|
132
|
+
$s = [math]::Round((Get-Item "$SkillRoot\tools\$t").Length / 1KB, 1)
|
|
133
|
+
& $testPass $t "$t found ($s KB)"
|
|
134
|
+
} else {
|
|
135
|
+
& $testFail $t "$t missing (REQUIRED)"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
foreach ($t in $recommendedTools) {
|
|
140
|
+
if (Test-Path "$SkillRoot\tools\$t") {
|
|
141
|
+
& $testPass $t "$t found"
|
|
142
|
+
} else {
|
|
143
|
+
& $testWarn $t "$t not found (recommended)"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# ═══════════════════════════════════════════════════════════
|
|
148
|
+
# PHASE 5: CONTENT VALIDATION
|
|
149
|
+
# ═══════════════════════════════════════════════════════════
|
|
150
|
+
|
|
151
|
+
Write-Host ""
|
|
152
|
+
Write-Host "Phase 5: Content" -ForegroundColor Yellow
|
|
153
|
+
|
|
154
|
+
if ($skillContent -match "Security Headers|Port Scanning|SQL Injection|XSS|OWASP") {
|
|
155
|
+
& $testPass "capabilities" "Core capabilities documented"
|
|
156
|
+
} else {
|
|
157
|
+
& $testWarn "capabilities" "Core capabilities unclear"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if ($skillContent -match "Quick Commands|bash|powershell") {
|
|
161
|
+
& $testPass "commands" "Quick commands documented"
|
|
162
|
+
} else {
|
|
163
|
+
& $testWarn "commands" "Quick commands unclear"
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if ($skillContent -match "Example|pentest|scan") {
|
|
167
|
+
& $testPass "examples" "Trigger examples found"
|
|
168
|
+
} else {
|
|
169
|
+
& $testWarn "examples" "Trigger examples unclear"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
# Check injection.md content
|
|
173
|
+
$injContent = Get-Content "$SkillRoot\checklists\injection.md" -Raw -ErrorAction SilentlyContinue
|
|
174
|
+
if ($injContent -match "SQL|sqlmap") {
|
|
175
|
+
& $testPass "injection" "Injection payloads found"
|
|
176
|
+
} else {
|
|
177
|
+
& $testWarn "injection" "Injection payloads unclear"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Check exposed-files.md content
|
|
181
|
+
$expContent = Get-Content "$SkillRoot\checklists\exposed-files.md" -Raw -ErrorAction SilentlyContinue
|
|
182
|
+
if ($expContent -match "\.env|\.git|backup|phpmyadmin") {
|
|
183
|
+
& $testPass "exposed" "Exposed files paths found"
|
|
184
|
+
} else {
|
|
185
|
+
& $testWarn "exposed" "Exposed files paths unclear"
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
# ═══════════════════════════════════════════════════════════
|
|
189
|
+
# PHASE 6: SYNTAX CHECK
|
|
190
|
+
# ═══════════════════════════════════════════════════════════
|
|
191
|
+
|
|
192
|
+
Write-Host ""
|
|
193
|
+
Write-Host "Phase 6: Syntax Check" -ForegroundColor Yellow
|
|
194
|
+
|
|
195
|
+
foreach ($f in @("header-scan.ps1","exposed-files-scan.ps1","full-scan.ps1","test-skill.ps1")) {
|
|
196
|
+
$file = "$SkillRoot\tools\$f"
|
|
197
|
+
if (Test-Path $file) {
|
|
198
|
+
$errors = $null
|
|
199
|
+
$null = [System.Management.Automation.PSParser]::Tokenize((Get-Content $file -Raw), [ref]$errors)
|
|
200
|
+
if ($errors.Count -eq 0) {
|
|
201
|
+
& $testPass "syntax-$f" "$f syntax valid"
|
|
202
|
+
} else {
|
|
203
|
+
& $testFail "syntax-$f" "$f has $($errors.Count) syntax errors"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# Check shell scripts
|
|
209
|
+
foreach ($f in @("header-scan.sh","exposed-files-scan.sh","full-scan.sh","test-skill.sh")) {
|
|
210
|
+
$file = "$SkillRoot\tools\$f"
|
|
211
|
+
if (Test-Path $file) {
|
|
212
|
+
$first = Get-Content $file -First 1 -ErrorAction SilentlyContinue
|
|
213
|
+
if ($first -match "^#!") {
|
|
214
|
+
& $testPass "shebang-$f" "$f has shebang"
|
|
215
|
+
} else {
|
|
216
|
+
& $testWarn "shebang-$f" "$f missing shebang"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
# ═══════════════════════════════════════════════════════════
|
|
222
|
+
# PHASE 7: SPECIAL FEATURES
|
|
223
|
+
# ═══════════════════════════════════════════════════════════
|
|
224
|
+
|
|
225
|
+
Write-Host ""
|
|
226
|
+
Write-Host "Phase 7: Special Features" -ForegroundColor Yellow
|
|
227
|
+
|
|
228
|
+
if ($skillContent -match "Phase \d") {
|
|
229
|
+
$phases = ([regex]::Matches($skillContent, "Phase \d+")).Count
|
|
230
|
+
& $testPass "phases" "$phases test phases defined"
|
|
231
|
+
} else {
|
|
232
|
+
& $testWarn "phases" "Test phases unclear"
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if ($skillContent -match "site/.*\.md|domain.*date") {
|
|
236
|
+
& $testPass "report-format" "Report format documented"
|
|
237
|
+
} else {
|
|
238
|
+
& $testWarn "report-format" "Report format unclear"
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if ($skillContent -match "disclaimer|IMPORTANT|REMINDER") {
|
|
242
|
+
& $testPass "disclaimer" "Disclaimer found"
|
|
243
|
+
} else {
|
|
244
|
+
& $testWarn "disclaimer" "Disclaimer not found"
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if ($skillContent -match "test skill|check skill|validate skill") {
|
|
248
|
+
& $testPass "skill-test" "Skill test triggers found"
|
|
249
|
+
} else {
|
|
250
|
+
& $testWarn "skill-test" "Skill test triggers not found"
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
# ═══════════════════════════════════════════════════════════
|
|
254
|
+
# SUMMARY
|
|
255
|
+
# ═══════════════════════════════════════════════════════════
|
|
256
|
+
|
|
257
|
+
Write-Host ""
|
|
258
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
259
|
+
Write-Host " SUMMARY" -ForegroundColor Cyan
|
|
260
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
261
|
+
Write-Host ""
|
|
262
|
+
Write-Host " PASS: $PASS" -ForegroundColor Green
|
|
263
|
+
Write-Host " WARN: $WARN" -ForegroundColor Yellow
|
|
264
|
+
Write-Host " FAIL: $FAIL" -ForegroundColor Red
|
|
265
|
+
Write-Host ""
|
|
266
|
+
|
|
267
|
+
$Total = $PASS + $WARN + $FAIL
|
|
268
|
+
$Rate = if ($Total -gt 0) { [math]::Round(($PASS / $Total) * 100, 1) } else { 0 }
|
|
269
|
+
|
|
270
|
+
Write-Host " Pass Rate: $Rate%"
|
|
271
|
+
Write-Host ""
|
|
272
|
+
|
|
273
|
+
$Health = if ($Total -gt 0) { [math]::Round((($PASS * 2 + $WARN) / ($Total * 2)) * 100, 1) } else { 0 }
|
|
274
|
+
|
|
275
|
+
Write-Host " Health Score: $Health%" -ForegroundColor $(if ($Health -ge 90) { "Green" } elseif ($Health -ge 70) { "Yellow" } else { "Red" })
|
|
276
|
+
Write-Host ""
|
|
277
|
+
|
|
278
|
+
if ($Health -ge 90) {
|
|
279
|
+
Write-Host " Status: EXCELLENT - Production ready!" -ForegroundColor Green
|
|
280
|
+
} elseif ($Health -ge 70) {
|
|
281
|
+
Write-Host " Status: GOOD - Minor improvements needed" -ForegroundColor Yellow
|
|
282
|
+
} else {
|
|
283
|
+
Write-Host " Status: NEEDS WORK - Issues found" -ForegroundColor Red
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
Write-Host ""
|
|
287
|
+
Write-Host " Completed: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Gray
|
|
288
|
+
Write-Host "========================================" -ForegroundColor Cyan
|
|
289
|
+
Write-Host ""
|
|
290
|
+
|
|
291
|
+
if ($FAIL -gt 5) { exit 1 } else { exit 0 }
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Skill Test Suite v1.0
|
|
3
|
+
# Tests if the pentesting skill is properly installed
|
|
4
|
+
|
|
5
|
+
# Colors
|
|
6
|
+
RED='\033[0;31m'
|
|
7
|
+
GREEN='\033[0;32m'
|
|
8
|
+
YELLOW='\033[1;33m'
|
|
9
|
+
CYAN='\033[0;36m'
|
|
10
|
+
NC='\033[0m' # No Color
|
|
11
|
+
|
|
12
|
+
PASS=0
|
|
13
|
+
FAIL=0
|
|
14
|
+
WARN=0
|
|
15
|
+
|
|
16
|
+
# Get skill root
|
|
17
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
18
|
+
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
19
|
+
|
|
20
|
+
# ═══════════════════════════════════════════════════════════
|
|
21
|
+
# TEST FUNCTION
|
|
22
|
+
# ═══════════════════════════════════════════════════════════
|
|
23
|
+
|
|
24
|
+
test_check() {
|
|
25
|
+
local name="$1"
|
|
26
|
+
local command="$2"
|
|
27
|
+
|
|
28
|
+
echo ""
|
|
29
|
+
echo -n "Testing: $name ... "
|
|
30
|
+
|
|
31
|
+
if eval "$command" > /dev/null 2>&1; then
|
|
32
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
33
|
+
PASS=$((PASS + 1))
|
|
34
|
+
return 0
|
|
35
|
+
else
|
|
36
|
+
# Try alternative check
|
|
37
|
+
if eval "$command" 2>/dev/null; then
|
|
38
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
39
|
+
PASS=$((PASS + 1))
|
|
40
|
+
return 0
|
|
41
|
+
else
|
|
42
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
43
|
+
FAIL=$((FAIL + 1))
|
|
44
|
+
return 1
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# ═══════════════════════════════════════════════════════════
|
|
50
|
+
# BANNER
|
|
51
|
+
# ═══════════════════════════════════════════════════════════
|
|
52
|
+
|
|
53
|
+
echo ""
|
|
54
|
+
echo -e "${CYAN}╔═══════════════════════════════════════════════════╗${NC}"
|
|
55
|
+
echo -e "${CYAN}║ 🧪 Pentesting Skill Test Suite v1.0 ║${NC}"
|
|
56
|
+
echo -e "${CYAN}╚═══════════════════════════════════════════════════╝${NC}"
|
|
57
|
+
echo ""
|
|
58
|
+
|
|
59
|
+
# ═══════════════════════════════════════════════════════════
|
|
60
|
+
# PHASE 1: FILE STRUCTURE
|
|
61
|
+
# ═══════════════════════════════════════════════════════════
|
|
62
|
+
|
|
63
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
64
|
+
echo -e "${CYAN}📁 Phase 1: File Structure${NC}"
|
|
65
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
66
|
+
|
|
67
|
+
echo ""
|
|
68
|
+
echo -n "Testing: Skill root exists ... "
|
|
69
|
+
if [ -d "$SKILL_ROOT" ]; then
|
|
70
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
71
|
+
PASS=$((PASS + 1))
|
|
72
|
+
else
|
|
73
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
74
|
+
FAIL=$((FAIL + 1))
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo -n "Testing: SKILL.md exists ... "
|
|
78
|
+
if [ -f "$SKILL_ROOT/SKILL.md" ]; then
|
|
79
|
+
SIZE=$(wc -c < "$SKILL_ROOT/SKILL.md" 2>/dev/null || echo "0")
|
|
80
|
+
echo -e "${GREEN}✅ PASS${NC} ($((SIZE/1024)) KB)"
|
|
81
|
+
PASS=$((PASS + 1))
|
|
82
|
+
else
|
|
83
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
84
|
+
FAIL=$((FAIL + 1))
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo -n "Testing: checklists directory exists ... "
|
|
88
|
+
if [ -d "$SKILL_ROOT/checklists" ]; then
|
|
89
|
+
COUNT=$(find "$SKILL_ROOT/checklists" -name "*.md" 2>/dev/null | wc -l)
|
|
90
|
+
echo -e "${GREEN}✅ PASS${NC} ($COUNT files)"
|
|
91
|
+
PASS=$((PASS + 1))
|
|
92
|
+
else
|
|
93
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
94
|
+
FAIL=$((FAIL + 1))
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
echo -n "Testing: tools directory exists ... "
|
|
98
|
+
if [ -d "$SKILL_ROOT/tools" ]; then
|
|
99
|
+
COUNT=$(find "$SKILL_ROOT/tools" -type f 2>/dev/null | wc -l)
|
|
100
|
+
echo -e "${GREEN}✅ PASS${NC} ($COUNT files)"
|
|
101
|
+
PASS=$((PASS + 1))
|
|
102
|
+
else
|
|
103
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
104
|
+
FAIL=$((FAIL + 1))
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# ═══════════════════════════════════════════════════════════
|
|
108
|
+
# PHASE 2: SKILL.MD VALIDATION
|
|
109
|
+
# ═══════════════════════════════════════════════════════════
|
|
110
|
+
|
|
111
|
+
echo ""
|
|
112
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
113
|
+
echo -e "${CYAN}📝 Phase 2: SKILL.md Validation${NC}"
|
|
114
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
115
|
+
|
|
116
|
+
echo -n "Testing: SKILL.md has frontmatter ... "
|
|
117
|
+
if grep -q "^---" "$SKILL_ROOT/SKILL.md" 2>/dev/null; then
|
|
118
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
119
|
+
PASS=$((PASS + 1))
|
|
120
|
+
else
|
|
121
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
122
|
+
FAIL=$((FAIL + 1))
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
echo -n "Testing: SKILL.md has name field ... "
|
|
126
|
+
if grep -q "^name:" "$SKILL_ROOT/SKILL.md" 2>/dev/null; then
|
|
127
|
+
NAME=$(grep "^name:" "$SKILL_ROOT/SKILL.md" | head -1 | sed 's/name://' | xargs)
|
|
128
|
+
echo -e "${GREEN}✅ PASS${NC} (name: $NAME)"
|
|
129
|
+
PASS=$((PASS + 1))
|
|
130
|
+
else
|
|
131
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
132
|
+
FAIL=$((FAIL + 1))
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
echo -n "Testing: SKILL.md has description field ... "
|
|
136
|
+
if grep -q "^description:" "$SKILL_ROOT/SKILL.md" 2>/dev/null; then
|
|
137
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
138
|
+
PASS=$((PASS + 1))
|
|
139
|
+
else
|
|
140
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
141
|
+
FAIL=$((FAIL + 1))
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
echo -n "Testing: SKILL.md has auto-load triggers ... "
|
|
145
|
+
if grep -qi "AUTO-LOAD\|auto-load\|TRIGGER\|trigger" "$SKILL_ROOT/SKILL.md" 2>/dev/null; then
|
|
146
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
147
|
+
PASS=$((PASS + 1))
|
|
148
|
+
else
|
|
149
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
150
|
+
WARN=$((WARN + 1))
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# ═══════════════════════════════════════════════════════════
|
|
154
|
+
# PHASE 3: CHECKLISTS VALIDATION
|
|
155
|
+
# ═══════════════════════════════════════════════════════════
|
|
156
|
+
|
|
157
|
+
echo ""
|
|
158
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
159
|
+
echo -e "${CYAN}📋 Phase 3: Checklists Validation${NC}"
|
|
160
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
161
|
+
|
|
162
|
+
REQUIRED_CHECKLISTS=("headers.md" "owasp.md" "ports.md" "injection.md")
|
|
163
|
+
RECOMMENDED_CHECKLISTS=("exposed-files.md" "cors.md" "jwt.md" "graphql.md")
|
|
164
|
+
|
|
165
|
+
for checklist in "${REQUIRED_CHECKLISTS[@]}"; do
|
|
166
|
+
echo -n "Testing: $checklist exists ... "
|
|
167
|
+
if [ -f "$SKILL_ROOT/checklists/$checklist" ]; then
|
|
168
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
169
|
+
PASS=$((PASS + 1))
|
|
170
|
+
else
|
|
171
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
172
|
+
FAIL=$((FAIL + 1))
|
|
173
|
+
fi
|
|
174
|
+
done
|
|
175
|
+
|
|
176
|
+
for checklist in "${RECOMMENDED_CHECKLISTS[@]}"; do
|
|
177
|
+
echo -n "Testing: $checklist exists (recommended) ... "
|
|
178
|
+
if [ -f "$SKILL_ROOT/checklists/$checklist" ]; then
|
|
179
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
180
|
+
PASS=$((PASS + 1))
|
|
181
|
+
else
|
|
182
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
183
|
+
WARN=$((WARN + 1))
|
|
184
|
+
fi
|
|
185
|
+
done
|
|
186
|
+
|
|
187
|
+
# ═══════════════════════════════════════════════════════════
|
|
188
|
+
# PHASE 4: TOOLS VALIDATION
|
|
189
|
+
# ═══════════════════════════════════════════════════════════
|
|
190
|
+
|
|
191
|
+
echo ""
|
|
192
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
193
|
+
echo -e "${CYAN}🔧 Phase 4: Tools Validation${NC}"
|
|
194
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
195
|
+
|
|
196
|
+
REQUIRED_TOOLS=("header-scan.sh" "header-scan.ps1")
|
|
197
|
+
RECOMMENDED_TOOLS=("exposed-files-scan.sh" "exposed-files-scan.ps1" "full-scan.sh" "full-scan.ps1")
|
|
198
|
+
|
|
199
|
+
for tool in "${REQUIRED_TOOLS[@]}"; do
|
|
200
|
+
echo -n "Testing: $tool exists ... "
|
|
201
|
+
if [ -f "$SKILL_ROOT/tools/$tool" ]; then
|
|
202
|
+
SIZE=$(wc -c < "$SKILL_ROOT/tools/$tool" 2>/dev/null || echo "0")
|
|
203
|
+
echo -e "${GREEN}✅ PASS${NC} ($((SIZE/1024)) KB)"
|
|
204
|
+
PASS=$((PASS + 1))
|
|
205
|
+
else
|
|
206
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
207
|
+
FAIL=$((FAIL + 1))
|
|
208
|
+
fi
|
|
209
|
+
done
|
|
210
|
+
|
|
211
|
+
for tool in "${RECOMMENDED_TOOLS[@]}"; do
|
|
212
|
+
echo -n "Testing: $tool exists (recommended) ... "
|
|
213
|
+
if [ -f "$SKILL_ROOT/tools/$tool" ]; then
|
|
214
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
215
|
+
PASS=$((PASS + 1))
|
|
216
|
+
else
|
|
217
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
218
|
+
WARN=$((WARN + 1))
|
|
219
|
+
fi
|
|
220
|
+
done
|
|
221
|
+
|
|
222
|
+
# ═══════════════════════════════════════════════════════════
|
|
223
|
+
# PHASE 5: CONTENT VALIDATION
|
|
224
|
+
# ═══════════════════════════════════════════════════════════
|
|
225
|
+
|
|
226
|
+
echo ""
|
|
227
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
228
|
+
echo -e "${CYAN}📄 Phase 5: Content Validation${NC}"
|
|
229
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
230
|
+
|
|
231
|
+
echo -n "Testing: SKILL.md has core capabilities ... "
|
|
232
|
+
CORE_COUNT=0
|
|
233
|
+
grep -qi "Security Headers\|Port Scanning\|SQL Injection\|XSS\|OWASP" "$SKILL_ROOT/SKILL.md" 2>/dev/null && CORE_COUNT=$((CORE_COUNT + 1))
|
|
234
|
+
if [ $CORE_COUNT -ge 4 ]; then
|
|
235
|
+
echo -e "${GREEN}✅ PASS${NC} ($CORE_COUNT/5 core capabilities)"
|
|
236
|
+
PASS=$((PASS + 1))
|
|
237
|
+
else
|
|
238
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
239
|
+
WARN=$((WARN + 1))
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
echo -n "Testing: SKILL.md has quick commands ... "
|
|
243
|
+
if grep -qi "QUICK\|Commands\|bash\|chmod" "$SKILL_ROOT/SKILL.md" 2>/dev/null; then
|
|
244
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
245
|
+
PASS=$((PASS + 1))
|
|
246
|
+
else
|
|
247
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
248
|
+
WARN=$((WARN + 1))
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
echo -n "Testing: injection.md has SQLi payloads ... "
|
|
252
|
+
if grep -qi "SQL\|sqlmap\|' OR \|UNION" "$SKILL_ROOT/checklists/injection.md" 2>/dev/null; then
|
|
253
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
254
|
+
PASS=$((PASS + 1))
|
|
255
|
+
else
|
|
256
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
257
|
+
WARN=$((WARN + 1))
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
# ═══════════════════════════════════════════════════════════
|
|
261
|
+
# PHASE 6: EXECUTABLE TESTS
|
|
262
|
+
# ═══════════════════════════════════════════════════════════
|
|
263
|
+
|
|
264
|
+
echo ""
|
|
265
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
266
|
+
echo -e "${CYAN}⚡ Phase 6: Executable Tests${NC}"
|
|
267
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
268
|
+
|
|
269
|
+
echo -n "Testing: header-scan.sh has shebang ... "
|
|
270
|
+
if [ -f "$SKILL_ROOT/tools/header-scan.sh" ]; then
|
|
271
|
+
FIRST_LINE=$(head -1 "$SKILL_ROOT/tools/header-scan.sh" 2>/dev/null)
|
|
272
|
+
if [[ "$FIRST_LINE" == "#!"* ]]; then
|
|
273
|
+
echo -e "${GREEN}✅ PASS${NC} ($FIRST_LINE)"
|
|
274
|
+
PASS=$((PASS + 1))
|
|
275
|
+
else
|
|
276
|
+
echo -e "${YELLOW}⚠️ WARN${NC} (no shebang)"
|
|
277
|
+
WARN=$((WARN + 1))
|
|
278
|
+
fi
|
|
279
|
+
else
|
|
280
|
+
echo -e "${YELLOW}⚠️ SKIP${NC} (file not found)"
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
echo -n "Testing: scripts are executable ... "
|
|
284
|
+
CHMOD_COUNT=0
|
|
285
|
+
for script in "$SKILL_ROOT/tools/"*.sh; do
|
|
286
|
+
if [ -f "$script" ]; then
|
|
287
|
+
chmod +x "$script" 2>/dev/null
|
|
288
|
+
CHMOD_COUNT=$((CHMOD_COUNT + 1))
|
|
289
|
+
fi
|
|
290
|
+
done
|
|
291
|
+
if [ $CHMOD_COUNT -gt 0 ]; then
|
|
292
|
+
echo -e "${GREEN}✅ PASS${NC} ($CHMOD_COUNT scripts made executable)"
|
|
293
|
+
PASS=$((PASS + 1))
|
|
294
|
+
else
|
|
295
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
296
|
+
WARN=$((WARN + 1))
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
# ═══════════════════════════════════════════════════════════
|
|
300
|
+
# SUMMARY
|
|
301
|
+
# ═══════════════════════════════════════════════════════════
|
|
302
|
+
|
|
303
|
+
echo ""
|
|
304
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
305
|
+
echo -e "${CYAN}📊 TEST SUMMARY${NC}"
|
|
306
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
307
|
+
echo ""
|
|
308
|
+
echo -e "${GREEN}✅ PASS: $PASS${NC}"
|
|
309
|
+
echo -e "${YELLOW}⚠️ WARN: $WARN${NC}"
|
|
310
|
+
echo -e "${RED}❌ FAIL: $FAIL${NC}"
|
|
311
|
+
echo ""
|
|
312
|
+
|
|
313
|
+
TOTAL=$((PASS + WARN + FAIL))
|
|
314
|
+
PASS_RATE=$(echo "scale=1; ($PASS / $TOTAL) * 100" | bc 2>/dev/null || echo "0")
|
|
315
|
+
|
|
316
|
+
echo "Pass Rate: $PASS_RATE%"
|
|
317
|
+
echo ""
|
|
318
|
+
|
|
319
|
+
# Skill Health Score
|
|
320
|
+
HEALTH_SCORE=$((PASS * 2 + WARN))
|
|
321
|
+
MAX_SCORE=$((TOTAL * 2))
|
|
322
|
+
HEALTH_PERCENT=$(echo "scale=1; ($HEALTH_SCORE / $MAX_SCORE) * 100" | bc 2>/dev/null || echo "0")
|
|
323
|
+
|
|
324
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
325
|
+
echo -e "${CYAN}🏥 SKILL HEALTH SCORE: $HEALTH_PERCENT%${NC}"
|
|
326
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
|
|
327
|
+
|
|
328
|
+
if (( $(echo "$HEALTH_PERCENT >= 90" | bc -l 2>/dev/null || echo "0") )); then
|
|
329
|
+
echo -e "Status: ${GREEN}🟢 EXCELLENT${NC} - Skill is production-ready!"
|
|
330
|
+
elif (( $(echo "$HEALTH_PERCENT >= 70" | bc -l 2>/dev/null || echo "0") )); then
|
|
331
|
+
echo -e "Status: ${YELLOW}🟡 GOOD${NC} - Minor improvements recommended"
|
|
332
|
+
else
|
|
333
|
+
echo -e "Status: ${RED}🔴 NEEDS WORK${NC} - Critical issues found"
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
echo ""
|
|
337
|
+
echo "Test completed at: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
338
|
+
echo ""
|
|
339
|
+
|
|
340
|
+
# Exit code
|
|
341
|
+
if [ $FAIL -gt 5 ]; then
|
|
342
|
+
exit 1
|
|
343
|
+
else
|
|
344
|
+
exit 0
|
|
345
|
+
fi
|