@datahogo/core 0.1.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 (153) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +17 -0
  3. package/dist/engines/config.d.ts +3 -0
  4. package/dist/engines/config.d.ts.map +1 -0
  5. package/dist/engines/config.js +433 -0
  6. package/dist/engines/config.js.map +1 -0
  7. package/dist/engines/dast.d.ts +3 -0
  8. package/dist/engines/dast.d.ts.map +1 -0
  9. package/dist/engines/dast.js +167 -0
  10. package/dist/engines/dast.js.map +1 -0
  11. package/dist/engines/db-rules.d.ts +3 -0
  12. package/dist/engines/db-rules.d.ts.map +1 -0
  13. package/dist/engines/db-rules.js +166 -0
  14. package/dist/engines/db-rules.js.map +1 -0
  15. package/dist/engines/dependencies.d.ts +3 -0
  16. package/dist/engines/dependencies.d.ts.map +1 -0
  17. package/dist/engines/dependencies.js +167 -0
  18. package/dist/engines/dependencies.js.map +1 -0
  19. package/dist/engines/github-actions.d.ts +3 -0
  20. package/dist/engines/github-actions.d.ts.map +1 -0
  21. package/dist/engines/github-actions.js +215 -0
  22. package/dist/engines/github-actions.js.map +1 -0
  23. package/dist/engines/gitleaks.d.ts +3 -0
  24. package/dist/engines/gitleaks.d.ts.map +1 -0
  25. package/dist/engines/gitleaks.js +107 -0
  26. package/dist/engines/gitleaks.js.map +1 -0
  27. package/dist/engines/npm-audit.d.ts +3 -0
  28. package/dist/engines/npm-audit.d.ts.map +1 -0
  29. package/dist/engines/npm-audit.js +113 -0
  30. package/dist/engines/npm-audit.js.map +1 -0
  31. package/dist/engines/patterns.d.ts +3 -0
  32. package/dist/engines/patterns.d.ts.map +1 -0
  33. package/dist/engines/patterns.js +1330 -0
  34. package/dist/engines/patterns.js.map +1 -0
  35. package/dist/engines/secrets.d.ts +4 -0
  36. package/dist/engines/secrets.d.ts.map +1 -0
  37. package/dist/engines/secrets.js +260 -0
  38. package/dist/engines/secrets.js.map +1 -0
  39. package/dist/engines/semgrep.d.ts +3 -0
  40. package/dist/engines/semgrep.d.ts.map +1 -0
  41. package/dist/engines/semgrep.js +173 -0
  42. package/dist/engines/semgrep.js.map +1 -0
  43. package/dist/engines/types.d.ts +30 -0
  44. package/dist/engines/types.d.ts.map +1 -0
  45. package/dist/engines/types.js +3 -0
  46. package/dist/engines/types.js.map +1 -0
  47. package/dist/engines/url-scanner.d.ts +3 -0
  48. package/dist/engines/url-scanner.d.ts.map +1 -0
  49. package/dist/engines/url-scanner.js +469 -0
  50. package/dist/engines/url-scanner.js.map +1 -0
  51. package/dist/index.d.ts +8 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +8 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/orchestrator.d.ts +32 -0
  56. package/dist/orchestrator.d.ts.map +1 -0
  57. package/dist/orchestrator.js +237 -0
  58. package/dist/orchestrator.js.map +1 -0
  59. package/dist/rules/.gitkeep +0 -0
  60. package/dist/rules/ai-llm-security.yaml +199 -0
  61. package/dist/rules/api-security.yaml +489 -0
  62. package/dist/rules/auth-patterns.yaml +406 -0
  63. package/dist/rules/crypto-patterns.yaml +227 -0
  64. package/dist/rules/database-cloud-security.yaml +169 -0
  65. package/dist/rules/general-security.yaml +588 -0
  66. package/dist/rules/injection-patterns.yaml +318 -0
  67. package/dist/rules/nextjs-security.yaml +532 -0
  68. package/dist/rules/node-security.yaml +380 -0
  69. package/dist/rules/rules/.gitkeep +0 -0
  70. package/dist/rules/rules/ai-llm-security.yaml +199 -0
  71. package/dist/rules/rules/api-security.yaml +489 -0
  72. package/dist/rules/rules/auth-patterns.yaml +406 -0
  73. package/dist/rules/rules/crypto-patterns.yaml +227 -0
  74. package/dist/rules/rules/database-cloud-security.yaml +169 -0
  75. package/dist/rules/rules/general-security.yaml +588 -0
  76. package/dist/rules/rules/injection-patterns.yaml +318 -0
  77. package/dist/rules/rules/nextjs-security.yaml +532 -0
  78. package/dist/rules/rules/node-security.yaml +380 -0
  79. package/dist/rules/rules/supabase-security.yaml +387 -0
  80. package/dist/rules/supabase-security.yaml +387 -0
  81. package/dist/scanning/agents/csharp-agent.d.ts +12 -0
  82. package/dist/scanning/agents/csharp-agent.d.ts.map +1 -0
  83. package/dist/scanning/agents/csharp-agent.js +592 -0
  84. package/dist/scanning/agents/csharp-agent.js.map +1 -0
  85. package/dist/scanning/agents/go-agent.d.ts +14 -0
  86. package/dist/scanning/agents/go-agent.d.ts.map +1 -0
  87. package/dist/scanning/agents/go-agent.js +641 -0
  88. package/dist/scanning/agents/go-agent.js.map +1 -0
  89. package/dist/scanning/agents/java-agent.d.ts +8 -0
  90. package/dist/scanning/agents/java-agent.d.ts.map +1 -0
  91. package/dist/scanning/agents/java-agent.js +807 -0
  92. package/dist/scanning/agents/java-agent.js.map +1 -0
  93. package/dist/scanning/agents/javascript-agent.d.ts +8 -0
  94. package/dist/scanning/agents/javascript-agent.d.ts.map +1 -0
  95. package/dist/scanning/agents/javascript-agent.js +77 -0
  96. package/dist/scanning/agents/javascript-agent.js.map +1 -0
  97. package/dist/scanning/agents/mobile-agent.d.ts +8 -0
  98. package/dist/scanning/agents/mobile-agent.d.ts.map +1 -0
  99. package/dist/scanning/agents/mobile-agent.js +916 -0
  100. package/dist/scanning/agents/mobile-agent.js.map +1 -0
  101. package/dist/scanning/agents/php-agent.d.ts +8 -0
  102. package/dist/scanning/agents/php-agent.d.ts.map +1 -0
  103. package/dist/scanning/agents/php-agent.js +679 -0
  104. package/dist/scanning/agents/php-agent.js.map +1 -0
  105. package/dist/scanning/agents/python-agent.d.ts +8 -0
  106. package/dist/scanning/agents/python-agent.d.ts.map +1 -0
  107. package/dist/scanning/agents/python-agent.js +701 -0
  108. package/dist/scanning/agents/python-agent.js.map +1 -0
  109. package/dist/scanning/agents/supabase-agent.d.ts +8 -0
  110. package/dist/scanning/agents/supabase-agent.d.ts.map +1 -0
  111. package/dist/scanning/agents/supabase-agent.js +484 -0
  112. package/dist/scanning/agents/supabase-agent.js.map +1 -0
  113. package/dist/scanning/orchestrator.d.ts +29 -0
  114. package/dist/scanning/orchestrator.d.ts.map +1 -0
  115. package/dist/scanning/orchestrator.js +186 -0
  116. package/dist/scanning/orchestrator.js.map +1 -0
  117. package/dist/scanning/tech-detector.d.ts +12 -0
  118. package/dist/scanning/tech-detector.d.ts.map +1 -0
  119. package/dist/scanning/tech-detector.js +252 -0
  120. package/dist/scanning/tech-detector.js.map +1 -0
  121. package/dist/scanning/types.d.ts +87 -0
  122. package/dist/scanning/types.d.ts.map +1 -0
  123. package/dist/scanning/types.js +5 -0
  124. package/dist/scanning/types.js.map +1 -0
  125. package/dist/utils/child-process.d.ts +2 -0
  126. package/dist/utils/child-process.d.ts.map +1 -0
  127. package/dist/utils/child-process.js +4 -0
  128. package/dist/utils/child-process.js.map +1 -0
  129. package/dist/utils/context-classifier.d.ts +11 -0
  130. package/dist/utils/context-classifier.d.ts.map +1 -0
  131. package/dist/utils/context-classifier.js +79 -0
  132. package/dist/utils/context-classifier.js.map +1 -0
  133. package/dist/utils/exec.d.ts +18 -0
  134. package/dist/utils/exec.d.ts.map +1 -0
  135. package/dist/utils/exec.js +51 -0
  136. package/dist/utils/exec.js.map +1 -0
  137. package/dist/utils/file-filter.d.ts +4 -0
  138. package/dist/utils/file-filter.d.ts.map +1 -0
  139. package/dist/utils/file-filter.js +68 -0
  140. package/dist/utils/file-filter.js.map +1 -0
  141. package/dist/utils/fs.d.ts +2 -0
  142. package/dist/utils/fs.d.ts.map +1 -0
  143. package/dist/utils/fs.js +5 -0
  144. package/dist/utils/fs.js.map +1 -0
  145. package/dist/utils/logger.d.ts +12 -0
  146. package/dist/utils/logger.d.ts.map +1 -0
  147. package/dist/utils/logger.js +27 -0
  148. package/dist/utils/logger.js.map +1 -0
  149. package/dist/utils/post-processor.d.ts +10 -0
  150. package/dist/utils/post-processor.d.ts.map +1 -0
  151. package/dist/utils/post-processor.js +183 -0
  152. package/dist/utils/post-processor.js.map +1 -0
  153. package/package.json +44 -0
@@ -0,0 +1,532 @@
1
+ rules:
2
+ # ============================================================
3
+ # React / Next.js Security Rules
4
+ # ============================================================
5
+
6
+ - id: datahogo-dangerous-inner-html
7
+ pattern: dangerouslySetInnerHTML={{ __html: $VAR }}
8
+ message: "dangerouslySetInnerHTML can lead to XSS if input is not sanitized with DOMPurify. Always sanitize user input before rendering HTML."
9
+ severity: WARNING
10
+ languages: [typescript, javascript, tsx, jsx]
11
+ metadata:
12
+ datahogo_id: 46
13
+ datahogo_category: "react-nextjs"
14
+ owasp_ref: "A03:2021"
15
+
16
+ - id: datahogo-tokens-in-localstorage
17
+ patterns:
18
+ - pattern: localStorage.setItem($KEY, $VALUE)
19
+ - metavariable-regex:
20
+ metavariable: $KEY
21
+ regex: (?i)(token|jwt|auth|session|access_token|refresh_token|api_key)
22
+ message: "Storing authentication tokens in localStorage is insecure. Use httpOnly cookies or secure session management instead."
23
+ severity: WARNING
24
+ languages: [typescript, javascript]
25
+ metadata:
26
+ datahogo_id: 47
27
+ datahogo_category: "react-nextjs"
28
+ owasp_ref: "A07:2021"
29
+
30
+ - id: datahogo-next-data-secrets
31
+ patterns:
32
+ - pattern: |
33
+ export async function getServerSideProps(...) {
34
+ ...
35
+ return {
36
+ props: { ...$PROPS... }
37
+ }
38
+ }
39
+ - metavariable-regex:
40
+ metavariable: $PROPS
41
+ regex: (?i)(api_key|secret|password|private_key|token|credentials)
42
+ message: "Sensitive data in getServerSideProps props will be serialized to __NEXT_DATA__ and exposed in the HTML. Never pass secrets to client components."
43
+ severity: WARNING
44
+ languages: [typescript, javascript]
45
+ metadata:
46
+ datahogo_id: 48
47
+ datahogo_category: "react-nextjs"
48
+ owasp_ref: "A01:2021"
49
+
50
+ - id: datahogo-open-cors-api
51
+ patterns:
52
+ - pattern-either:
53
+ - pattern: headers.set("Access-Control-Allow-Origin", "*")
54
+ - pattern: headers.append("Access-Control-Allow-Origin", "*")
55
+ - pattern: res.setHeader("Access-Control-Allow-Origin", "*")
56
+ - pattern-inside: |
57
+ export async function $METHOD(...) {
58
+ ...
59
+ }
60
+ message: "Open CORS policy (Access-Control-Allow-Origin: *) allows any origin to access your API. Restrict to specific trusted domains."
61
+ severity: WARNING
62
+ languages: [typescript, javascript]
63
+ metadata:
64
+ datahogo_id: 50
65
+ datahogo_category: "react-nextjs"
66
+ owasp_ref: "A05:2021"
67
+
68
+ - id: datahogo-no-csrf-server-action
69
+ patterns:
70
+ - pattern: |
71
+ "use server";
72
+ export async function $ACTION(...) {
73
+ ...
74
+ }
75
+ - pattern-not: |
76
+ "use server";
77
+ export async function $ACTION(...) {
78
+ ...
79
+ verifyRequestOrigin(...)
80
+ ...
81
+ }
82
+ - pattern-not: |
83
+ "use server";
84
+ export async function $ACTION(...) {
85
+ ...
86
+ csrf(...)
87
+ ...
88
+ }
89
+ message: "Server Actions should verify request origin to prevent CSRF attacks. Add origin validation or CSRF token checks."
90
+ severity: WARNING
91
+ languages: [typescript, javascript]
92
+ metadata:
93
+ datahogo_id: 51
94
+ datahogo_category: "react-nextjs"
95
+
96
+ - id: datahogo-nextjs-middleware-bypass
97
+ patterns:
98
+ - pattern-either:
99
+ - pattern: |
100
+ export const config = {
101
+ matcher: [..., $PATTERN, ...]
102
+ }
103
+ - pattern: |
104
+ export const config = {
105
+ matcher: $PATTERN
106
+ }
107
+ - metavariable-regex:
108
+ metavariable: $PATTERN
109
+ regex: ^(?!.*_next).*$
110
+ message: "Middleware matcher may be vulnerable to bypass. Ensure paths starting with /_next are excluded to prevent CVE-2025-29927."
111
+ severity: ERROR
112
+ languages: [typescript, javascript]
113
+ metadata:
114
+ datahogo_id: 52
115
+ datahogo_category: "react-nextjs"
116
+
117
+ - id: datahogo-auth-frontend-only
118
+ patterns:
119
+ - pattern: |
120
+ "use client";
121
+ ...
122
+ - pattern-either:
123
+ - pattern: if ($USER.role === "admin") { ... }
124
+ - pattern: if ($USER.isAdmin) { ... }
125
+ - pattern: if ($SESSION.user.role === $ROLE) { ... }
126
+ - pattern: |
127
+ $USER.role === $ROLE ? ... : ...
128
+ message: "Auth checks in client components can be bypassed. Always verify permissions on the server (API routes, Server Components)."
129
+ severity: WARNING
130
+ languages: [typescript, javascript, tsx, jsx]
131
+ metadata:
132
+ datahogo_id: 57
133
+ datahogo_category: "vibecoding"
134
+ owasp_ref: "A01:2021"
135
+
136
+ - id: datahogo-api-no-auth-check
137
+ patterns:
138
+ - pattern: |
139
+ export async function $METHOD(req: Request) {
140
+ ...
141
+ }
142
+ - metavariable-regex:
143
+ metavariable: $METHOD
144
+ regex: (GET|POST|PUT|PATCH|DELETE)
145
+ - pattern-not: |
146
+ export async function $METHOD(req: Request) {
147
+ ...
148
+ $CLIENT.auth.getUser()
149
+ ...
150
+ }
151
+ - pattern-not: |
152
+ export async function $METHOD(req: Request) {
153
+ ...
154
+ getUser()
155
+ ...
156
+ }
157
+ - pattern-not: |
158
+ export async function $METHOD(req: Request) {
159
+ ...
160
+ getSession()
161
+ ...
162
+ }
163
+ - pattern-not: |
164
+ export async function $METHOD(req: Request) {
165
+ ...
166
+ verifyAuth()
167
+ ...
168
+ }
169
+ message: "API route handler is missing authentication check. Always verify user session before processing requests."
170
+ severity: ERROR
171
+ languages: [typescript, javascript]
172
+ metadata:
173
+ datahogo_id: 58
174
+ datahogo_category: "vibecoding"
175
+ owasp_ref: "A01:2021"
176
+
177
+ - id: datahogo-dom-xss-document-write
178
+ patterns:
179
+ - pattern-either:
180
+ - pattern: document.write($VAR)
181
+ - pattern: $ELEM.innerHTML = $VAR
182
+ - pattern-either:
183
+ - pattern-regex: location
184
+ - pattern-regex: document\.URL
185
+ - pattern-regex: window\.name
186
+ - pattern-regex: document\.referrer
187
+ message: "DOM-based XSS vulnerability. Using document.write or innerHTML with untrusted input (location, URL, etc.) allows script injection."
188
+ severity: WARNING
189
+ languages: [typescript, javascript]
190
+ metadata:
191
+ datahogo_id: 86
192
+ datahogo_category: "frontend"
193
+ owasp_ref: "A03:2021"
194
+
195
+ - id: datahogo-stored-xss-no-sanitize
196
+ patterns:
197
+ - pattern-either:
198
+ - pattern: dangerouslySetInnerHTML={{ __html: $USER_DATA }}
199
+ - pattern: $ELEM.innerHTML = $USER_DATA
200
+ - pattern-not: dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(...) }}
201
+ - pattern-not: $ELEM.innerHTML = DOMPurify.sanitize(...)
202
+ message: "Stored XSS risk. User-generated content rendered without sanitization. Use DOMPurify or avoid innerHTML entirely."
203
+ severity: WARNING
204
+ languages: [typescript, javascript, tsx, jsx]
205
+ metadata:
206
+ datahogo_id: 87
207
+ datahogo_category: "frontend"
208
+ owasp_ref: "A03:2021"
209
+
210
+ - id: datahogo-postmessage-no-origin
211
+ patterns:
212
+ - pattern: |
213
+ window.addEventListener("message", $HANDLER)
214
+ - pattern-not: |
215
+ window.addEventListener("message", ($EVENT) => {
216
+ ...
217
+ $EVENT.origin
218
+ ...
219
+ })
220
+ - pattern-not: |
221
+ window.addEventListener("message", function($EVENT) {
222
+ ...
223
+ $EVENT.origin
224
+ ...
225
+ })
226
+ message: "postMessage listener missing origin verification. Always check event.origin to prevent XSS from untrusted domains."
227
+ severity: WARNING
228
+ languages: [typescript, javascript]
229
+ metadata:
230
+ datahogo_id: 88
231
+ datahogo_category: "frontend"
232
+ owasp_ref: "A01:2021"
233
+
234
+ - id: datahogo-no-x-frame-options
235
+ patterns:
236
+ - pattern-either:
237
+ - pattern: |
238
+ export async function $METHOD(...) {
239
+ ...
240
+ return new Response(...)
241
+ }
242
+ - pattern: |
243
+ export async function middleware(...) {
244
+ ...
245
+ return NextResponse.next()
246
+ }
247
+ - pattern-not: |
248
+ $HEADERS.set("X-Frame-Options", ...)
249
+ - pattern-not: |
250
+ $HEADERS.append("X-Frame-Options", ...)
251
+ message: "Missing X-Frame-Options header allows clickjacking attacks. Set to DENY or SAMEORIGIN in middleware or API responses."
252
+ severity: WARNING
253
+ languages: [typescript, javascript]
254
+ metadata:
255
+ datahogo_id: 89
256
+ datahogo_category: "frontend"
257
+
258
+ - id: datahogo-iframe-no-sandbox
259
+ pattern-regex: <iframe(?:(?!sandbox)[^>])*src=
260
+ message: "Iframe without sandbox attribute can execute scripts and access parent window. Add sandbox='allow-scripts allow-same-origin' with minimal permissions."
261
+ severity: WARNING
262
+ languages: [typescript, javascript, tsx, jsx]
263
+ metadata:
264
+ datahogo_id: 90
265
+ datahogo_category: "frontend"
266
+
267
+ - id: datahogo-cdn-no-integrity
268
+ patterns:
269
+ - pattern-either:
270
+ - pattern-regex: <script\s+src=["']https?://(?:cdn|cdnjs|unpkg|jsdelivr)
271
+ - pattern-regex: <link\s+(?:[^>]*\s+)?href=["']https?://(?:cdn|cdnjs|unpkg|jsdelivr)
272
+ - pattern-not-regex: integrity=["']sha
273
+ message: "CDN resource loaded without Subresource Integrity (SRI). Add integrity attribute to prevent tampering."
274
+ severity: INFO
275
+ languages: [typescript, javascript, tsx, jsx, html]
276
+ metadata:
277
+ datahogo_id: 91
278
+ datahogo_category: "frontend"
279
+
280
+ - id: datahogo-client-redirect-unsafe
281
+ patterns:
282
+ - pattern-either:
283
+ - pattern: window.location = $URL
284
+ - pattern: window.location.href = $URL
285
+ - pattern: location.href = $URL
286
+ - pattern: router.push($URL)
287
+ - pattern-either:
288
+ - pattern: window.location = $PARAMS.get(...)
289
+ - pattern: window.location.href = searchParams.get(...)
290
+ - pattern: router.push(req.query.$PARAM)
291
+ message: "Client-side redirect with unvalidated user input enables open redirect attacks. Validate URL against whitelist before redirecting."
292
+ severity: WARNING
293
+ languages: [typescript, javascript]
294
+ metadata:
295
+ datahogo_id: 92
296
+ datahogo_category: "frontend"
297
+ owasp_ref: "A01:2021"
298
+
299
+ - id: datahogo-sensitive-data-in-url
300
+ patterns:
301
+ - pattern-either:
302
+ - pattern: router.push(`/...?token=${$TOKEN}`)
303
+ - pattern: window.location = `...?password=${$PWD}`
304
+ - pattern: redirect(`...?api_key=${$KEY}`)
305
+ - metavariable-regex:
306
+ metavariable: $TOKEN
307
+ regex: (?i)(token|password|secret|api_key|private_key|credentials)
308
+ message: "Sensitive data in URL query parameters will be logged in browser history and server logs. Use POST body or secure headers instead."
309
+ severity: WARNING
310
+ languages: [typescript, javascript]
311
+ metadata:
312
+ datahogo_id: 93
313
+ datahogo_category: "frontend"
314
+ owasp_ref: "A04:2021"
315
+
316
+ - id: datahogo-no-error-boundary
317
+ patterns:
318
+ - pattern: |
319
+ export default function $LAYOUT({ children }: { children: React.ReactNode }) {
320
+ return (
321
+ ...
322
+ {children}
323
+ ...
324
+ )
325
+ }
326
+ - pattern-not: |
327
+ export default function $LAYOUT({ children }: { children: React.ReactNode }) {
328
+ return (
329
+ ...
330
+ <ErrorBoundary>
331
+ {children}
332
+ </ErrorBoundary>
333
+ ...
334
+ )
335
+ }
336
+ - pattern-inside: |
337
+ ...
338
+ app/$ROUTE/layout.tsx
339
+ message: "No React Error Boundary in layout. Unhandled errors can expose stack traces to users. Wrap children in ErrorBoundary component."
340
+ severity: INFO
341
+ languages: [typescript, javascript, tsx, jsx]
342
+ metadata:
343
+ datahogo_id: 174
344
+ datahogo_category: "best-practices"
345
+
346
+ # ============================================================
347
+ # Additional Next.js Specific Patterns
348
+ # ============================================================
349
+
350
+ - id: datahogo-next-env-client-exposed
351
+ patterns:
352
+ - pattern-either:
353
+ - pattern: process.env.$VAR
354
+ - pattern: env.$VAR
355
+ - metavariable-regex:
356
+ metavariable: $VAR
357
+ regex: ^(?!NEXT_PUBLIC_).*(?i)(secret|key|password|private|token|credential).*$
358
+ - pattern-inside: |
359
+ "use client";
360
+ ...
361
+ message: "Server-side environment variable accessed in client component. Only NEXT_PUBLIC_* vars are available in the browser. This will be undefined."
362
+ severity: WARNING
363
+ languages: [typescript, javascript]
364
+ metadata:
365
+ datahogo_id: 134
366
+ datahogo_category: "serverless"
367
+
368
+ - id: datahogo-next-image-unoptimized
369
+ patterns:
370
+ - pattern: <img src={$SRC} ... />
371
+ - pattern-not: <Image src={$SRC} ... />
372
+ - pattern-inside: |
373
+ export default function $COMPONENT(...) {
374
+ ...
375
+ }
376
+ message: "Using native <img> tag instead of Next.js <Image>. This bypasses automatic optimization, lazy loading, and responsive images."
377
+ severity: INFO
378
+ languages: [typescript, javascript, tsx, jsx]
379
+ metadata:
380
+ datahogo_id: 165
381
+ datahogo_category: "best-practices"
382
+
383
+ - id: datahogo-use-client-entire-route
384
+ patterns:
385
+ - pattern: |
386
+ "use client";
387
+ ...
388
+ export default function Page() {
389
+ ...
390
+ }
391
+ - pattern-not: |
392
+ "use client";
393
+ ...
394
+ export default function Page() {
395
+ ...
396
+ useState(...)
397
+ ...
398
+ }
399
+ - pattern-not: |
400
+ "use client";
401
+ ...
402
+ export default function Page() {
403
+ ...
404
+ useEffect(...)
405
+ ...
406
+ }
407
+ - pattern-not: |
408
+ "use client";
409
+ ...
410
+ export default function Page() {
411
+ ...
412
+ onClick=...
413
+ ...
414
+ }
415
+ message: "Entire page marked as 'use client' without obvious client-side features. Consider using Server Components for better performance."
416
+ severity: INFO
417
+ languages: [typescript, javascript, tsx, jsx]
418
+ metadata:
419
+ datahogo_id: 171
420
+ datahogo_category: "best-practices"
421
+
422
+ - id: datahogo-revalidate-with-cache-no-store
423
+ patterns:
424
+ - pattern: |
425
+ fetch($URL, {
426
+ ...
427
+ cache: "no-store",
428
+ ...
429
+ next: { revalidate: $TIME }
430
+ ...
431
+ })
432
+ message: "Using cache: 'no-store' with revalidate is contradictory. Remove cache option or use cache: 'force-cache' with revalidate."
433
+ severity: WARNING
434
+ languages: [typescript, javascript]
435
+ metadata:
436
+ datahogo_id: 171
437
+ datahogo_category: "best-practices"
438
+
439
+ - id: datahogo-server-action-no-revalidate
440
+ patterns:
441
+ - pattern: |
442
+ "use server";
443
+ export async function $ACTION(...) {
444
+ ...
445
+ $DB.insert(...)
446
+ ...
447
+ }
448
+ - pattern-not: |
449
+ "use server";
450
+ export async function $ACTION(...) {
451
+ ...
452
+ revalidatePath(...)
453
+ ...
454
+ }
455
+ - pattern-not: |
456
+ "use server";
457
+ export async function $ACTION(...) {
458
+ ...
459
+ revalidateTag(...)
460
+ ...
461
+ }
462
+ message: "Server Action modifies data without revalidating cache. Call revalidatePath() or revalidateTag() to update stale data."
463
+ severity: WARNING
464
+ languages: [typescript, javascript]
465
+ metadata:
466
+ datahogo_id: 171
467
+ datahogo_category: "best-practices"
468
+
469
+ - id: datahogo-dynamic-force-dynamic-missing
470
+ patterns:
471
+ - pattern: |
472
+ export async function $METHOD(request: Request) {
473
+ ...
474
+ $PARAMS.get(...)
475
+ ...
476
+ }
477
+ - pattern-not: |
478
+ export const dynamic = "force-dynamic"
479
+ ...
480
+ export async function $METHOD(request: Request) {
481
+ ...
482
+ }
483
+ - pattern-not: |
484
+ export const revalidate = 0
485
+ ...
486
+ export async function $METHOD(request: Request) {
487
+ ...
488
+ }
489
+ message: "Route uses dynamic request data (searchParams, cookies, headers) but doesn't set 'export const dynamic = force-dynamic'. May serve stale cached data."
490
+ severity: WARNING
491
+ languages: [typescript, javascript]
492
+ metadata:
493
+ datahogo_id: 171
494
+ datahogo_category: "best-practices"
495
+
496
+ - id: datahogo-console-log-in-production
497
+ patterns:
498
+ - pattern-either:
499
+ - pattern: console.log(...)
500
+ - pattern: console.info(...)
501
+ - pattern: console.warn(...)
502
+ - pattern-inside: |
503
+ export async function $METHOD(...) {
504
+ ...
505
+ }
506
+ message: "console.log in production code can leak sensitive data and impacts performance. Use structured logging (Sentry, Winston) instead."
507
+ severity: WARNING
508
+ languages: [typescript, javascript]
509
+ metadata:
510
+ datahogo_id: 172
511
+ datahogo_category: "best-practices"
512
+
513
+ - id: datahogo-api-route-throws-without-try
514
+ patterns:
515
+ - pattern: |
516
+ export async function $METHOD(...) {
517
+ ...
518
+ }
519
+ - pattern-not: |
520
+ export async function $METHOD(...) {
521
+ try {
522
+ ...
523
+ } catch (...) {
524
+ ...
525
+ }
526
+ }
527
+ message: "API route without try-catch. Unhandled errors will expose stack traces to clients. Wrap in try-catch and return user-friendly errors."
528
+ severity: WARNING
529
+ languages: [typescript, javascript]
530
+ metadata:
531
+ datahogo_id: 173
532
+ datahogo_category: "best-practices"