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.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +181 -0
  3. package/bin/doorman.js +444 -0
  4. package/package.json +74 -0
  5. package/src/ai-fixer.js +559 -0
  6. package/src/ast-scanner.js +434 -0
  7. package/src/auth.js +149 -0
  8. package/src/baseline.js +48 -0
  9. package/src/compliance.js +539 -0
  10. package/src/config.js +466 -0
  11. package/src/custom-rules.js +32 -0
  12. package/src/dashboard.js +202 -0
  13. package/src/detector.js +142 -0
  14. package/src/fix-engine.js +48 -0
  15. package/src/fix-registry-extra.js +95 -0
  16. package/src/fix-registry-go-rust.js +77 -0
  17. package/src/fix-registry-java-csharp.js +77 -0
  18. package/src/fix-registry-js.js +99 -0
  19. package/src/fix-registry-mcp-ai.js +57 -0
  20. package/src/fix-registry-python.js +87 -0
  21. package/src/fixer-ruby-php.js +608 -0
  22. package/src/fixer.js +2113 -0
  23. package/src/hooks.js +115 -0
  24. package/src/ignore.js +176 -0
  25. package/src/index.js +384 -0
  26. package/src/metrics.js +126 -0
  27. package/src/monorepo.js +65 -0
  28. package/src/presets.js +54 -0
  29. package/src/reporter.js +975 -0
  30. package/src/rule-worker.js +36 -0
  31. package/src/rules/ast-rules.js +756 -0
  32. package/src/rules/bugs/accessibility.js +235 -0
  33. package/src/rules/bugs/ai-codegen-fixable.js +172 -0
  34. package/src/rules/bugs/ai-codegen.js +365 -0
  35. package/src/rules/bugs/code-smell-bugs.js +247 -0
  36. package/src/rules/bugs/crypto-bugs.js +195 -0
  37. package/src/rules/bugs/docker-bugs.js +158 -0
  38. package/src/rules/bugs/general.js +361 -0
  39. package/src/rules/bugs/go-bugs.js +279 -0
  40. package/src/rules/bugs/index.js +73 -0
  41. package/src/rules/bugs/js-api.js +257 -0
  42. package/src/rules/bugs/js-array-object.js +210 -0
  43. package/src/rules/bugs/js-async-fixable.js +223 -0
  44. package/src/rules/bugs/js-async.js +211 -0
  45. package/src/rules/bugs/js-closure-scope.js +182 -0
  46. package/src/rules/bugs/js-database.js +203 -0
  47. package/src/rules/bugs/js-error-handling.js +148 -0
  48. package/src/rules/bugs/js-logic.js +261 -0
  49. package/src/rules/bugs/js-memory.js +214 -0
  50. package/src/rules/bugs/js-node.js +361 -0
  51. package/src/rules/bugs/js-react.js +373 -0
  52. package/src/rules/bugs/js-regex.js +200 -0
  53. package/src/rules/bugs/js-state.js +272 -0
  54. package/src/rules/bugs/js-type-coercion.js +318 -0
  55. package/src/rules/bugs/nextjs-bugs.js +242 -0
  56. package/src/rules/bugs/nextjs-fixable.js +120 -0
  57. package/src/rules/bugs/node-fixable.js +178 -0
  58. package/src/rules/bugs/python-advanced.js +245 -0
  59. package/src/rules/bugs/python-fixable.js +98 -0
  60. package/src/rules/bugs/python.js +284 -0
  61. package/src/rules/bugs/react-fixable.js +207 -0
  62. package/src/rules/bugs/ruby-bugs.js +182 -0
  63. package/src/rules/bugs/shell-bugs.js +181 -0
  64. package/src/rules/bugs/silent-failures.js +261 -0
  65. package/src/rules/bugs/ts-bugs.js +235 -0
  66. package/src/rules/bugs/unused-vars.js +65 -0
  67. package/src/rules/compliance/accessibility-ext.js +468 -0
  68. package/src/rules/compliance/education.js +322 -0
  69. package/src/rules/compliance/financial.js +421 -0
  70. package/src/rules/compliance/frameworks.js +507 -0
  71. package/src/rules/compliance/healthcare.js +520 -0
  72. package/src/rules/compliance/index.js +2714 -0
  73. package/src/rules/compliance/regional-eu.js +480 -0
  74. package/src/rules/compliance/regional-international.js +903 -0
  75. package/src/rules/cost/index.js +1993 -0
  76. package/src/rules/data/index.js +2503 -0
  77. package/src/rules/dependencies/index.js +1684 -0
  78. package/src/rules/deployment/index.js +2050 -0
  79. package/src/rules/index.js +71 -0
  80. package/src/rules/infrastructure/index.js +3048 -0
  81. package/src/rules/performance/index.js +3455 -0
  82. package/src/rules/quality/index.js +3175 -0
  83. package/src/rules/reliability/index.js +3040 -0
  84. package/src/rules/scope-rules.js +815 -0
  85. package/src/rules/security/ai-api.js +1177 -0
  86. package/src/rules/security/auth.js +1328 -0
  87. package/src/rules/security/cors.js +127 -0
  88. package/src/rules/security/crypto.js +527 -0
  89. package/src/rules/security/csharp.js +862 -0
  90. package/src/rules/security/csrf.js +193 -0
  91. package/src/rules/security/dart.js +835 -0
  92. package/src/rules/security/deserialization.js +291 -0
  93. package/src/rules/security/file-upload.js +187 -0
  94. package/src/rules/security/go.js +850 -0
  95. package/src/rules/security/headers.js +235 -0
  96. package/src/rules/security/index.js +65 -0
  97. package/src/rules/security/injection.js +1639 -0
  98. package/src/rules/security/mcp-server.js +71 -0
  99. package/src/rules/security/misconfiguration.js +660 -0
  100. package/src/rules/security/oauth-jwt.js +329 -0
  101. package/src/rules/security/path-traversal.js +295 -0
  102. package/src/rules/security/php.js +1054 -0
  103. package/src/rules/security/prototype-pollution.js +283 -0
  104. package/src/rules/security/rate-limiting.js +208 -0
  105. package/src/rules/security/ruby.js +1061 -0
  106. package/src/rules/security/rust.js +693 -0
  107. package/src/rules/security/secrets.js +747 -0
  108. package/src/rules/security/shell.js +647 -0
  109. package/src/rules/security/ssrf.js +298 -0
  110. package/src/rules/security/supply-chain-advanced.js +393 -0
  111. package/src/rules/security/supply-chain.js +734 -0
  112. package/src/rules/security/swift.js +835 -0
  113. package/src/rules/security/taint.js +27 -0
  114. package/src/rules/security/xss.js +520 -0
  115. package/src/scan-cache.js +71 -0
  116. package/src/scanner.js +710 -0
  117. package/src/scope-analyzer.js +685 -0
  118. package/src/share.js +88 -0
  119. package/src/taint.js +300 -0
  120. package/src/telemetry.js +183 -0
  121. package/src/tracer.js +190 -0
  122. package/src/upload.js +35 -0
  123. package/src/worker.js +31 -0
@@ -0,0 +1,193 @@
1
+ const JS_EXT = ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'];
2
+ const isJS = (f) => JS_EXT.some(ext => f.endsWith(ext));
3
+ const isTest = (f) => f.includes('test') || f.includes('spec') || f.includes('mock') || f.includes('fixture');
4
+
5
+ const rules = [
6
+ // SEC-CSRF-001
7
+ {
8
+ id: 'SEC-CSRF-001', category: 'security', severity: 'high', confidence: 'likely',
9
+ title: 'Missing CSRF protection',
10
+ check({ files, stack }) {
11
+ const findings = [];
12
+ if (stack.framework === 'nextjs') return findings; // Next.js server actions have built-in CSRF
13
+ if (stack.runtime !== 'node') return findings;
14
+
15
+ const hasCsrf = Object.keys(stack.dependencies || {}).some(d =>
16
+ ['csurf', 'csrf', 'csrf-csrf', 'lusca'].includes(d)
17
+ );
18
+ if (hasCsrf) return findings;
19
+
20
+ const hasForms = [...files.values()].some(c =>
21
+ c.includes('<form') && (c.includes('method="POST"') || c.includes("method='POST'") || c.includes('method="post"'))
22
+ );
23
+ if (hasForms) {
24
+ findings.push({
25
+ ruleId: 'SEC-CSRF-001', category: 'security', severity: 'high',
26
+ title: 'No CSRF protection on forms with POST method',
27
+ description: 'Forms without CSRF tokens can be exploited by attackers to submit requests on behalf of users.',
28
+ fix: null,
29
+ });
30
+ }
31
+ return findings;
32
+ },
33
+ },
34
+
35
+ // SEC-CSRF-002
36
+ {
37
+ id: 'SEC-CSRF-002', category: 'security', severity: 'critical', confidence: 'definite',
38
+ title: 'CSRF token not validated on server',
39
+ check({ files }) {
40
+ const findings = [];
41
+ for (const [fp, content] of files) {
42
+ if (!isJS(fp) || isTest(fp)) continue;
43
+ if (content.includes('csrf') && content.includes('token')) {
44
+ // Token is referenced but no middleware validates it
45
+ if (!content.includes('csrfProtection') && !content.includes('verifyCsrf') && !content.includes('csrf()')) {
46
+ // Check if it's just being set but never verified
47
+ if (content.includes('csrfToken') && !content.includes('validate') && !content.includes('verify')) {
48
+ findings.push({
49
+ ruleId: 'SEC-CSRF-002', category: 'security', severity: 'critical',
50
+ title: 'CSRF token generated but may not be validated server-side',
51
+ file: fp, fix: null,
52
+ });
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return findings;
58
+ },
59
+ },
60
+
61
+ // SEC-CSRF-003
62
+ {
63
+ id: 'SEC-CSRF-003', category: 'security', severity: 'high', confidence: 'likely',
64
+ title: 'Cookie without SameSite attribute',
65
+ check({ files }) {
66
+ const findings = [];
67
+ for (const [fp, content] of files) {
68
+ if (!isJS(fp) || isTest(fp)) continue;
69
+ const lines = content.split('\n');
70
+ for (let i = 0; i < lines.length; i++) {
71
+ if (lines[i].match(/(?:cookie|session).*(?:httpOnly|secure|maxAge)/i) && !lines[i].includes('sameSite') && !content.includes('sameSite')) {
72
+ findings.push({
73
+ ruleId: 'SEC-CSRF-003', category: 'security', severity: 'high',
74
+ title: 'Cookie configured without SameSite attribute',
75
+ description: 'Set SameSite=Lax or SameSite=Strict to prevent CSRF attacks.',
76
+ file: fp, line: i + 1, fix: null,
77
+ });
78
+ break;
79
+ }
80
+ }
81
+ }
82
+ return findings;
83
+ },
84
+ },
85
+
86
+ // SEC-CSRF-004
87
+ {
88
+ id: 'SEC-CSRF-004', category: 'security', severity: 'high', confidence: 'likely',
89
+ title: 'Cookie without Secure flag',
90
+ check({ files }) {
91
+ const findings = [];
92
+ for (const [fp, content] of files) {
93
+ if (!isJS(fp) || isTest(fp)) continue;
94
+ if (content.match(/cookie.*httpOnly/i) || content.match(/session.*cookie/i)) {
95
+ if (content.includes('secure: false') || (!content.includes('secure:') && !content.includes('secure :'))) {
96
+ findings.push({
97
+ ruleId: 'SEC-CSRF-004', category: 'security', severity: 'high',
98
+ title: 'Session cookie missing Secure flag — will be sent over HTTP',
99
+ file: fp, fix: null,
100
+ });
101
+ }
102
+ }
103
+ }
104
+ return findings;
105
+ },
106
+ },
107
+
108
+ // SEC-CSRF-005
109
+ {
110
+ id: 'SEC-CSRF-005', category: 'security', severity: 'high', confidence: 'likely',
111
+ title: 'Cookie without HttpOnly flag',
112
+ check({ files }) {
113
+ const findings = [];
114
+ for (const [fp, content] of files) {
115
+ if (!isJS(fp) || isTest(fp)) continue;
116
+ if (content.match(/(?:res\.cookie|setCookie|set-cookie)/i)) {
117
+ if (content.includes('httpOnly: false')) {
118
+ const lines = content.split('\n');
119
+ for (let i = 0; i < lines.length; i++) {
120
+ if (lines[i].includes('httpOnly: false')) {
121
+ findings.push({
122
+ ruleId: 'SEC-CSRF-005', category: 'security', severity: 'high',
123
+ title: 'Cookie with httpOnly explicitly set to false — accessible to JavaScript',
124
+ file: fp, line: i + 1, fix: null,
125
+ });
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ return findings;
132
+ },
133
+ },
134
+
135
+ // SEC-CSRF-006
136
+ {
137
+ id: 'SEC-CSRF-006', category: 'security', severity: 'medium', confidence: 'likely',
138
+ title: 'State-changing GET request',
139
+ check({ files }) {
140
+ const findings = [];
141
+ for (const [fp, content] of files) {
142
+ if (!isJS(fp) || isTest(fp)) continue;
143
+ const lines = content.split('\n');
144
+ for (let i = 0; i < lines.length; i++) {
145
+ // Flag GET routes where the inline handler body performs a state-changing DB operation.
146
+ // Check the route line + next 8 lines for actual mutations (deleteOne, destroy, UPDATE, etc.)
147
+ if (lines[i].match(/\.get\s*\(.*['"`]\/[^'"` ]+['"`]/i) &&
148
+ !lines[i].trim().startsWith('//')) {
149
+ const window = lines.slice(i, i + 9).join('\n');
150
+ const stateChange = /\.(?:deleteOne|deleteMany|findByIdAndDelete|destroy|remove|drop)\s*\(|db\.(?:query|run)\s*\(\s*['"`]\s*(?:DELETE|UPDATE|INSERT)/i;
151
+ if (stateChange.test(window)) {
152
+ findings.push({
153
+ ruleId: 'SEC-CSRF-006', category: 'security', severity: 'medium',
154
+ title: 'State-changing operation on GET endpoint — should be POST/PUT/DELETE',
155
+ file: fp, line: i + 1, fix: null,
156
+ });
157
+ }
158
+ }
159
+ }
160
+ }
161
+ return findings;
162
+ },
163
+ },
164
+
165
+ // SEC-CSRF-007
166
+ {
167
+ id: 'SEC-CSRF-007', category: 'security', severity: 'medium', confidence: 'likely',
168
+ title: 'Missing Origin/Referer validation',
169
+ check({ files, stack }) {
170
+ const findings = [];
171
+ if (stack.runtime !== 'node') return findings;
172
+ const hasOriginCheck = [...files.values()].some(c =>
173
+ c.includes('origin') && (c.includes('req.headers') || c.includes('request.headers'))
174
+ );
175
+ const hasCors = Object.keys(stack.dependencies || {}).some(d => d === 'cors');
176
+ if (!hasOriginCheck && !hasCors) {
177
+ const hasMutations = [...files.values()].some(c =>
178
+ c.match(/\.(post|put|patch|delete)\s*\(/)
179
+ );
180
+ if (hasMutations) {
181
+ findings.push({
182
+ ruleId: 'SEC-CSRF-007', category: 'security', severity: 'medium',
183
+ title: 'No Origin or Referer header validation on state-changing endpoints',
184
+ fix: null,
185
+ });
186
+ }
187
+ }
188
+ return findings;
189
+ },
190
+ },
191
+ ];
192
+
193
+ export default rules;