getdoorman 1.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/LICENSE +21 -0
- package/README.md +181 -0
- package/bin/doorman.js +444 -0
- package/package.json +74 -0
- package/src/ai-fixer.js +559 -0
- package/src/ast-scanner.js +434 -0
- package/src/auth.js +149 -0
- package/src/baseline.js +48 -0
- package/src/compliance.js +539 -0
- package/src/config.js +466 -0
- package/src/custom-rules.js +32 -0
- package/src/dashboard.js +202 -0
- package/src/detector.js +142 -0
- package/src/fix-engine.js +48 -0
- package/src/fix-registry-extra.js +95 -0
- package/src/fix-registry-go-rust.js +77 -0
- package/src/fix-registry-java-csharp.js +77 -0
- package/src/fix-registry-js.js +99 -0
- package/src/fix-registry-mcp-ai.js +57 -0
- package/src/fix-registry-python.js +87 -0
- package/src/fixer-ruby-php.js +608 -0
- package/src/fixer.js +2113 -0
- package/src/hooks.js +115 -0
- package/src/ignore.js +176 -0
- package/src/index.js +384 -0
- package/src/metrics.js +126 -0
- package/src/monorepo.js +65 -0
- package/src/presets.js +54 -0
- package/src/reporter.js +975 -0
- package/src/rule-worker.js +36 -0
- package/src/rules/ast-rules.js +756 -0
- package/src/rules/bugs/accessibility.js +235 -0
- package/src/rules/bugs/ai-codegen-fixable.js +172 -0
- package/src/rules/bugs/ai-codegen.js +365 -0
- package/src/rules/bugs/code-smell-bugs.js +247 -0
- package/src/rules/bugs/crypto-bugs.js +195 -0
- package/src/rules/bugs/docker-bugs.js +158 -0
- package/src/rules/bugs/general.js +361 -0
- package/src/rules/bugs/go-bugs.js +279 -0
- package/src/rules/bugs/index.js +73 -0
- package/src/rules/bugs/js-api.js +257 -0
- package/src/rules/bugs/js-array-object.js +210 -0
- package/src/rules/bugs/js-async-fixable.js +223 -0
- package/src/rules/bugs/js-async.js +211 -0
- package/src/rules/bugs/js-closure-scope.js +182 -0
- package/src/rules/bugs/js-database.js +203 -0
- package/src/rules/bugs/js-error-handling.js +148 -0
- package/src/rules/bugs/js-logic.js +261 -0
- package/src/rules/bugs/js-memory.js +214 -0
- package/src/rules/bugs/js-node.js +361 -0
- package/src/rules/bugs/js-react.js +373 -0
- package/src/rules/bugs/js-regex.js +200 -0
- package/src/rules/bugs/js-state.js +272 -0
- package/src/rules/bugs/js-type-coercion.js +318 -0
- package/src/rules/bugs/nextjs-bugs.js +242 -0
- package/src/rules/bugs/nextjs-fixable.js +120 -0
- package/src/rules/bugs/node-fixable.js +178 -0
- package/src/rules/bugs/python-advanced.js +245 -0
- package/src/rules/bugs/python-fixable.js +98 -0
- package/src/rules/bugs/python.js +284 -0
- package/src/rules/bugs/react-fixable.js +207 -0
- package/src/rules/bugs/ruby-bugs.js +182 -0
- package/src/rules/bugs/shell-bugs.js +181 -0
- package/src/rules/bugs/silent-failures.js +261 -0
- package/src/rules/bugs/ts-bugs.js +235 -0
- package/src/rules/bugs/unused-vars.js +65 -0
- package/src/rules/compliance/accessibility-ext.js +468 -0
- package/src/rules/compliance/education.js +322 -0
- package/src/rules/compliance/financial.js +421 -0
- package/src/rules/compliance/frameworks.js +507 -0
- package/src/rules/compliance/healthcare.js +520 -0
- package/src/rules/compliance/index.js +2714 -0
- package/src/rules/compliance/regional-eu.js +480 -0
- package/src/rules/compliance/regional-international.js +903 -0
- package/src/rules/cost/index.js +1993 -0
- package/src/rules/data/index.js +2503 -0
- package/src/rules/dependencies/index.js +1684 -0
- package/src/rules/deployment/index.js +2050 -0
- package/src/rules/index.js +71 -0
- package/src/rules/infrastructure/index.js +3048 -0
- package/src/rules/performance/index.js +3455 -0
- package/src/rules/quality/index.js +3175 -0
- package/src/rules/reliability/index.js +3040 -0
- package/src/rules/scope-rules.js +815 -0
- package/src/rules/security/ai-api.js +1177 -0
- package/src/rules/security/auth.js +1328 -0
- package/src/rules/security/cors.js +127 -0
- package/src/rules/security/crypto.js +527 -0
- package/src/rules/security/csharp.js +862 -0
- package/src/rules/security/csrf.js +193 -0
- package/src/rules/security/dart.js +835 -0
- package/src/rules/security/deserialization.js +291 -0
- package/src/rules/security/file-upload.js +187 -0
- package/src/rules/security/go.js +850 -0
- package/src/rules/security/headers.js +235 -0
- package/src/rules/security/index.js +65 -0
- package/src/rules/security/injection.js +1639 -0
- package/src/rules/security/mcp-server.js +71 -0
- package/src/rules/security/misconfiguration.js +660 -0
- package/src/rules/security/oauth-jwt.js +329 -0
- package/src/rules/security/path-traversal.js +295 -0
- package/src/rules/security/php.js +1054 -0
- package/src/rules/security/prototype-pollution.js +283 -0
- package/src/rules/security/rate-limiting.js +208 -0
- package/src/rules/security/ruby.js +1061 -0
- package/src/rules/security/rust.js +693 -0
- package/src/rules/security/secrets.js +747 -0
- package/src/rules/security/shell.js +647 -0
- package/src/rules/security/ssrf.js +298 -0
- package/src/rules/security/supply-chain-advanced.js +393 -0
- package/src/rules/security/supply-chain.js +734 -0
- package/src/rules/security/swift.js +835 -0
- package/src/rules/security/taint.js +27 -0
- package/src/rules/security/xss.js +520 -0
- package/src/scan-cache.js +71 -0
- package/src/scanner.js +710 -0
- package/src/scope-analyzer.js +685 -0
- package/src/share.js +88 -0
- package/src/taint.js +300 -0
- package/src/telemetry.js +183 -0
- package/src/tracer.js +190 -0
- package/src/upload.js +35 -0
- package/src/worker.js +31 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// MCP Server Security Rules (50 rules)
|
|
2
|
+
const SKIP_PATH = /node_modules|\.min\.js|vendor|dist\/|build\/|\.test\.|\.spec\./;
|
|
3
|
+
function scanLines(content, pattern, path, rule) {
|
|
4
|
+
const findings = [];
|
|
5
|
+
const lines = content.split('\n');
|
|
6
|
+
for (let i = 0; i < lines.length; i++) {
|
|
7
|
+
if (pattern.test(lines[i])) findings.push({ ruleId: rule.id, file: path, line: i + 1, title: rule.title, severity: rule.severity });
|
|
8
|
+
}
|
|
9
|
+
return findings;
|
|
10
|
+
}
|
|
11
|
+
function checkAll(rule, files, pattern) {
|
|
12
|
+
const findings = [];
|
|
13
|
+
for (const [path, content] of files) {
|
|
14
|
+
if (SKIP_PATH.test(path)) continue;
|
|
15
|
+
findings.push(...scanLines(content, pattern, path, rule));
|
|
16
|
+
}
|
|
17
|
+
return findings;
|
|
18
|
+
}
|
|
19
|
+
const rules = [
|
|
20
|
+
{ id: 'SEC-MCP-001', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP tool without input validation', check({ files }) { return checkAll(this, files, /server\.tool\([^,]+,\s*async\s*\(\s*\{/); } },
|
|
21
|
+
{ id: 'SEC-MCP-002', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP params in file operation', check({ files }) { return checkAll(this, files, /fs\.\w+\(\s*(?:params|args|input)\.\w+/); } },
|
|
22
|
+
{ id: 'SEC-MCP-003', category: 'security', severity: 'critical', confidence: 'likely', title: 'MCP params in exec/spawn', check({ files }) { return checkAll(this, files, /(?:exec|spawn|execSync)\(\s*(?:params|args|input)\./); } },
|
|
23
|
+
{ id: 'SEC-MCP-004', category: 'security', severity: 'critical', confidence: 'likely', title: 'MCP params in SQL query', check({ files }) { return checkAll(this, files, /(?:query|execute)\(\s*`[^`]*\$\{(?:params|args|input)\./); } },
|
|
24
|
+
{ id: 'SEC-MCP-005', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP params in eval', check({ files }) { return checkAll(this, files, /(?:eval|new\s+Function)\(\s*(?:params|args|input)\./); } },
|
|
25
|
+
{ id: 'SEC-MCP-006', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP tool without schema', check({ files }) { return checkAll(this, files, /server\.tool\(\s*['"][^'"]+['"]\s*,\s*(?:async\s*)?\(/); } },
|
|
26
|
+
{ id: 'SEC-MCP-007', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP params in URL (SSRF)', check({ files }) { return checkAll(this, files, /(?:fetch|axios|got|request)\(\s*(?:params|args|input)\./); } },
|
|
27
|
+
{ id: 'SEC-MCP-008', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP params in regex (ReDoS)', check({ files }) { return checkAll(this, files, /new\s+RegExp\(\s*(?:params|args|input)\./); } },
|
|
28
|
+
{ id: 'SEC-MCP-009', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP params in path.join', check({ files }) { return checkAll(this, files, /path\.(?:join|resolve)\([^,]*,\s*(?:params|args|input)\./); } },
|
|
29
|
+
{ id: 'SEC-MCP-010', category: 'security', severity: 'medium', confidence: 'likely', title: 'MCP params in template literal', check({ files }) { return checkAll(this, files, /`[^`]*\$\{(?:params|args|input)\.(?!name\b|type\b)/); } },
|
|
30
|
+
{ id: 'SEC-MCP-011', category: 'security', severity: 'high', confidence: 'suggestion', title: 'MCP server without auth', check({ files }) { return checkAll(this, files, /new\s+(?:McpServer|Server)\(\s*\{(?![^}]*auth)/); } },
|
|
31
|
+
{ id: 'SEC-MCP-012', category: 'security', severity: 'high', confidence: 'suggestion', title: 'MCP handler without permission check', check({ files }) { return checkAll(this, files, /setRequestHandler\(\s*\w+\s*,\s*async/); } },
|
|
32
|
+
{ id: 'SEC-MCP-013', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP API key hardcoded', check({ files }) { return checkAll(this, files, /(?:mcp|MCP).*(?:key|token|secret)\s*[:=]\s*['"][a-zA-Z0-9]{16,}['"]/); } },
|
|
33
|
+
{ id: 'SEC-MCP-014', category: 'security', severity: 'medium', confidence: 'likely', title: 'MCP transport without TLS', check({ files }) { return checkAll(this, files, /transport.*['"]http:\/\//); } },
|
|
34
|
+
{ id: 'SEC-MCP-015', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP wildcard permissions', check({ files }) { return checkAll(this, files, /allowedTools:\s*\[\s*['"]?\*['"]?\s*\]/); } },
|
|
35
|
+
{ id: 'SEC-MCP-016', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no CORS config', check({ files }) { return checkAll(this, files, /(?:SSE|Http)ServerTransport\(/); } },
|
|
36
|
+
{ id: 'SEC-MCP-017', category: 'security', severity: 'low', confidence: 'suggestion', title: 'MCP broad file access', check({ files }) { return checkAll(this, files, /readFile(?:Sync)?\(\s*(?:params|args|input)\.(?:path|file)/); } },
|
|
37
|
+
{ id: 'SEC-MCP-018', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no rate limiting', check({ files }) { return checkAll(this, files, /new\s+(?:McpServer|Server)\(\s*\{(?![^}]*rateLimit)/); } },
|
|
38
|
+
{ id: 'SEC-MCP-019', category: 'security', severity: 'low', confidence: 'suggestion', title: 'MCP no request size limit', check({ files }) { return checkAll(this, files, /new\s+\w+Transport\(\s*\{(?![^}]*maxSize)/); } },
|
|
39
|
+
{ id: 'SEC-MCP-020', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no token validation', check({ files }) { return checkAll(this, files, /server\.connect\(\s*transport\s*\)/); } },
|
|
40
|
+
{ id: 'SEC-MCP-021', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP exposes env vars', check({ files }) { return checkAll(this, files, /(?:content|text|result).*process\.env/); } },
|
|
41
|
+
{ id: 'SEC-MCP-022', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP unfiltered DB rows', check({ files }) { return checkAll(this, files, /JSON\.stringify\(\s*(?:rows|results|records)\s*\)/); } },
|
|
42
|
+
{ id: 'SEC-MCP-023', category: 'security', severity: 'medium', confidence: 'likely', title: 'MCP stack traces exposed', check({ files }) { return checkAll(this, files, /(?:error|err)\.stack.*(?:content|text)/); } },
|
|
43
|
+
{ id: 'SEC-MCP-024', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP logs sensitive params', check({ files }) { return checkAll(this, files, /console\.log\(\s*(?:JSON\.stringify\()?\s*(?:params|args)\b/); } },
|
|
44
|
+
{ id: 'SEC-MCP-025', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP raw file in response', check({ files }) { return checkAll(this, files, /readFileSync\([^)]+\)\.toString\(\)/); } },
|
|
45
|
+
{ id: 'SEC-MCP-026', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP credentials in response', check({ files }) { return checkAll(this, files, /(?:password|secret|token|apiKey).*(?:content|text):\s/i); } },
|
|
46
|
+
{ id: 'SEC-MCP-027', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no response size limit', check({ files }) { return checkAll(this, files, /text:\s*JSON\.stringify/); } },
|
|
47
|
+
{ id: 'SEC-MCP-028', category: 'security', severity: 'low', confidence: 'suggestion', title: 'MCP description leaks impl', check({ files }) { return checkAll(this, files, /description:\s*['"].*(?:database|internal|private)/i); } },
|
|
48
|
+
{ id: 'SEC-MCP-029', category: 'security', severity: 'medium', confidence: 'likely', title: 'MCP cross-tool data leak', check({ files }) { return checkAll(this, files, /(?:global|globalThis)\.\w+.*=.*(?:params|args)\./); } },
|
|
49
|
+
{ id: 'SEC-MCP-030', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP debug mode enabled', check({ files }) { return checkAll(this, files, /(?:debug|verbose)\s*[:=]\s*true/); } },
|
|
50
|
+
{ id: 'SEC-MCP-031', category: 'security', severity: 'critical', confidence: 'likely', title: 'MCP shell injection', check({ files }) { return checkAll(this, files, /exec\(\s*`[^`]*\$\{(?:params|args|input)\./); } },
|
|
51
|
+
{ id: 'SEC-MCP-032', category: 'security', severity: 'critical', confidence: 'likely', title: 'MCP template injection', check({ files }) { return checkAll(this, files, /(?:render|compile|template)\(\s*(?:params|args|input)\./); } },
|
|
52
|
+
{ id: 'SEC-MCP-033', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP LDAP injection', check({ files }) { return checkAll(this, files, /(?:ldap|LDAP).*(?:search|bind).*(?:params|args)\./); } },
|
|
53
|
+
{ id: 'SEC-MCP-034', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP XML injection', check({ files }) { return checkAll(this, files, /[<].*\$\{(?:params|args|input)\./); } },
|
|
54
|
+
{ id: 'SEC-MCP-035', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP header injection', check({ files }) { return checkAll(this, files, /setHeader\([^,]+,\s*(?:params|args|input)\./); } },
|
|
55
|
+
{ id: 'SEC-MCP-036', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP open redirect', check({ files }) { return checkAll(this, files, /redirect\(\s*(?:params|args|input)\./); } },
|
|
56
|
+
{ id: 'SEC-MCP-037', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP NoSQL injection', check({ files }) { return checkAll(this, files, /\.find\(\s*\{[^}]*:\s*(?:params|args|input)\./); } },
|
|
57
|
+
{ id: 'SEC-MCP-038', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP prompt injection risk', check({ files }) { return checkAll(this, files, /(?:prompt|system|message).*(?:params|args|input)\.\w+/); } },
|
|
58
|
+
{ id: 'SEC-MCP-039', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP unsafe deserialization', check({ files }) { return checkAll(this, files, /(?:deserialize|unserialize)\(\s*(?:params|args|input)\./); } },
|
|
59
|
+
{ id: 'SEC-MCP-040', category: 'security', severity: 'medium', confidence: 'likely', title: 'MCP dynamic import', check({ files }) { return checkAll(this, files, /(?:require|import)\(\s*(?:params|args|input)\./); } },
|
|
60
|
+
{ id: 'SEC-MCP-041', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no error handler', check({ files }) { return checkAll(this, files, /server\.connect\(\s*transport\s*\)/); } },
|
|
61
|
+
{ id: 'SEC-MCP-042', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no tool timeout', check({ files }) { return checkAll(this, files, /server\.tool\([^,]+,\s*async/); } },
|
|
62
|
+
{ id: 'SEC-MCP-043', category: 'security', severity: 'low', confidence: 'suggestion', title: 'MCP no audit logging', check({ files }) { return checkAll(this, files, /server\.tool\([^,]+,\s*async\s*\(/); } },
|
|
63
|
+
{ id: 'SEC-MCP-044', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP swallows errors', check({ files }) { return checkAll(this, files, /catch\s*\(\s*\w*\s*\)\s*\{\s*return\s*\{/); } },
|
|
64
|
+
{ id: 'SEC-MCP-045', category: 'security', severity: 'low', confidence: 'suggestion', title: 'MCP hardcoded port', check({ files }) { return checkAll(this, files, /\.listen\(\s*\d{4,5}\s*\)/); } },
|
|
65
|
+
{ id: 'SEC-MCP-046', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP no disconnect cleanup', check({ files }) { return checkAll(this, files, /transport\.start/); } },
|
|
66
|
+
{ id: 'SEC-MCP-047', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP unrestricted dir listing', check({ files }) { return checkAll(this, files, /(?:readdir|readdirSync)\(\s*(?:params|args|input)\./); } },
|
|
67
|
+
{ id: 'SEC-MCP-048', category: 'security', severity: 'high', confidence: 'likely', title: 'MCP process execution', check({ files }) { return checkAll(this, files, /(?:spawn|fork|execFile)\(\s*(?:params|args|input)\./); } },
|
|
68
|
+
{ id: 'SEC-MCP-049', category: 'security', severity: 'medium', confidence: 'suggestion', title: 'MCP outbound requests', check({ files }) { return checkAll(this, files, /(?:http|https)\.(?:get|request)\(\s*(?:params|args|input)\./); } },
|
|
69
|
+
{ id: 'SEC-MCP-050', category: 'security', severity: 'low', confidence: 'suggestion', title: 'MCP SDK not pinned', check({ files }) { return checkAll(this, files, /"@modelcontextprotocol\/sdk":\s*"\^/); } },
|
|
70
|
+
];
|
|
71
|
+
export default rules;
|