cyberaudit-skill 3.1.4 → 3.2.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 +84 -25
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +555 -170
- package/dist/cli.test.d.ts +1 -0
- package/dist/cli.test.js +100 -0
- package/dist/mcp-server.d.ts +135 -1
- package/dist/mcp-server.js +185 -96
- package/dist/mcp-server.test.d.ts +1 -0
- package/dist/mcp-server.test.js +77 -0
- package/dist/report/generator.d.ts +2 -0
- package/dist/report/generator.js +260 -0
- package/dist/report/generator.test.d.ts +1 -0
- package/dist/report/generator.test.js +73 -0
- package/dist/report/types.d.ts +31 -0
- package/dist/report/types.js +1 -0
- package/dist/scanners/secrets.d.ts +32 -0
- package/dist/scanners/secrets.js +437 -0
- package/dist/scanners/secrets.test.d.ts +1 -0
- package/dist/scanners/secrets.test.js +96 -0
- package/dist/scanners/types.d.ts +22 -0
- package/dist/scanners/types.js +1 -0
- package/dist/scanners/web.d.ts +37 -0
- package/dist/scanners/web.js +327 -0
- package/dist/scanners/web.test.d.ts +1 -0
- package/dist/scanners/web.test.js +67 -0
- package/package.json +15 -3
- package/skills/cyberaudit/AGENT-BOOT.md +1 -1
- package/skills/cyberaudit/COMMANDS.md +11 -1
- package/skills/cyberaudit/INSTALL.md +7 -6
- package/skills/cyberaudit/README.md +20 -5
- package/skills/cyberaudit/SKILL.md +20 -5
- package/skills/cyberaudit/cloud/CLOUD-CHECKLIST.md +85 -0
- package/skills/cyberaudit/cloud/CLOUD-PHILOSOPHY.md +91 -0
- package/skills/cyberaudit/cloud/CLOUD-REMEDIATION-LIBRARY.md +145 -0
- package/skills/cyberaudit/commands/audit-angular.md +11 -0
- package/skills/cyberaudit/commands/audit-api-bola.md +11 -0
- package/skills/cyberaudit/commands/audit-api-bopla.md +11 -0
- package/skills/cyberaudit/commands/audit-api-graphql.md +11 -0
- package/skills/cyberaudit/commands/audit-api-inventory.md +11 -0
- package/skills/cyberaudit/commands/audit-api-rate-limit.md +11 -0
- package/skills/cyberaudit/commands/audit-api-rest.md +11 -0
- package/skills/cyberaudit/commands/audit-api-third-party.md +11 -0
- package/skills/cyberaudit/commands/audit-api-ws.md +11 -0
- package/skills/cyberaudit/commands/audit-auth-api.md +11 -0
- package/skills/cyberaudit/commands/audit-auth-mobile.md +11 -0
- package/skills/cyberaudit/commands/audit-auth.md +12 -0
- package/skills/cyberaudit/commands/audit-binary.md +11 -0
- package/skills/cyberaudit/commands/audit-cis.md +11 -0
- package/skills/cyberaudit/commands/audit-cloud-iam.md +11 -0
- package/skills/cyberaudit/commands/audit-cloud-network.md +11 -0
- package/skills/cyberaudit/commands/audit-cloud-s3.md +11 -0
- package/skills/cyberaudit/commands/audit-cloud.md +10 -0
- package/skills/cyberaudit/commands/audit-cors.md +11 -0
- package/skills/cyberaudit/commands/audit-crypto-mobile.md +11 -0
- package/skills/cyberaudit/commands/audit-crypto.md +10 -0
- package/skills/cyberaudit/commands/audit-csrf.md +11 -0
- package/skills/cyberaudit/commands/audit-deeplinks.md +11 -0
- package/skills/cyberaudit/commands/audit-deps.md +11 -0
- package/skills/cyberaudit/commands/audit-deserial.md +11 -0
- package/skills/cyberaudit/commands/audit-exec.md +11 -0
- package/skills/cyberaudit/commands/audit-expo.md +11 -0
- package/skills/cyberaudit/commands/audit-express.md +11 -0
- package/skills/cyberaudit/commands/audit-flutter.md +11 -0
- package/skills/cyberaudit/commands/audit-headers.md +11 -0
- package/skills/cyberaudit/commands/audit-hipaa.md +11 -0
- package/skills/cyberaudit/commands/audit-idor.md +11 -0
- package/skills/cyberaudit/commands/audit-injection.md +12 -0
- package/skills/cyberaudit/commands/audit-ionic.md +11 -0
- package/skills/cyberaudit/commands/audit-laravel.md +11 -0
- package/skills/cyberaudit/commands/audit-logic.md +11 -0
- package/skills/cyberaudit/commands/audit-masvs.md +11 -0
- package/skills/cyberaudit/commands/audit-nestjs.md +11 -0
- package/skills/cyberaudit/commands/audit-network.md +11 -0
- package/skills/cyberaudit/commands/audit-nextjs.md +11 -0
- package/skills/cyberaudit/commands/audit-owasp.md +11 -0
- package/skills/cyberaudit/commands/audit-pci.md +11 -0
- package/skills/cyberaudit/commands/audit-permissions.md +11 -0
- package/skills/cyberaudit/commands/audit-react-native.md +11 -0
- package/skills/cyberaudit/commands/audit-react.md +11 -0
- package/skills/cyberaudit/commands/audit-rgpd.md +11 -0
- package/skills/cyberaudit/commands/audit-runtime.md +11 -0
- package/skills/cyberaudit/commands/audit-secrets.md +11 -0
- package/skills/cyberaudit/commands/audit-ssrf.md +11 -0
- package/skills/cyberaudit/commands/audit-storage.md +11 -0
- package/skills/cyberaudit/commands/audit-vue.md +11 -0
- package/skills/cyberaudit/commands/audit-xss.md +11 -0
- package/skills/cyberaudit/commands/audit-xxe.md +11 -0
- package/skills/cyberaudit/reports/EXECUTIVE-SUMMARY-TEMPLATE.md +1 -1
- package/skills/cyberaudit/reports/REPORT-TEMPLATE-CLOUD.md +103 -0
- package/skills/cyberaudit/reports/REPORT-TEMPLATE-MOBILE.md +2 -2
- package/skills/cyberaudit/reports/REPORT-TEMPLATE-WEB.md +2 -2
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
|
|
2
|
+
import { join, extname } from 'path';
|
|
3
|
+
const IGNORE_DIRS = ['node_modules', '.git', 'dist', 'build', '.next', '.nuxt', 'coverage', '.cache', 'vendor', 'out'];
|
|
4
|
+
function shouldIgnoreDir(name) {
|
|
5
|
+
return IGNORE_DIRS.includes(name);
|
|
6
|
+
}
|
|
7
|
+
function walkFiles(dir, exts, maxSize = 1_000_000) {
|
|
8
|
+
const files = [];
|
|
9
|
+
const walk = (d) => {
|
|
10
|
+
try {
|
|
11
|
+
const entries = readdirSync(d);
|
|
12
|
+
for (const e of entries) {
|
|
13
|
+
if (shouldIgnoreDir(e))
|
|
14
|
+
continue;
|
|
15
|
+
const full = join(d, e);
|
|
16
|
+
try {
|
|
17
|
+
const st = statSync(full);
|
|
18
|
+
if (st.isDirectory())
|
|
19
|
+
walk(full);
|
|
20
|
+
else if (st.isFile()) {
|
|
21
|
+
if (st.size > maxSize)
|
|
22
|
+
continue;
|
|
23
|
+
const ext = extname(full).toLowerCase();
|
|
24
|
+
// Allow .js, .ts, .jsx, .tsx, .vue, .php, .py etc
|
|
25
|
+
if (exts.length === 0 || exts.includes(ext) || full.endsWith('.js') || full.endsWith('.ts')) {
|
|
26
|
+
// Quick binary skip
|
|
27
|
+
if (['.png', '.jpg', '.jpeg', '.gif', '.ico', '.pdf', '.zip', '.woff', '.woff2'].includes(ext))
|
|
28
|
+
continue;
|
|
29
|
+
files.push(full);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch { }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch { }
|
|
37
|
+
};
|
|
38
|
+
walk(dir);
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
const WEB_PATTERNS = [
|
|
42
|
+
{
|
|
43
|
+
id: 'WEB_SQLI_CONCAT',
|
|
44
|
+
name: 'SQL Injection via string concatenation / template literal',
|
|
45
|
+
regex: /(?:db|pool|connection|client)\.(?:query|execute)\s*\(\s*["'`].*\+.*req\.|(?:query|execute)\s*\(\s*`[^`]*\$\{[^}]*req\.[^}]*\}[^`]*`/gi,
|
|
46
|
+
severity: 'CRITICAL',
|
|
47
|
+
cvss: 9.8,
|
|
48
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H',
|
|
49
|
+
description: 'SQL query built via string concatenation or template literal with user input (req.*). Classic SQLi.',
|
|
50
|
+
remediation: 'Use parameterized queries: db.query("SELECT * FROM users WHERE id = ?", [id]) or ORM safe methods. Never interpolate user input.',
|
|
51
|
+
owasp: 'A03:2021 — Injection',
|
|
52
|
+
cwe: 'CWE-89',
|
|
53
|
+
extensions: ['.js', '.ts', '.jsx', '.tsx', '.php'],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'WEB_SQLI_RAW',
|
|
57
|
+
name: 'SQL Injection via raw query with interpolation',
|
|
58
|
+
regex: /(?:SELECT|INSERT|UPDATE|DELETE).*\+.*req\.(?:body|query|params)\./gi,
|
|
59
|
+
severity: 'CRITICAL',
|
|
60
|
+
cvss: 9.8,
|
|
61
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H',
|
|
62
|
+
description: 'Raw SQL contains req.body/query/params concatenation.',
|
|
63
|
+
remediation: 'Use prepared statements / ORM. Validate whitelist for ORDER BY / table names.',
|
|
64
|
+
owasp: 'A03:2021',
|
|
65
|
+
cwe: 'CWE-89',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'WEB_XSS_DANGEROUS',
|
|
69
|
+
name: 'XSS via dangerouslySetInnerHTML without DOMPurify',
|
|
70
|
+
regex: /dangerouslySetInnerHTML\s*=\s*\{\{\s*__html\s*:\s*[^}]*\}/g,
|
|
71
|
+
severity: 'HIGH',
|
|
72
|
+
cvss: 7.5,
|
|
73
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N',
|
|
74
|
+
description: 'React dangerouslySetInnerHTML used. If user input reaches it without sanitization, XSS.',
|
|
75
|
+
remediation: 'Use DOMPurify: import DOMPurify from "dompurify"; <div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(userInput)}} /> or avoid innerHTML.',
|
|
76
|
+
owasp: 'A03:2021',
|
|
77
|
+
cwe: 'CWE-79',
|
|
78
|
+
falsePositiveIfContains: ['DOMPurify', 'sanitize'],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'WEB_XSS_INNERHTML',
|
|
82
|
+
name: 'XSS via innerHTML assignment',
|
|
83
|
+
regex: /(?:\.innerHTML\s*=|v-html\s*=|{{\s*.*\s*\|\s*safe}})/g,
|
|
84
|
+
severity: 'HIGH',
|
|
85
|
+
cvss: 7.2,
|
|
86
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N',
|
|
87
|
+
description: 'Direct innerHTML assignment or v-html without sanitization.',
|
|
88
|
+
remediation: 'Escape output, use textContent, or sanitize with DOMPurify / HTMLPurifier.',
|
|
89
|
+
owasp: 'A03:2021',
|
|
90
|
+
cwe: 'CWE-79',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'WEB_JWT_DECODE',
|
|
94
|
+
name: 'JWT decode without verify (auth bypass)',
|
|
95
|
+
regex: /jwt\.decode\s*\(/g,
|
|
96
|
+
severity: 'HIGH',
|
|
97
|
+
cvss: 8.1,
|
|
98
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N',
|
|
99
|
+
description: 'jwt.decode() used instead of jwt.verify(). decode does NOT validate signature, allows forged tokens.',
|
|
100
|
+
remediation: 'Use jwt.verify(token, secret, {algorithms: ["HS256"]}) and explicitly set algorithm. Never trust decode.',
|
|
101
|
+
owasp: 'A02:2021 — Cryptographic Failures',
|
|
102
|
+
cwe: 'CWE-345',
|
|
103
|
+
falsePositiveIfContains: ['jwt.verify'],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 'WEB_CORS_WILDCARD',
|
|
107
|
+
name: 'CORS wildcard with credentials',
|
|
108
|
+
regex: /(?:origin\s*:\s*['"]\*['"]|Access-Control-Allow-Origin.*\*|cors\(\s*\{\s*origin\s*:\s*true)/gi,
|
|
109
|
+
severity: 'MEDIUM',
|
|
110
|
+
cvss: 6.5,
|
|
111
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N',
|
|
112
|
+
description: 'CORS configured with wildcard origin. If credentials:true, allows any site to read authenticated responses.',
|
|
113
|
+
remediation: 'Whitelist explicit origins: cors({origin: ["https://app.example.com"], credentials:true}). Never * with credentials.',
|
|
114
|
+
owasp: 'A01:2021 — Broken Access Control',
|
|
115
|
+
cwe: 'CWE-942',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'WEB_EXEC_INJECTION',
|
|
119
|
+
name: 'Command injection via exec / spawn with user input',
|
|
120
|
+
regex: /(?:exec|execSync|spawn|spawnSync)\s*\(\s*[`'"].*\$\{.*req\.|exec\s*\(\s*.*\+.*req\.(?:body|query|params)/g,
|
|
121
|
+
severity: 'CRITICAL',
|
|
122
|
+
cvss: 9.8,
|
|
123
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H',
|
|
124
|
+
description: 'Child process exec with user-controlled input. Leads to RCE.',
|
|
125
|
+
remediation: 'Avoid shell. Use execFile with allowlist, or native libs (e.g., sharp instead of convert). Validate strict whitelist.',
|
|
126
|
+
owasp: 'A03:2021',
|
|
127
|
+
cwe: 'CWE-77',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: 'WEB_EVAL',
|
|
131
|
+
name: 'Code injection via eval / Function',
|
|
132
|
+
regex: /(?:\beval\s*\(|new\s+Function\s*\()/g,
|
|
133
|
+
severity: 'CRITICAL',
|
|
134
|
+
cvss: 9.8,
|
|
135
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H',
|
|
136
|
+
description: 'eval() or new Function() with potential user input. Arbitrary code execution.',
|
|
137
|
+
remediation: 'Remove eval. Use JSON.parse, or safe alternatives. If unavoidable, strict allowlist and no user input.',
|
|
138
|
+
owasp: 'A03:2021',
|
|
139
|
+
cwe: 'CWE-95',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'WEB_MASS_ASSIGNMENT',
|
|
143
|
+
name: 'Mass assignment via req.body directly in create/update',
|
|
144
|
+
regex: /(?:\.create\s*\(\s*req\.body|\.update\s*\(\s*req\.body|\.findOneAndUpdate\s*\(\s*.*req\.body)/g,
|
|
145
|
+
severity: 'HIGH',
|
|
146
|
+
cvss: 8.1,
|
|
147
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N',
|
|
148
|
+
description: 'Direct use of req.body in ORM create/update without whitelist. Allows role/balance elevation.',
|
|
149
|
+
remediation: 'Whitelist allowed fields: const {name,email} = req.body; Model.create({name,email}). Use ValidationPipe whitelist:true in NestJS.',
|
|
150
|
+
owasp: 'A03:2021',
|
|
151
|
+
cwe: 'CWE-915',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'WEB_NOSQL_INJECTION',
|
|
155
|
+
name: 'NoSQL injection via req.body in find',
|
|
156
|
+
regex: /(?:find|findOne)\s*\(\s*\{[^}]*req\.body\./g,
|
|
157
|
+
severity: 'HIGH',
|
|
158
|
+
cvss: 8.2,
|
|
159
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N',
|
|
160
|
+
description: 'NoSQL query uses req.body field directly as filter. If attacker sends {$gt:""} it bypasses auth.',
|
|
161
|
+
remediation: 'Use String(req.body.username) or mongoSanitize. Validate types, strip $ operators.',
|
|
162
|
+
owasp: 'A03:2021',
|
|
163
|
+
cwe: 'CWE-943',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'WEB_HELMET_MISSING',
|
|
167
|
+
name: 'Express app without helmet (missing security headers)',
|
|
168
|
+
fileRegex: /express\s*\(\)/,
|
|
169
|
+
severity: 'LOW',
|
|
170
|
+
cvss: 3.7,
|
|
171
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N',
|
|
172
|
+
description: 'Express app detected but helmet middleware not used. Missing CSP, HSTS, X-Frame, etc.',
|
|
173
|
+
remediation: 'Add helmet: import helmet from "helmet"; app.use(helmet()); Configure CSP.',
|
|
174
|
+
owasp: 'A05:2021 — Security Misconfiguration',
|
|
175
|
+
cwe: 'CWE-693',
|
|
176
|
+
mustContain: ['express'],
|
|
177
|
+
falsePositiveIfContains: ['helmet'],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: 'WEB_LARAVEL_DEBUG',
|
|
181
|
+
name: 'Laravel APP_DEBUG true in production example or .env',
|
|
182
|
+
regex: /APP_DEBUG\s*=\s*true/gi,
|
|
183
|
+
severity: 'MEDIUM',
|
|
184
|
+
cvss: 5.3,
|
|
185
|
+
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N',
|
|
186
|
+
description: 'APP_DEBUG=true exposes stack traces, env vars.',
|
|
187
|
+
remediation: 'Set APP_DEBUG=false in production, APP_ENV=production. Ensure .env not committed.',
|
|
188
|
+
owasp: 'A05:2021',
|
|
189
|
+
cwe: 'CWE-215',
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
export function scanWeb(targetPath) {
|
|
193
|
+
if (!existsSync(targetPath))
|
|
194
|
+
throw new Error(`Target not found: ${targetPath}`);
|
|
195
|
+
const stat = statSync(targetPath);
|
|
196
|
+
let files = [];
|
|
197
|
+
if (stat.isFile())
|
|
198
|
+
files = [targetPath];
|
|
199
|
+
else
|
|
200
|
+
files = walkFiles(targetPath, ['.js', '.ts', '.jsx', '.tsx', '.vue', '.php', '.py', '.go', '.java']);
|
|
201
|
+
const findings = [];
|
|
202
|
+
for (const file of files) {
|
|
203
|
+
let content;
|
|
204
|
+
try {
|
|
205
|
+
content = readFileSync(file, 'utf-8');
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (content.length > 1_000_000)
|
|
211
|
+
continue;
|
|
212
|
+
const lines = content.split(/\r?\n/);
|
|
213
|
+
for (const pattern of WEB_PATTERNS) {
|
|
214
|
+
// Extension filter
|
|
215
|
+
if (pattern.extensions && pattern.extensions.length > 0) {
|
|
216
|
+
const ext = file.slice(file.lastIndexOf('.')).toLowerCase();
|
|
217
|
+
if (!pattern.extensions.includes(ext) && !pattern.extensions.some(e => file.endsWith(e))) {
|
|
218
|
+
// allow if file contains mustContain anyway? Skip strict
|
|
219
|
+
if (!pattern.mustContain)
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// mustContain filter
|
|
224
|
+
if (pattern.mustContain && !pattern.mustContain.some(k => content.includes(k)))
|
|
225
|
+
continue;
|
|
226
|
+
// false positive mitigation present
|
|
227
|
+
if (pattern.falsePositiveIfContains && pattern.falsePositiveIfContains.some(k => content.includes(k))) {
|
|
228
|
+
// For some patterns, we still want to report if mitigation not on same line? For simplicity skip file-level
|
|
229
|
+
// But for line-level, we check per line later; here we skip only for fileRegex patterns
|
|
230
|
+
if (pattern.fileRegex)
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (pattern.fileRegex) {
|
|
234
|
+
pattern.fileRegex.lastIndex = 0;
|
|
235
|
+
if (pattern.fileRegex.test(content)) {
|
|
236
|
+
// Find line of first match for file-level
|
|
237
|
+
const match = content.match(pattern.fileRegex);
|
|
238
|
+
let lineNum = 1;
|
|
239
|
+
if (match && match.index !== undefined) {
|
|
240
|
+
const before = content.slice(0, match.index);
|
|
241
|
+
lineNum = before.split('\n').length;
|
|
242
|
+
}
|
|
243
|
+
findings.push({
|
|
244
|
+
id: `VULN-${pattern.id}`,
|
|
245
|
+
patternId: pattern.id,
|
|
246
|
+
severity: pattern.severity,
|
|
247
|
+
cvss: pattern.cvss,
|
|
248
|
+
cvssVector: pattern.cvssVector,
|
|
249
|
+
file,
|
|
250
|
+
line: lineNum,
|
|
251
|
+
match: match ? match[0].slice(0, 120) : pattern.id,
|
|
252
|
+
description: pattern.description,
|
|
253
|
+
remediation: pattern.remediation,
|
|
254
|
+
owasp: pattern.owasp,
|
|
255
|
+
cwe: pattern.cwe,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (!pattern.regex)
|
|
261
|
+
continue;
|
|
262
|
+
for (let i = 0; i < lines.length; i++) {
|
|
263
|
+
const line = lines[i];
|
|
264
|
+
if (line.length > 2000)
|
|
265
|
+
continue;
|
|
266
|
+
pattern.regex.lastIndex = 0;
|
|
267
|
+
let m;
|
|
268
|
+
while ((m = pattern.regex.exec(line)) !== null) {
|
|
269
|
+
const raw = m[0];
|
|
270
|
+
if (raw.length < 4)
|
|
271
|
+
continue;
|
|
272
|
+
// Skip if mitigation on same line
|
|
273
|
+
if (pattern.falsePositiveIfContains && pattern.falsePositiveIfContains.some(k => line.includes(k))) {
|
|
274
|
+
// if mitigation present on same line, skip
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
findings.push({
|
|
278
|
+
id: `VULN-${pattern.id}`,
|
|
279
|
+
patternId: pattern.id,
|
|
280
|
+
severity: pattern.severity,
|
|
281
|
+
cvss: pattern.cvss,
|
|
282
|
+
cvssVector: pattern.cvssVector,
|
|
283
|
+
file,
|
|
284
|
+
line: i + 1,
|
|
285
|
+
column: m.index,
|
|
286
|
+
match: raw.slice(0, 200),
|
|
287
|
+
description: pattern.description,
|
|
288
|
+
remediation: pattern.remediation,
|
|
289
|
+
owasp: pattern.owasp,
|
|
290
|
+
cwe: pattern.cwe,
|
|
291
|
+
});
|
|
292
|
+
if (m[0].length === 0)
|
|
293
|
+
pattern.regex.lastIndex++;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const seen = new Set();
|
|
299
|
+
const deduped = [];
|
|
300
|
+
for (const f of findings) {
|
|
301
|
+
const key = `${f.file}:${f.line}:${f.patternId}:${f.match}`;
|
|
302
|
+
if (!seen.has(key)) {
|
|
303
|
+
seen.add(key);
|
|
304
|
+
deduped.push(f);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const order = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3, INFO: 4 };
|
|
308
|
+
deduped.sort((a, b) => order[a.severity] - order[b.severity] || a.file.localeCompare(b.file));
|
|
309
|
+
return deduped;
|
|
310
|
+
}
|
|
311
|
+
export function formatWebFindingsText(findings, target) {
|
|
312
|
+
if (findings.length === 0) {
|
|
313
|
+
return `✅ No web vulnerabilities found in ${target}\nChecked ${WEB_PATTERNS.length} patterns.\n`;
|
|
314
|
+
}
|
|
315
|
+
const bySev = {};
|
|
316
|
+
findings.forEach(f => bySev[f.severity] = (bySev[f.severity] || 0) + 1);
|
|
317
|
+
let out = `🕷️ Web scan results for ${target}\nTotal: ${findings.length} | ${Object.entries(bySev).map(([k, v]) => `${k}:${v}`).join(' ')}\n\n`;
|
|
318
|
+
for (const f of findings) {
|
|
319
|
+
const icon = f.severity === 'CRITICAL' ? '🔴' : f.severity === 'HIGH' ? '🟠' : f.severity === 'MEDIUM' ? '🟡' : '🟢';
|
|
320
|
+
out += `${icon} [${f.severity}] ${f.patternId} — ${f.file}:${f.line}\n`;
|
|
321
|
+
out += ` Match: ${f.match}\n`;
|
|
322
|
+
out += ` CVSS: ${f.cvss} ${f.cvssVector}\n`;
|
|
323
|
+
out += ` Fix: ${f.remediation.split('.')[0]}.\n\n`;
|
|
324
|
+
}
|
|
325
|
+
return out;
|
|
326
|
+
}
|
|
327
|
+
export { WEB_PATTERNS };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, writeFileSync, rmSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { scanWeb } from './web.js';
|
|
6
|
+
describe('Web Scanner', () => {
|
|
7
|
+
let tmp;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tmp = mkdtempSync(join(tmpdir(), 'cyberaudit-web-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
it('should detect SQLi concat', () => {
|
|
15
|
+
writeFileSync(join(tmp, 'db.js'), 'db.query("SELECT * FROM users WHERE id = " + req.query.id);');
|
|
16
|
+
const findings = scanWeb(tmp);
|
|
17
|
+
expect(findings.some(f => f.patternId === 'WEB_SQLI_CONCAT' || f.patternId === 'WEB_SQLI_RAW')).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it('should detect XSS dangerouslySetInnerHTML', () => {
|
|
20
|
+
writeFileSync(join(tmp, 'comp.jsx'), '<div dangerouslySetInnerHTML={{ __html: userInput }} />');
|
|
21
|
+
const findings = scanWeb(tmp);
|
|
22
|
+
expect(findings.some(f => f.patternId === 'WEB_XSS_DANGEROUS')).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('should not flag XSS if DOMPurify present', () => {
|
|
25
|
+
writeFileSync(join(tmp, 'comp.jsx'), `
|
|
26
|
+
import DOMPurify from 'dompurify';
|
|
27
|
+
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
|
|
28
|
+
`);
|
|
29
|
+
const findings = scanWeb(tmp);
|
|
30
|
+
// Should be filtered because DOMPurify present
|
|
31
|
+
expect(findings.some(f => f.patternId === 'WEB_XSS_DANGEROUS')).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
it('should detect jwt.decode', () => {
|
|
34
|
+
writeFileSync(join(tmp, 'auth.js'), 'const payload = jwt.decode(token);');
|
|
35
|
+
const findings = scanWeb(tmp);
|
|
36
|
+
expect(findings.some(f => f.patternId === 'WEB_JWT_DECODE')).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
it('should detect CORS wildcard', () => {
|
|
39
|
+
writeFileSync(join(tmp, 'server.js'), "app.use(cors({ origin: '*' }));");
|
|
40
|
+
const findings = scanWeb(tmp);
|
|
41
|
+
expect(findings.some(f => f.patternId === 'WEB_CORS_WILDCARD')).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
it('should detect eval', () => {
|
|
44
|
+
writeFileSync(join(tmp, 'bad.js'), 'eval(userInput);');
|
|
45
|
+
const findings = scanWeb(tmp);
|
|
46
|
+
expect(findings.some(f => f.patternId === 'WEB_EVAL')).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it('should detect mass assignment', () => {
|
|
49
|
+
writeFileSync(join(tmp, 'user.js'), 'User.create(req.body);');
|
|
50
|
+
const findings = scanWeb(tmp);
|
|
51
|
+
expect(findings.some(f => f.patternId === 'WEB_MASS_ASSIGNMENT')).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
it('should detect NoSQL injection', () => {
|
|
54
|
+
writeFileSync(join(tmp, 'login.js'), 'db.users.find({ username: req.body.username });');
|
|
55
|
+
const findings = scanWeb(tmp);
|
|
56
|
+
expect(findings.some(f => f.patternId === 'WEB_NOSQL_INJECTION')).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
it('should return empty for clean file', () => {
|
|
59
|
+
writeFileSync(join(tmp, 'clean.js'), 'const a = 1; console.log(a);');
|
|
60
|
+
const findings = scanWeb(tmp);
|
|
61
|
+
expect(findings.length).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
it('should have at least 10 patterns', async () => {
|
|
64
|
+
const { WEB_PATTERNS } = await import('./web.js');
|
|
65
|
+
expect(WEB_PATTERNS.length).toBeGreaterThanOrEqual(10);
|
|
66
|
+
});
|
|
67
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyberaudit-skill",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Universal security audit skill for AI agents. Install once, audit any web or mobile app. OpenCode, Claude Code, Cursor, Kiro, Gemini — all supported.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -38,9 +38,16 @@
|
|
|
38
38
|
"build": "tsc",
|
|
39
39
|
"start": "node dist/cli.js",
|
|
40
40
|
"dev": "tsx src/cli.ts",
|
|
41
|
+
"dev:serve": "tsx src/mcp-server.ts",
|
|
41
42
|
"install:local": "node dist/cli.js install",
|
|
42
43
|
"install:all": "node dist/cli.js install --agent all",
|
|
43
|
-
"serve": "
|
|
44
|
+
"serve": "node dist/mcp-server.js",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"lint": "eslint src/",
|
|
48
|
+
"lint:fix": "eslint src/ --fix",
|
|
49
|
+
"format": "prettier --write \"src/**/*.{ts,js,md}\"",
|
|
50
|
+
"format:check": "prettier --check \"src/**/*.{ts,js}\"",
|
|
44
51
|
"prepublishOnly": "npm run build"
|
|
45
52
|
},
|
|
46
53
|
"dependencies": {
|
|
@@ -48,8 +55,13 @@
|
|
|
48
55
|
},
|
|
49
56
|
"devDependencies": {
|
|
50
57
|
"@types/node": "^20.0.0",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^8.64.0",
|
|
59
|
+
"@typescript-eslint/parser": "^8.64.0",
|
|
60
|
+
"eslint": "^10.7.0",
|
|
61
|
+
"prettier": "^3.9.5",
|
|
51
62
|
"tsx": "^4.0.0",
|
|
52
|
-
"typescript": "^5.0.0"
|
|
63
|
+
"typescript": "^5.0.0",
|
|
64
|
+
"vitest": "^4.1.10"
|
|
53
65
|
},
|
|
54
66
|
"engines": {
|
|
55
67
|
"node": ">=18.0.0"
|
|
@@ -71,6 +71,15 @@ When user types `/cyberaudit` or `/audit` — **list all commands below**.
|
|
|
71
71
|
| `/audit:api:inventory` | API inventory/discovery |
|
|
72
72
|
| `/audit:api:third-party` | Third-party API audit |
|
|
73
73
|
|
|
74
|
+
## Cloud
|
|
75
|
+
|
|
76
|
+
| Command | Action |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `/audit:cloud` | Full cloud config audit (CIS, S3, IAM, SG) |
|
|
79
|
+
| `/audit:cloud:s3` | Storage / buckets public access |
|
|
80
|
+
| `/audit:cloud:iam` | IAM least privilege & wildcards |
|
|
81
|
+
| `/audit:cloud:network` | Security Groups & firewall |
|
|
82
|
+
|
|
74
83
|
## Compliance
|
|
75
84
|
|
|
76
85
|
| Command | Action |
|
|
@@ -80,7 +89,8 @@ When user types `/cyberaudit` or `/audit` — **list all commands below**.
|
|
|
80
89
|
| `/audit:hipaa` | HIPAA compliance check |
|
|
81
90
|
| `/audit:masvs` | MASVS 2.0 score |
|
|
82
91
|
| `/audit:owasp` | OWASP Top 10 score |
|
|
92
|
+
| `/audit:cis` | CIS Benchmark cloud score |
|
|
83
93
|
|
|
84
94
|
## Execution
|
|
85
95
|
|
|
86
|
-
For any `/audit:xxx` command, load the corresponding files from `web/`, `mobile/`, `api/`, or `reports/`, then execute the audit methodology from `SKILL.md`.
|
|
96
|
+
For any `/audit:xxx` command, load the corresponding files from `web/`, `mobile/`, `api/`, `cloud/`, or `reports/`, then execute the audit methodology from `SKILL.md`.
|
|
@@ -23,7 +23,7 @@ OPTION A — PROJECT-LOCAL (recommended for teams)
|
|
|
23
23
|
All developers get access automatically.
|
|
24
24
|
|
|
25
25
|
# In your project root directory
|
|
26
|
-
git clone https://github.com/
|
|
26
|
+
git clone https://github.com/ArisRoman/cyberaudit-skill \
|
|
27
27
|
.skills/cyberaudit
|
|
28
28
|
|
|
29
29
|
# Add to .gitignore if you don't want to commit it
|
|
@@ -42,7 +42,7 @@ OPTION B — MACHINE-GLOBAL (recommended for solo devs)
|
|
|
42
42
|
|
|
43
43
|
# In your home directory
|
|
44
44
|
mkdir -p ~/.skills
|
|
45
|
-
git clone https://github.com/
|
|
45
|
+
git clone https://github.com/ArisRoman/cyberaudit-skill \
|
|
46
46
|
~/.skills/cyberaudit
|
|
47
47
|
|
|
48
48
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -295,10 +295,10 @@ ANY OTHER AGENT (via API)
|
|
|
295
295
|
═══════════════════════════════════════════════════════════════
|
|
296
296
|
|
|
297
297
|
Report an issue:
|
|
298
|
-
github.com/
|
|
298
|
+
github.com/ArisRoman/cyberaudit-skill/issues
|
|
299
299
|
|
|
300
300
|
Suggest an improvement:
|
|
301
|
-
github.com/
|
|
301
|
+
github.com/ArisRoman/cyberaudit-skill/pulls
|
|
302
302
|
|
|
303
303
|
Add a new framework:
|
|
304
304
|
Create web/frameworks/NEW-FRAMEWORK.md
|
|
@@ -306,6 +306,7 @@ ANY OTHER AGENT (via API)
|
|
|
306
306
|
Add the command in COMMANDS.md
|
|
307
307
|
Submit a PR
|
|
308
308
|
|
|
309
|
-
VERSION: 3.
|
|
309
|
+
VERSION: 3.1.5
|
|
310
310
|
LICENSE: MIT
|
|
311
|
-
STANDARDS: OWASP Top 10 2023 · MASVS 2.0 · CVSS 3.1
|
|
311
|
+
STANDARDS: OWASP Top 10 2023 · MASVS 2.0 · CVSS 3.1 · CIS Cloud
|
|
312
|
+
REPO: github.com/ArisRoman/cyberaudit-skill
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CyberAudit Skill
|
|
2
2
|
|
|
3
|
-
Security audit intelligence for AI agents. Pure Markdown,
|
|
3
|
+
Security audit intelligence for AI agents. Pure Markdown, deterministic CLI + MCP.
|
|
4
4
|
|
|
5
5
|
## Coverage
|
|
6
6
|
|
|
@@ -8,22 +8,28 @@ Security audit intelligence for AI agents. Pure Markdown, zero dependencies.
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| **Web** | 7 frameworks (React, Next.js, Laravel, NestJS, Express, Vue, Angular), 13 vulnerability types |
|
|
10
10
|
| **Mobile** | 4 frameworks (React Native, Flutter, Ionic, Expo), 8 vulnerability types |
|
|
11
|
+
| **API** | 3 types (REST, GraphQL, WebSocket), 5 vuln categories (BOLA, BOPLA, rate-limit, inventory, third-party) |
|
|
12
|
+
| **Cloud** | S3 public, IAM wildcard, SG open, IMDSv1, secrets in IaC, CloudTrail (CIS benchmark) |
|
|
11
13
|
| **Scoring** | CVSS 3.1 with aggravating/mitigating context factors |
|
|
12
|
-
| **Compliance** | RGPD, PCI-DSS, HIPAA, SOC 2 |
|
|
13
|
-
| **Reports** | Web + Mobile + Executive Summary templates |
|
|
14
|
+
| **Compliance** | RGPD, PCI-DSS, HIPAA, SOC 2, CIS |
|
|
15
|
+
| **Reports** | Web + Mobile + API + Cloud + Executive Summary templates |
|
|
16
|
+
| **Commands** | 60 slash-commands (`/audit:web`, `/audit:cloud:s3`, etc.) |
|
|
14
17
|
|
|
15
18
|
## Files
|
|
16
19
|
|
|
17
20
|
```
|
|
18
21
|
AGENT-BOOT.md Boot sequence, oath, audit levels
|
|
19
22
|
SKILL.md Main intelligence, taxonomy, rules
|
|
20
|
-
COMMANDS.md Operational commands
|
|
23
|
+
COMMANDS.md Operational commands (60 commands)
|
|
21
24
|
USAGE-GUIDE.md User-facing guide
|
|
22
25
|
MASTER.md Full vulnerability taxonomy + scoring
|
|
23
26
|
web/ Web audit checklists, per-framework guides
|
|
24
27
|
mobile/ Mobile audit checklists, per-framework guides
|
|
28
|
+
api/ API checklists + type guides
|
|
29
|
+
cloud/ Cloud checklists, philosophy, remediation (S3, IAM, SG)
|
|
25
30
|
shared/ Scoring, CVSS, OWASP mapping, compliance
|
|
26
|
-
reports/ Report templates (web, mobile, executive)
|
|
31
|
+
reports/ Report templates (web, mobile, api, cloud, executive)
|
|
32
|
+
commands/ 60 command definitions for OpenCode autocomplete
|
|
27
33
|
```
|
|
28
34
|
|
|
29
35
|
## Audit Levels
|
|
@@ -39,6 +45,15 @@ reports/ Report templates (web, mobile, executive)
|
|
|
39
45
|
npx -y cyberaudit-skill install
|
|
40
46
|
```
|
|
41
47
|
|
|
48
|
+
## CLI
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx -y cyberaudit-skill list
|
|
52
|
+
npx -y cyberaudit-skill install --dry-run
|
|
53
|
+
npx -y cyberaudit-skill serve # MCP server
|
|
54
|
+
npm test # 14 tests
|
|
55
|
+
```
|
|
56
|
+
|
|
42
57
|
## License
|
|
43
58
|
|
|
44
59
|
MIT
|
|
@@ -9,7 +9,7 @@ description: >
|
|
|
9
9
|
compatibility: Pure Markdown skill, no external dependencies. Works with any AI agent that loads SKILL.md.
|
|
10
10
|
metadata:
|
|
11
11
|
author: ArisRoman
|
|
12
|
-
version: "3.
|
|
12
|
+
version: "3.1.5"
|
|
13
13
|
allowed-tools: Read Edit Grep Glob Bash
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -84,6 +84,14 @@ Security audit intelligence for AI agents. Universal, framework-agnostic, method
|
|
|
84
84
|
| `/audit:api:inventory` | API inventory/discovery |
|
|
85
85
|
| `/audit:api:third-party` | Third-party API audit |
|
|
86
86
|
|
|
87
|
+
### Cloud
|
|
88
|
+
| Command | Action |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `/audit:cloud` | Full cloud config audit (S3, IAM, SG) |
|
|
91
|
+
| `/audit:cloud:s3` | Storage security (public buckets) |
|
|
92
|
+
| `/audit:cloud:iam` | IAM privilege audit |
|
|
93
|
+
| `/audit:cloud:network` | Security groups & network audit |
|
|
94
|
+
|
|
87
95
|
### Compliance
|
|
88
96
|
| Command | Action |
|
|
89
97
|
|---|---|
|
|
@@ -92,28 +100,30 @@ Security audit intelligence for AI agents. Universal, framework-agnostic, method
|
|
|
92
100
|
| `/audit:hipaa` | HIPAA compliance check |
|
|
93
101
|
| `/audit:masvs` | MASVS 2.0 score |
|
|
94
102
|
| `/audit:owasp` | OWASP Top 10 score |
|
|
103
|
+
| `/audit:cis` | CIS Benchmark cloud score |
|
|
95
104
|
|
|
96
105
|
## Boot Sequence
|
|
97
106
|
|
|
98
107
|
Execute on every audit request:
|
|
99
108
|
|
|
100
109
|
**STEP 1 — IDENTIFICATION** (30 sec)
|
|
101
|
-
- TYPE → Web / Mobile / API / Both
|
|
102
|
-
- FRAMEWORK → Identify precisely (React, Laravel, Flutter, etc.)
|
|
110
|
+
- TYPE → Web / Mobile / API / Cloud / Both
|
|
111
|
+
- FRAMEWORK → Identify precisely (React, Laravel, Flutter, Terraform, etc.)
|
|
103
112
|
- CONTEXT → Dev / Staging / Production
|
|
104
|
-
- SCOPE → Entire code / Single module
|
|
113
|
+
- SCOPE → Entire code / Single module / IaC
|
|
105
114
|
- URGENCY → Quick scan / Standard / Deep / Red Team
|
|
106
115
|
|
|
107
116
|
**STEP 2 — MODE LOADING**
|
|
108
117
|
- Web → Load web checklist + framework-specific guide
|
|
109
118
|
- Mobile → Load mobile checklist + framework-specific guide
|
|
110
119
|
- API → Load API checklist + type-specific guide (REST/GraphQL/WebSocket)
|
|
120
|
+
- Cloud → Load cloud checklist + philosophy (AWS/GCP/Azure)
|
|
111
121
|
|
|
112
122
|
**STEP 3 — STRUCTURED AUDIT**
|
|
113
123
|
Follow the loaded philosophy. Never skip a phase. Document each finding immediately.
|
|
114
124
|
|
|
115
125
|
**STEP 4 — REPORT**
|
|
116
|
-
Use template. CVSS 3.1 scoring. Complete remediation code for each finding.
|
|
126
|
+
Use template (web/mobile/api/cloud). CVSS 3.1 scoring. Complete remediation code for each finding.
|
|
117
127
|
|
|
118
128
|
## Universal Principles
|
|
119
129
|
|
|
@@ -255,7 +265,12 @@ This skill lives at `~/.skills/cyberaudit/`. Additional sub-skills:
|
|
|
255
265
|
│ ├── REPORT-TEMPLATE-WEB.md
|
|
256
266
|
│ ├── REPORT-TEMPLATE-MOBILE.md
|
|
257
267
|
│ ├── REPORT-TEMPLATE-API.md
|
|
268
|
+
│ ├── REPORT-TEMPLATE-CLOUD.md
|
|
258
269
|
│ └── EXECUTIVE-SUMMARY-TEMPLATE.md
|
|
270
|
+
├── cloud/
|
|
271
|
+
│ ├── CLOUD-CHECKLIST.md
|
|
272
|
+
│ ├── CLOUD-PHILOSOPHY.md
|
|
273
|
+
│ └── CLOUD-REMEDIATION-LIBRARY.md
|
|
259
274
|
├── shared/
|
|
260
275
|
│ ├── COMPLIANCE.md
|
|
261
276
|
│ ├── CVSS-GUIDE.md
|