@reliabilityworks/ruleset-sveltekit 0.3.0 → 0.5.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/package.json +1 -1
- package/rules.json +746 -0
package/package.json
CHANGED
package/rules.json
CHANGED
|
@@ -22,5 +22,751 @@
|
|
|
22
22
|
"pattern": "\\bhost\\s*:\\s*['\"]0\\.0\\.0\\.0['\"]",
|
|
23
23
|
"message": "Vite server host appears to be set to 0.0.0.0."
|
|
24
24
|
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "sveltekit/open-redirect-searchparams",
|
|
28
|
+
"severity": "high",
|
|
29
|
+
"title": "Open redirect via searchParams",
|
|
30
|
+
"description": "Redirecting to user-controlled URLs can enable phishing and token leakage.",
|
|
31
|
+
"matcher": {
|
|
32
|
+
"type": "regex",
|
|
33
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
34
|
+
"pattern": "redirect\\s*\\([^\\)]*(url\\.)?searchParams\\.get\\(\\s*['\"]next['\"]",
|
|
35
|
+
"message": "Redirect appears to use a user-controlled next parameter."
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "sveltekit/open-redirect-throw",
|
|
40
|
+
"severity": "high",
|
|
41
|
+
"title": "throw redirect with user input",
|
|
42
|
+
"description": "Throwing redirects to user-controlled destinations can enable open redirects.",
|
|
43
|
+
"matcher": {
|
|
44
|
+
"type": "regex",
|
|
45
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
46
|
+
"pattern": "throw\\s+redirect\\s*\\([^\\)]*searchParams\\.get",
|
|
47
|
+
"message": "throw redirect appears to use searchParams.get."
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "sveltekit/redirect-301",
|
|
52
|
+
"severity": "low",
|
|
53
|
+
"title": "Redirect uses 301",
|
|
54
|
+
"description": "Permanent redirects can cache unsafe destinations; ensure redirect targets are safe.",
|
|
55
|
+
"matcher": {
|
|
56
|
+
"type": "regex",
|
|
57
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
58
|
+
"pattern": "redirect\\s*\\(\\s*301\\s*,",
|
|
59
|
+
"message": "Redirect uses status 301."
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "sveltekit/redirect-302",
|
|
64
|
+
"severity": "low",
|
|
65
|
+
"title": "Redirect uses 302",
|
|
66
|
+
"description": "Temporary redirects can still be abused if the destination is user-controlled.",
|
|
67
|
+
"matcher": {
|
|
68
|
+
"type": "regex",
|
|
69
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
70
|
+
"pattern": "redirect\\s*\\(\\s*302\\s*,",
|
|
71
|
+
"message": "Redirect uses status 302."
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "sveltekit/cookies-secure-false",
|
|
76
|
+
"severity": "high",
|
|
77
|
+
"title": "Cookie set with secure: false",
|
|
78
|
+
"description": "Cookies without secure may be sent over HTTP and can be intercepted.",
|
|
79
|
+
"matcher": {
|
|
80
|
+
"type": "regex",
|
|
81
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
82
|
+
"pattern": "cookies\\.set\\([^\\)]*\\{[^}]*\\bsecure\\s*:\\s*false",
|
|
83
|
+
"flags": "s",
|
|
84
|
+
"message": "cookies.set appears to set secure: false."
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"id": "sveltekit/cookies-httponly-false",
|
|
89
|
+
"severity": "high",
|
|
90
|
+
"title": "Cookie set with httpOnly: false",
|
|
91
|
+
"description": "Cookies without httpOnly can be accessed by JavaScript and stolen via XSS.",
|
|
92
|
+
"matcher": {
|
|
93
|
+
"type": "regex",
|
|
94
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
95
|
+
"pattern": "cookies\\.set\\([^\\)]*\\{[^}]*\\bhttpOnly\\s*:\\s*false",
|
|
96
|
+
"flags": "s",
|
|
97
|
+
"message": "cookies.set appears to set httpOnly: false."
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "sveltekit/cookies-samesite-none",
|
|
102
|
+
"severity": "medium",
|
|
103
|
+
"title": "Cookie SameSite set to none",
|
|
104
|
+
"description": "SameSite=none can enable cross-site cookie sending; ensure CSRF protections and secure cookies.",
|
|
105
|
+
"matcher": {
|
|
106
|
+
"type": "regex",
|
|
107
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
108
|
+
"pattern": "sameSite\\s*:\\s*['\"]none['\"]",
|
|
109
|
+
"message": "sameSite appears to be set to 'none'."
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "sveltekit/cookies-domain-dot",
|
|
114
|
+
"severity": "medium",
|
|
115
|
+
"title": "Cookie domain set to dot-prefixed domain",
|
|
116
|
+
"description": "Setting cookie domain broadly can increase exposure across subdomains.",
|
|
117
|
+
"matcher": {
|
|
118
|
+
"type": "regex",
|
|
119
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
120
|
+
"pattern": "domain\\s*:\\s*['\"]\\.[^'\"]+['\"]",
|
|
121
|
+
"message": "Cookie domain appears to be set for all subdomains."
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "sveltekit/cookies-path-root",
|
|
126
|
+
"severity": "low",
|
|
127
|
+
"title": "Cookie path set to '/'",
|
|
128
|
+
"description": "Cookies scoped to '/' are sent to all paths; consider narrowing scope when possible.",
|
|
129
|
+
"matcher": {
|
|
130
|
+
"type": "regex",
|
|
131
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
132
|
+
"pattern": "\\bpath\\s*:\\s*['\"]/['\"]",
|
|
133
|
+
"message": "Cookie path appears to be set to '/'."
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "sveltekit/cookies-set-without-options",
|
|
138
|
+
"severity": "medium",
|
|
139
|
+
"title": "cookies.set without options",
|
|
140
|
+
"description": "Setting cookies without explicit security options can lead to insecure defaults.",
|
|
141
|
+
"matcher": {
|
|
142
|
+
"type": "regex",
|
|
143
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
144
|
+
"pattern": "cookies\\.set\\s*\\(\\s*['\"][^'\"]+['\"]\\s*,\\s*[^,\\)]+\\s*\\)",
|
|
145
|
+
"message": "cookies.set called without an options object."
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"id": "sveltekit/csp-unsafe-inline",
|
|
150
|
+
"severity": "high",
|
|
151
|
+
"title": "CSP allows unsafe-inline",
|
|
152
|
+
"description": "CSP with unsafe-inline weakens script protections and increases XSS risk.",
|
|
153
|
+
"matcher": {
|
|
154
|
+
"type": "regex",
|
|
155
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
156
|
+
"pattern": "Content-Security-Policy[^\\n\\r]*unsafe-inline",
|
|
157
|
+
"message": "Content-Security-Policy includes unsafe-inline."
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"id": "sveltekit/csp-unsafe-eval",
|
|
162
|
+
"severity": "high",
|
|
163
|
+
"title": "CSP allows unsafe-eval",
|
|
164
|
+
"description": "CSP with unsafe-eval weakens script protections and increases XSS risk.",
|
|
165
|
+
"matcher": {
|
|
166
|
+
"type": "regex",
|
|
167
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
168
|
+
"pattern": "Content-Security-Policy[^\\n\\r]*unsafe-eval",
|
|
169
|
+
"message": "Content-Security-Policy includes unsafe-eval."
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "sveltekit/header-x-powered-by",
|
|
174
|
+
"severity": "low",
|
|
175
|
+
"title": "X-Powered-By header referenced",
|
|
176
|
+
"description": "X-Powered-By can reveal implementation details.",
|
|
177
|
+
"matcher": {
|
|
178
|
+
"type": "regex",
|
|
179
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
180
|
+
"pattern": "X-Powered-By",
|
|
181
|
+
"message": "X-Powered-By header referenced."
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"id": "sveltekit/http-url",
|
|
186
|
+
"severity": "medium",
|
|
187
|
+
"title": "Plain HTTP URL",
|
|
188
|
+
"description": "Using HTTP can expose data to interception.",
|
|
189
|
+
"matcher": {
|
|
190
|
+
"type": "regex",
|
|
191
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
192
|
+
"pattern": "['\"]http://",
|
|
193
|
+
"message": "Plain http:// URL detected."
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"id": "sveltekit/tls-reject-unauthorized-zero",
|
|
198
|
+
"severity": "high",
|
|
199
|
+
"title": "TLS verification disabled",
|
|
200
|
+
"description": "Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables TLS verification and enables MITM attacks.",
|
|
201
|
+
"matcher": {
|
|
202
|
+
"type": "regex",
|
|
203
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
204
|
+
"pattern": "NODE_TLS_REJECT_UNAUTHORIZED[^=]{0,20}=\\s*['\"]0['\"]",
|
|
205
|
+
"message": "NODE_TLS_REJECT_UNAUTHORIZED is set to 0."
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"id": "sveltekit/reject-unauthorized-false",
|
|
210
|
+
"severity": "high",
|
|
211
|
+
"title": "rejectUnauthorized set to false",
|
|
212
|
+
"description": "Setting rejectUnauthorized: false disables TLS certificate verification.",
|
|
213
|
+
"matcher": {
|
|
214
|
+
"type": "regex",
|
|
215
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
216
|
+
"pattern": "rejectUnauthorized\\s*:\\s*false",
|
|
217
|
+
"message": "rejectUnauthorized appears to be false."
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"id": "sveltekit/ssrf-localhost",
|
|
222
|
+
"severity": "high",
|
|
223
|
+
"title": "Potential SSRF to localhost",
|
|
224
|
+
"description": "Requesting localhost can enable SSRF attacks.",
|
|
225
|
+
"matcher": {
|
|
226
|
+
"type": "regex",
|
|
227
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
228
|
+
"pattern": "http://(localhost|127\\.0\\.0\\.1)",
|
|
229
|
+
"message": "Potential SSRF target (localhost) detected."
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"id": "sveltekit/ssrf-metadata",
|
|
234
|
+
"severity": "high",
|
|
235
|
+
"title": "Potential SSRF to cloud metadata",
|
|
236
|
+
"description": "Requesting 169.254.169.254 can expose cloud instance metadata.",
|
|
237
|
+
"matcher": {
|
|
238
|
+
"type": "regex",
|
|
239
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
240
|
+
"pattern": "169\\.254\\.169\\.254",
|
|
241
|
+
"message": "Potential SSRF target (metadata IP) detected."
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "sveltekit/fetch-user-url-param",
|
|
246
|
+
"severity": "high",
|
|
247
|
+
"title": "fetch to URL from user input",
|
|
248
|
+
"description": "Fetching user-controlled URLs can enable SSRF.",
|
|
249
|
+
"matcher": {
|
|
250
|
+
"type": "regex",
|
|
251
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
252
|
+
"pattern": "fetch\\s*\\(\\s*url\\.searchParams\\.get\\(\\s*['\"]url['\"]",
|
|
253
|
+
"message": "fetch appears to use url.searchParams.get('url')."
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"id": "sveltekit/path-join-user-input",
|
|
258
|
+
"severity": "high",
|
|
259
|
+
"title": "path.join with user input",
|
|
260
|
+
"description": "Joining paths with user-controlled input can enable path traversal.",
|
|
261
|
+
"matcher": {
|
|
262
|
+
"type": "regex",
|
|
263
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
264
|
+
"pattern": "path\\.join\\s*\\([^\\)]*(searchParams\\.get|req\\.|userInput)",
|
|
265
|
+
"message": "path.join appears to use dynamic input."
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"id": "sveltekit/fs-readfile-user-input",
|
|
270
|
+
"severity": "high",
|
|
271
|
+
"title": "fs.readFile with user input",
|
|
272
|
+
"description": "Reading files using user-controlled paths can enable file disclosure.",
|
|
273
|
+
"matcher": {
|
|
274
|
+
"type": "regex",
|
|
275
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
276
|
+
"pattern": "readFile(Sync)?\\s*\\([^\\)]*(searchParams\\.get|req\\.|userInput)",
|
|
277
|
+
"message": "readFile appears to use dynamic input."
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"id": "sveltekit/fs-writefile-user-input",
|
|
282
|
+
"severity": "high",
|
|
283
|
+
"title": "fs.writeFile with user input",
|
|
284
|
+
"description": "Writing files using user-controlled paths can enable overwrites.",
|
|
285
|
+
"matcher": {
|
|
286
|
+
"type": "regex",
|
|
287
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
288
|
+
"pattern": "writeFile(Sync)?\\s*\\([^\\)]*(searchParams\\.get|req\\.|userInput)",
|
|
289
|
+
"message": "writeFile appears to use dynamic input."
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"id": "sveltekit/eval",
|
|
294
|
+
"severity": "high",
|
|
295
|
+
"title": "eval usage",
|
|
296
|
+
"description": "eval can enable code injection vulnerabilities and is strongly discouraged.",
|
|
297
|
+
"matcher": {
|
|
298
|
+
"type": "regex",
|
|
299
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
300
|
+
"pattern": "\\beval\\s*\\(",
|
|
301
|
+
"message": "eval detected; avoid dynamic code execution."
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"id": "sveltekit/new-function",
|
|
306
|
+
"severity": "high",
|
|
307
|
+
"title": "Function constructor usage",
|
|
308
|
+
"description": "new Function can enable code injection vulnerabilities and is strongly discouraged.",
|
|
309
|
+
"matcher": {
|
|
310
|
+
"type": "regex",
|
|
311
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
312
|
+
"pattern": "\\bnew\\s+Function\\s*\\(",
|
|
313
|
+
"message": "new Function detected; avoid dynamic code execution."
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"id": "sveltekit/child-process-exec",
|
|
318
|
+
"severity": "high",
|
|
319
|
+
"title": "child_process exec usage",
|
|
320
|
+
"description": "Executing shell commands can lead to command injection vulnerabilities.",
|
|
321
|
+
"matcher": {
|
|
322
|
+
"type": "regex",
|
|
323
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
324
|
+
"pattern": "\\bexec\\s*\\(",
|
|
325
|
+
"message": "exec detected; ensure inputs are not user-controlled."
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"id": "sveltekit/child-process-execsync",
|
|
330
|
+
"severity": "high",
|
|
331
|
+
"title": "child_process execSync usage",
|
|
332
|
+
"description": "Executing shell commands can lead to command injection vulnerabilities.",
|
|
333
|
+
"matcher": {
|
|
334
|
+
"type": "regex",
|
|
335
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
336
|
+
"pattern": "\\bexecSync\\s*\\(",
|
|
337
|
+
"message": "execSync detected; ensure inputs are not user-controlled."
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"id": "sveltekit/child-process-spawn",
|
|
342
|
+
"severity": "high",
|
|
343
|
+
"title": "child_process spawn usage",
|
|
344
|
+
"description": "Spawning subprocesses can lead to command injection vulnerabilities.",
|
|
345
|
+
"matcher": {
|
|
346
|
+
"type": "regex",
|
|
347
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
348
|
+
"pattern": "\\bspawn\\s*\\(",
|
|
349
|
+
"message": "spawn detected; ensure inputs are not user-controlled."
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"id": "sveltekit/child-process-spawnsync",
|
|
354
|
+
"severity": "high",
|
|
355
|
+
"title": "child_process spawnSync usage",
|
|
356
|
+
"description": "Spawning subprocesses can lead to command injection vulnerabilities.",
|
|
357
|
+
"matcher": {
|
|
358
|
+
"type": "regex",
|
|
359
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
360
|
+
"pattern": "\\bspawnSync\\s*\\(",
|
|
361
|
+
"message": "spawnSync detected; ensure inputs are not user-controlled."
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"id": "sveltekit/child-process-fork",
|
|
366
|
+
"severity": "medium",
|
|
367
|
+
"title": "child_process fork usage",
|
|
368
|
+
"description": "Forking subprocesses can increase attack surface; ensure the child module path is safe.",
|
|
369
|
+
"matcher": {
|
|
370
|
+
"type": "regex",
|
|
371
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
372
|
+
"pattern": "\\bfork\\s*\\(",
|
|
373
|
+
"message": "fork detected; ensure the child module path is safe."
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"id": "sveltekit/crypto-md5",
|
|
378
|
+
"severity": "medium",
|
|
379
|
+
"title": "MD5 hashing",
|
|
380
|
+
"description": "MD5 is considered cryptographically broken and unsuitable for security-sensitive use.",
|
|
381
|
+
"matcher": {
|
|
382
|
+
"type": "regex",
|
|
383
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
384
|
+
"pattern": "createHash\\s*\\(\\s*['\"]md5['\"]",
|
|
385
|
+
"message": "MD5 hashing detected; avoid for security-sensitive use."
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"id": "sveltekit/crypto-sha1",
|
|
390
|
+
"severity": "low",
|
|
391
|
+
"title": "SHA-1 hashing",
|
|
392
|
+
"description": "SHA-1 is considered weak for collision resistance and should be avoided for new security-sensitive uses.",
|
|
393
|
+
"matcher": {
|
|
394
|
+
"type": "regex",
|
|
395
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
396
|
+
"pattern": "createHash\\s*\\(\\s*['\"]sha1['\"]",
|
|
397
|
+
"message": "SHA-1 hashing detected; avoid for security-sensitive use."
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
"id": "sveltekit/math-random",
|
|
402
|
+
"severity": "medium",
|
|
403
|
+
"title": "Math.random usage",
|
|
404
|
+
"description": "Math.random is not cryptographically secure and should not be used for secrets or tokens.",
|
|
405
|
+
"matcher": {
|
|
406
|
+
"type": "regex",
|
|
407
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
408
|
+
"pattern": "Math\\.random\\s*\\(",
|
|
409
|
+
"message": "Math.random detected; avoid for security-sensitive use."
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"id": "sveltekit/cookie-parser-secret-hardcoded",
|
|
414
|
+
"severity": "high",
|
|
415
|
+
"title": "Hardcoded cookie-parser secret",
|
|
416
|
+
"description": "Hardcoding secrets in source code increases risk of compromise.",
|
|
417
|
+
"matcher": {
|
|
418
|
+
"type": "regex",
|
|
419
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
420
|
+
"pattern": "cookieParser\\s*\\(\\s*['\"][^'\"]{8,}['\"]",
|
|
421
|
+
"message": "cookieParser appears to use a hardcoded secret."
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
"id": "sveltekit/jwt-secret-hardcoded",
|
|
426
|
+
"severity": "high",
|
|
427
|
+
"title": "Hardcoded JWT secret",
|
|
428
|
+
"description": "Hardcoding JWT secrets increases risk of token forgery.",
|
|
429
|
+
"matcher": {
|
|
430
|
+
"type": "regex",
|
|
431
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
432
|
+
"pattern": "jwt\\.(sign|verify)\\s*\\([^\\)]*,\\s*['\"][^'\"]{8,}['\"]",
|
|
433
|
+
"message": "JWT signing/verifying appears to use a hardcoded secret."
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"id": "sveltekit/jwt-alg-none",
|
|
438
|
+
"severity": "high",
|
|
439
|
+
"title": "JWT algorithm set to none",
|
|
440
|
+
"description": "alg=none disables signature verification.",
|
|
441
|
+
"matcher": {
|
|
442
|
+
"type": "regex",
|
|
443
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
444
|
+
"pattern": "\\balgorithms?\\s*:\\s*\\[[^\\]]*['\"]none['\"]",
|
|
445
|
+
"message": "JWT algorithms appears to include 'none'."
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"id": "sveltekit/insecure-session-secret",
|
|
450
|
+
"severity": "high",
|
|
451
|
+
"title": "Hardcoded session secret",
|
|
452
|
+
"description": "Hardcoded session secrets increase risk of session forgery.",
|
|
453
|
+
"matcher": {
|
|
454
|
+
"type": "regex",
|
|
455
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
456
|
+
"pattern": "SESSION_SECRET\\s*=\\s*['\"][^'\"]{8,}['\"]",
|
|
457
|
+
"message": "Hardcoded session secret detected."
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"id": "sveltekit/bcrypt-low-rounds",
|
|
462
|
+
"severity": "medium",
|
|
463
|
+
"title": "bcrypt salt rounds too low",
|
|
464
|
+
"description": "Low bcrypt rounds reduce password hashing strength.",
|
|
465
|
+
"matcher": {
|
|
466
|
+
"type": "regex",
|
|
467
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
468
|
+
"pattern": "bcrypt\\.(hash|hashSync)\\s*\\([^\\)]*,\\s*([0-9]|1[0-1])\\b",
|
|
469
|
+
"message": "bcrypt rounds appear low."
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"id": "sveltekit/password-compare-timing",
|
|
474
|
+
"severity": "medium",
|
|
475
|
+
"title": "Insecure string comparison for secrets",
|
|
476
|
+
"description": "Using === to compare secrets can introduce timing attacks in some contexts.",
|
|
477
|
+
"matcher": {
|
|
478
|
+
"type": "regex",
|
|
479
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
480
|
+
"pattern": "\\b(password|secret|token)\\b[^\\n\\r]{0,40}===",
|
|
481
|
+
"message": "Potential secret comparison using ===."
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
"id": "sveltekit/sql-string-concat",
|
|
486
|
+
"severity": "high",
|
|
487
|
+
"title": "Potential SQL string concatenation",
|
|
488
|
+
"description": "Building SQL queries via string concatenation can lead to injection vulnerabilities.",
|
|
489
|
+
"matcher": {
|
|
490
|
+
"type": "regex",
|
|
491
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
492
|
+
"pattern": "SELECT\\s+[^;]*\\+\\s*(req\\.|userInput)",
|
|
493
|
+
"message": "SQL string concatenation detected."
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"id": "sveltekit/sql-template-interpolation",
|
|
498
|
+
"severity": "high",
|
|
499
|
+
"title": "SQL template literal interpolation",
|
|
500
|
+
"description": "Using user-controlled input in SQL template literals can enable injection vulnerabilities.",
|
|
501
|
+
"matcher": {
|
|
502
|
+
"type": "regex",
|
|
503
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
504
|
+
"pattern": "SELECT[^`]*\\$\\{\\s*(req\\.|userInput)",
|
|
505
|
+
"message": "SQL template interpolation detected."
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"id": "sveltekit/mongodb-where",
|
|
510
|
+
"severity": "high",
|
|
511
|
+
"title": "MongoDB $where usage",
|
|
512
|
+
"description": "$where executes JavaScript on the server and can enable injection.",
|
|
513
|
+
"matcher": {
|
|
514
|
+
"type": "regex",
|
|
515
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
516
|
+
"pattern": "\\$where\\b",
|
|
517
|
+
"message": "$where usage detected."
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
"id": "sveltekit/regex-from-user-input",
|
|
522
|
+
"severity": "medium",
|
|
523
|
+
"title": "RegExp constructed from dynamic input",
|
|
524
|
+
"description": "Constructing regular expressions from untrusted input can lead to ReDoS.",
|
|
525
|
+
"matcher": {
|
|
526
|
+
"type": "regex",
|
|
527
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
528
|
+
"pattern": "new\\s+RegExp\\s*\\([^\\)]*(url\\.searchParams\\.get|searchParams\\.get|req\\.query|userInput)",
|
|
529
|
+
"message": "new RegExp appears to use dynamic input."
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"id": "sveltekit/xss-raw-html",
|
|
534
|
+
"severity": "high",
|
|
535
|
+
"title": "Raw HTML rendering",
|
|
536
|
+
"description": "Rendering raw HTML can introduce XSS if the content is untrusted.",
|
|
537
|
+
"matcher": {
|
|
538
|
+
"type": "regex",
|
|
539
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
540
|
+
"pattern": "\\{@html",
|
|
541
|
+
"message": "Svelte raw HTML directive ({@html}) detected."
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
"id": "sveltekit/response-html-content-type",
|
|
546
|
+
"severity": "medium",
|
|
547
|
+
"title": "HTML response content type",
|
|
548
|
+
"description": "Serving HTML from server code requires careful escaping of user-controlled data.",
|
|
549
|
+
"matcher": {
|
|
550
|
+
"type": "regex",
|
|
551
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
552
|
+
"pattern": "text/html",
|
|
553
|
+
"message": "text/html referenced; ensure untrusted content is escaped."
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"id": "sveltekit/template-interpolation-user-input",
|
|
558
|
+
"severity": "high",
|
|
559
|
+
"title": "User input interpolated into template string",
|
|
560
|
+
"description": "Interpolating user-controlled input into strings can cause XSS or injection depending on usage.",
|
|
561
|
+
"matcher": {
|
|
562
|
+
"type": "regex",
|
|
563
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
564
|
+
"pattern": "\\$\\{\\s*url\\.searchParams\\.get\\(",
|
|
565
|
+
"message": "Template string interpolation of url.searchParams.get detected."
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
"id": "sveltekit/cors-allow-origin-star",
|
|
570
|
+
"severity": "medium",
|
|
571
|
+
"title": "CORS allows any origin",
|
|
572
|
+
"description": "Access-Control-Allow-Origin: * can be dangerous for authenticated endpoints.",
|
|
573
|
+
"matcher": {
|
|
574
|
+
"type": "regex",
|
|
575
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
576
|
+
"pattern": "Access-Control-Allow-Origin[^\\n\\r]*\\*",
|
|
577
|
+
"message": "Access-Control-Allow-Origin appears to allow '*'."
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
"id": "sveltekit/cors-allow-headers-star",
|
|
582
|
+
"severity": "medium",
|
|
583
|
+
"title": "CORS allows any request headers",
|
|
584
|
+
"description": "Allowing any headers in CORS responses can broaden attack surface.",
|
|
585
|
+
"matcher": {
|
|
586
|
+
"type": "regex",
|
|
587
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
588
|
+
"pattern": "Access-Control-Allow-Headers[^\\n\\r]*\\*",
|
|
589
|
+
"message": "Access-Control-Allow-Headers appears to be '*'."
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
"id": "sveltekit/cors-allow-methods-star",
|
|
594
|
+
"severity": "medium",
|
|
595
|
+
"title": "CORS allows any methods",
|
|
596
|
+
"description": "Allowing any methods in CORS responses can broaden attack surface.",
|
|
597
|
+
"matcher": {
|
|
598
|
+
"type": "regex",
|
|
599
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
600
|
+
"pattern": "Access-Control-Allow-Methods[^\\n\\r]*\\*",
|
|
601
|
+
"message": "Access-Control-Allow-Methods appears to be '*'."
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"id": "sveltekit/cors-credentials-true",
|
|
606
|
+
"severity": "high",
|
|
607
|
+
"title": "CORS credentials enabled",
|
|
608
|
+
"description": "credentials: true can be risky when combined with permissive origins.",
|
|
609
|
+
"matcher": {
|
|
610
|
+
"type": "regex",
|
|
611
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
612
|
+
"pattern": "\\bcredentials\\s*:\\s*true",
|
|
613
|
+
"message": "CORS credentials appears enabled."
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"id": "sveltekit/debug-enabled",
|
|
618
|
+
"severity": "medium",
|
|
619
|
+
"title": "Debug enabled",
|
|
620
|
+
"description": "Debug mode can leak sensitive information.",
|
|
621
|
+
"matcher": {
|
|
622
|
+
"type": "regex",
|
|
623
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
624
|
+
"pattern": "\\bdebug\\s*:\\s*true",
|
|
625
|
+
"message": "debug appears to be enabled."
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
"id": "sveltekit/console-log-env",
|
|
630
|
+
"severity": "medium",
|
|
631
|
+
"title": "Logging environment variables",
|
|
632
|
+
"description": "Logging process.env can leak secrets into logs.",
|
|
633
|
+
"matcher": {
|
|
634
|
+
"type": "regex",
|
|
635
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
636
|
+
"pattern": "console\\.log\\([^\\)]*process\\.env",
|
|
637
|
+
"message": "process.env appears to be logged."
|
|
638
|
+
}
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"id": "sveltekit/log-authorization-header",
|
|
642
|
+
"severity": "high",
|
|
643
|
+
"title": "Authorization header logged",
|
|
644
|
+
"description": "Logging Authorization headers can leak tokens.",
|
|
645
|
+
"matcher": {
|
|
646
|
+
"type": "regex",
|
|
647
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
648
|
+
"pattern": "authorization\\b[^\\n\\r]{0,80}console\\.log",
|
|
649
|
+
"message": "Authorization appears to be logged."
|
|
650
|
+
}
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
"id": "sveltekit/log-request-body",
|
|
654
|
+
"severity": "high",
|
|
655
|
+
"title": "Request body logged",
|
|
656
|
+
"description": "Logging request bodies can leak secrets and PII.",
|
|
657
|
+
"matcher": {
|
|
658
|
+
"type": "regex",
|
|
659
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
660
|
+
"pattern": "console\\.log\\([^\\)]*(await\\s+)?request\\.(json|text|formData)\\(",
|
|
661
|
+
"message": "Request body appears to be logged."
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"id": "sveltekit/request-headers-logged",
|
|
666
|
+
"severity": "medium",
|
|
667
|
+
"title": "Request headers logged",
|
|
668
|
+
"description": "Logging headers can leak credentials and PII.",
|
|
669
|
+
"matcher": {
|
|
670
|
+
"type": "regex",
|
|
671
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
672
|
+
"pattern": "console\\.log\\([^\\)]*request\\.headers",
|
|
673
|
+
"message": "request.headers appears to be logged."
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
"id": "sveltekit/json-parse-request-body",
|
|
678
|
+
"severity": "medium",
|
|
679
|
+
"title": "JSON.parse on request body",
|
|
680
|
+
"description": "Blindly parsing request bodies can be risky; ensure schema validation and size limits.",
|
|
681
|
+
"matcher": {
|
|
682
|
+
"type": "regex",
|
|
683
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
684
|
+
"pattern": "JSON\\.parse\\s*\\([^\\)]*request\\.text\\(\\)",
|
|
685
|
+
"message": "JSON.parse(request.text()) detected; ensure validation and limits."
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
"id": "sveltekit/xml-parser",
|
|
690
|
+
"severity": "medium",
|
|
691
|
+
"title": "XML parsing",
|
|
692
|
+
"description": "Parsing XML can be risky without secure parser configuration.",
|
|
693
|
+
"matcher": {
|
|
694
|
+
"type": "regex",
|
|
695
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
696
|
+
"pattern": "xml2js|fast-xml-parser|libxml",
|
|
697
|
+
"message": "XML parser referenced."
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"id": "sveltekit/graphql-playground-enabled",
|
|
702
|
+
"severity": "medium",
|
|
703
|
+
"title": "GraphQL playground enabled",
|
|
704
|
+
"description": "Exposing GraphQL playground in production can leak schema information.",
|
|
705
|
+
"matcher": {
|
|
706
|
+
"type": "regex",
|
|
707
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
708
|
+
"pattern": "graphql-playground|ApolloServer\\([^\\)]*introspection\\s*:\\s*true",
|
|
709
|
+
"message": "GraphQL playground or introspection appears enabled."
|
|
710
|
+
}
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"id": "sveltekit/rate-limit-usage",
|
|
714
|
+
"severity": "low",
|
|
715
|
+
"title": "Rate limiting referenced",
|
|
716
|
+
"description": "Ensure rate limiting is applied to sensitive routes.",
|
|
717
|
+
"matcher": {
|
|
718
|
+
"type": "regex",
|
|
719
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
720
|
+
"pattern": "rateLimit\\s*\\(",
|
|
721
|
+
"message": "rateLimit usage detected."
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
"id": "sveltekit/csrf-disabled",
|
|
726
|
+
"severity": "high",
|
|
727
|
+
"title": "CSRF protection disabled",
|
|
728
|
+
"description": "Disabling CSRF protections can enable cross-site request forgery.",
|
|
729
|
+
"matcher": {
|
|
730
|
+
"type": "regex",
|
|
731
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
732
|
+
"pattern": "csrf\\s*:\\s*false",
|
|
733
|
+
"message": "CSRF appears disabled."
|
|
734
|
+
}
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
"id": "sveltekit/file-upload-any",
|
|
738
|
+
"severity": "medium",
|
|
739
|
+
"title": "File upload any() usage",
|
|
740
|
+
"description": "Accepting any files without validation can enable abuse.",
|
|
741
|
+
"matcher": {
|
|
742
|
+
"type": "regex",
|
|
743
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
744
|
+
"pattern": "upload\\.any\\s*\\(",
|
|
745
|
+
"message": "upload.any() usage detected."
|
|
746
|
+
}
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
"id": "sveltekit/file-upload-temp-dir",
|
|
750
|
+
"severity": "low",
|
|
751
|
+
"title": "File uploads stored in /tmp",
|
|
752
|
+
"description": "Storing uploads in /tmp can be risky depending on host constraints; ensure cleanup and permissions.",
|
|
753
|
+
"matcher": {
|
|
754
|
+
"type": "regex",
|
|
755
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
756
|
+
"pattern": "['\"]/tmp/",
|
|
757
|
+
"message": "Reference to /tmp detected."
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
"id": "sveltekit/location-header-user-input",
|
|
762
|
+
"severity": "high",
|
|
763
|
+
"title": "Location header from user input",
|
|
764
|
+
"description": "Setting Location header from user input can enable redirects and header injection.",
|
|
765
|
+
"matcher": {
|
|
766
|
+
"type": "regex",
|
|
767
|
+
"fileGlobs": ["**/*.{js,ts}"],
|
|
768
|
+
"pattern": "Location['\"]?\\s*:\\s*url\\.searchParams\\.get",
|
|
769
|
+
"message": "Location header appears to be set from url.searchParams.get."
|
|
770
|
+
}
|
|
25
771
|
}
|
|
26
772
|
]
|