seaworthycode 1.1.2 → 1.2.3

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 (68) hide show
  1. package/dist/index.js +739 -42
  2. package/dist/index.js.map +1 -1
  3. package/package.json +14 -12
  4. package/rules/external/configuration/insecure-cookie-flags.test.yaml +114 -0
  5. package/rules/external/configuration/insecure-cookie-flags.yaml +77 -0
  6. package/rules/external/configuration/missing-ssl-verification.test.yaml +130 -0
  7. package/rules/external/configuration/missing-ssl-verification.yaml +123 -0
  8. package/rules/external/data-exposure/debug-artifacts.test.yaml +143 -0
  9. package/rules/external/data-exposure/debug-artifacts.yaml +57 -0
  10. package/rules/external/data-exposure/hardcoded-ip.test.yaml +131 -0
  11. package/rules/external/data-exposure/hardcoded-ip.yaml +67 -0
  12. package/rules/external/data-exposure/localstorage-sensitive-data.test.yaml +58 -0
  13. package/rules/external/data-exposure/localstorage-sensitive-data.yaml +60 -0
  14. package/rules/external/dependencies/deprecated-functions.test.yaml +92 -0
  15. package/rules/external/dependencies/deprecated-functions.yaml +66 -0
  16. package/rules/external/ops/hardcoded-port.test.yaml +141 -0
  17. package/rules/external/ops/hardcoded-port.yaml +91 -0
  18. package/rules/external/ops/insecure-file-permissions.test.yaml +111 -0
  19. package/rules/external/ops/insecure-file-permissions.yaml +91 -0
  20. package/rules/external/resilience/missing-memory-limit.test.yaml +54 -0
  21. package/rules/external/resilience/missing-memory-limit.yaml +59 -0
  22. package/rules/external/resilience/missing-timeout-config.test.yaml +179 -0
  23. package/rules/external/resilience/missing-timeout-config.yaml +124 -0
  24. package/rules/external/security/broken-crypto-algorithm.test.yaml +104 -0
  25. package/rules/external/security/broken-crypto-algorithm.yaml +79 -0
  26. package/rules/external/security/http-method-override.test.yaml +40 -0
  27. package/rules/external/security/http-method-override.yaml +35 -0
  28. package/rules/external/security/http-no-tls.test.yaml +115 -0
  29. package/rules/external/security/http-no-tls.yaml +59 -0
  30. package/rules/external/security/path-traversal.test.yaml +188 -0
  31. package/rules/external/security/path-traversal.yaml +210 -0
  32. package/rules/external/security/unsafe-innerhtml.test.yaml +72 -0
  33. package/rules/external/security/unsafe-innerhtml.yaml +46 -0
  34. package/rules/external/security/untrusted-deserialization.test.yaml +79 -0
  35. package/rules/external/security/untrusted-deserialization.yaml +48 -0
  36. package/rules/external/security/weak-encryption-mode.test.yaml +126 -0
  37. package/rules/external/security/weak-encryption-mode.yaml +104 -0
  38. package/rules/external/security/weak-hash-algorithm.test.yaml +121 -0
  39. package/rules/external/security/weak-hash-algorithm.yaml +87 -0
  40. package/rules/external/security/xxe-parsing.test.yaml +76 -0
  41. package/rules/external/security/xxe-parsing.yaml +63 -0
  42. package/rules/internal/security/dangerous-eval.test.yaml +126 -0
  43. package/rules/internal/security/dangerous-eval.yaml +134 -0
  44. package/rules/internal/security/no-document-write.test.yaml +33 -0
  45. package/rules/internal/security/no-document-write.yaml +40 -0
  46. package/rules/internal/taint/MATRIX.md +16 -0
  47. package/rules/internal/taint/bash.test.yaml +84 -0
  48. package/rules/internal/taint/bash.yaml +166 -0
  49. package/rules/internal/taint/dvwa.test.yaml +217 -0
  50. package/rules/internal/taint/go.test.yaml +207 -0
  51. package/rules/internal/taint/go.yaml +325 -0
  52. package/rules/internal/taint/java.test.yaml +158 -0
  53. package/rules/internal/taint/java.yaml +318 -0
  54. package/rules/internal/taint/javascript.test.yaml +374 -0
  55. package/rules/internal/taint/javascript.yaml +439 -0
  56. package/rules/internal/taint/php.test.yaml +134 -0
  57. package/rules/internal/taint/php.yaml +331 -0
  58. package/rules/internal/taint/python.test.yaml +427 -0
  59. package/rules/internal/taint/python.yaml +636 -0
  60. package/rules/internal/taint/ruby.test.yaml +148 -0
  61. package/rules/internal/taint/ruby.yaml +233 -0
  62. package/rules/internal/taint/rust.test.yaml +585 -0
  63. package/rules/internal/taint/rust.yaml +483 -0
  64. package/rules/internal/taint/tsx.test.yaml +140 -0
  65. package/rules/internal/taint/tsx.yaml +51 -0
  66. package/rules/internal/taint/typescript.test.yaml +393 -0
  67. package/rules/internal/taint/typescript.yaml +660 -0
  68. package/wasm/tree-sitter-sql.wasm +0 -0
@@ -0,0 +1,439 @@
1
+ # attribution: CWE-79
2
+ attribution: CWE-79
3
+ language: javascript
4
+ applies-to: []
5
+
6
+ sources:
7
+ - id: req.body
8
+ class: http-body
9
+ query: |
10
+ (member_expression
11
+ object: (identifier) @obj
12
+ property: (property_identifier) @prop
13
+ (#eq? @obj "req")
14
+ (#eq? @prop "body")) @source
15
+
16
+ - id: req.query
17
+ class: http-params
18
+ query: |
19
+ (member_expression
20
+ object: (identifier) @obj
21
+ property: (property_identifier) @prop
22
+ (#eq? @obj "req")
23
+ (#eq? @prop "query")) @source
24
+
25
+ - id: req.params
26
+ class: http-params
27
+ query: |
28
+ (member_expression
29
+ object: (identifier) @obj
30
+ property: (property_identifier) @prop
31
+ (#eq? @obj "req")
32
+ (#eq? @prop "params")) @source
33
+
34
+ - id: req.file.path
35
+ class: http-body
36
+ query: |
37
+ (member_expression
38
+ object: (member_expression
39
+ object: (identifier) @obj
40
+ property: (property_identifier) @fileProp
41
+ (#eq? @obj "req")
42
+ (#eq? @fileProp "file"))
43
+ property: (property_identifier) @prop
44
+ (#match? @prop "^(path|filename|originalname)$")) @source
45
+
46
+ - id: process.argv
47
+ class: process-argv
48
+ query: |
49
+ (member_expression
50
+ object: (identifier) @obj
51
+ property: (property_identifier) @prop
52
+ (#eq? @obj "process")
53
+ (#eq? @prop "argv")) @source
54
+
55
+ - id: process.env
56
+ class: env-var
57
+ query: |
58
+ (member_expression
59
+ object: (identifier) @obj
60
+ property: (property_identifier) @prop
61
+ (#eq? @obj "process")
62
+ (#eq? @prop "env")) @source
63
+
64
+ - id: fs.readFileSync
65
+ class: fs-read
66
+ query: |
67
+ (call_expression
68
+ function: (member_expression
69
+ object: (identifier) @obj
70
+ property: (property_identifier) @prop
71
+ (#eq? @obj "fs")
72
+ (#eq? @prop "readFileSync"))
73
+ arguments: (arguments (_) @source))
74
+
75
+ - id: fs.createReadStream
76
+ class: fs-read
77
+ query: |
78
+ (call_expression
79
+ function: (member_expression
80
+ object: (identifier) @obj
81
+ property: (property_identifier) @prop
82
+ (#eq? @obj "fs")
83
+ (#eq? @prop "createReadStream"))
84
+ arguments: (arguments (_) @source)) @match
85
+
86
+ - id: fetch-response-text
87
+ class: network-response
88
+ query: |
89
+ (call_expression
90
+ function: (member_expression
91
+ property: (property_identifier) @thenProp
92
+ (#eq? @thenProp "then"))
93
+ arguments: (arguments
94
+ (arrow_function body: (identifier) @source))) @match
95
+
96
+ - id: axios-get-response
97
+ class: network-response
98
+ query: |
99
+ (call_expression
100
+ function: (member_expression
101
+ object: (member_expression
102
+ object: (identifier) @obj
103
+ property: (property_identifier) @method
104
+ (#eq? @obj "axios")
105
+ (#eq? @method "get"))
106
+ property: (property_identifier) @thenProp
107
+ (#eq? @thenProp "then"))
108
+ arguments: (arguments (arrow_function . parameters: (formal_parameters (identifier) @resp) . body: (member_expression
109
+ object: (identifier) @resp2
110
+ property: (property_identifier) @bodyProp
111
+ (#eq? @resp2 @resp)
112
+ (#eq? @bodyProp "data")))) @source) @match
113
+
114
+ sinks:
115
+ - id: eval
116
+ sink-class: code-execution
117
+ query: |
118
+ (call_expression
119
+ function: (identifier) @func
120
+ (#eq? @func "eval")
121
+ arguments: (arguments (_) @sink)) @match
122
+
123
+ - id: Function
124
+ sink-class: code-execution
125
+ query: |
126
+ (new_expression
127
+ constructor: (identifier) @func
128
+ (#eq? @func "Function")
129
+ arguments: (arguments (_) @sink)) @match
130
+
131
+ - id: vm.runInNewContext
132
+ sink-class: code-execution
133
+ query: |
134
+ (call_expression
135
+ function: (member_expression
136
+ object: (identifier) @obj
137
+ property: (property_identifier) @prop
138
+ (#eq? @obj "vm")
139
+ (#eq? @prop "runInNewContext"))
140
+ arguments: (arguments (_) @sink)) @match
141
+
142
+ - id: res.send
143
+ sink-class: xss
144
+ query: |
145
+ (call_expression
146
+ function: (member_expression
147
+ object: (identifier) @obj
148
+ property: (property_identifier) @prop
149
+ (#eq? @obj "res")
150
+ (#eq? @prop "send"))
151
+ arguments: (arguments (_) @sink)) @match
152
+
153
+ - id: res.write
154
+ sink-class: xss
155
+ query: |
156
+ (call_expression
157
+ function: (member_expression
158
+ object: (identifier) @obj
159
+ property: (property_identifier) @prop
160
+ (#eq? @obj "res")
161
+ (#eq? @prop "write"))
162
+ arguments: (arguments (_) @sink)) @match
163
+
164
+ - id: res.json
165
+ sink-class: xss
166
+ query: |
167
+ (call_expression
168
+ function: (member_expression
169
+ object: (identifier) @obj
170
+ property: (property_identifier) @prop
171
+ (#eq? @obj "res")
172
+ (#eq? @prop "json"))
173
+ arguments: (arguments (_) @sink)) @match
174
+
175
+ - id: innerHTML
176
+ sink-class: xss
177
+ query: |
178
+ (assignment_expression
179
+ left: (member_expression
180
+ property: (property_identifier) @prop
181
+ (#eq? @prop "innerHTML"))
182
+ right: (_) @sink) @match
183
+
184
+ - id: db.query
185
+ sink-class: sql-injection
186
+ query: |
187
+ (call_expression
188
+ function: (member_expression
189
+ object: (identifier) @obj
190
+ property: (property_identifier) @prop
191
+ (#eq? @obj "db")
192
+ (#eq? @prop "query"))
193
+ arguments: (arguments (_) @sink)) @match
194
+
195
+ - id: connection.execute
196
+ sink-class: sql-injection
197
+ query: |
198
+ (call_expression
199
+ function: (member_expression
200
+ object: (identifier) @obj
201
+ property: (property_identifier) @prop
202
+ (#eq? @obj "connection")
203
+ (#eq? @prop "execute"))
204
+ arguments: (arguments (_) @sink)) @match
205
+
206
+ - id: sequelize.query
207
+ sink-class: sql-injection
208
+ query: |
209
+ (call_expression
210
+ function: (member_expression
211
+ object: (member_expression)
212
+ property: (property_identifier) @prop
213
+ (#eq? @prop "query"))
214
+ arguments: (arguments (_) @sink)) @match
215
+
216
+ - id: Model.find-$where
217
+ sink-class: sql-injection
218
+ query: |
219
+ (call_expression
220
+ function: (member_expression
221
+ property: (property_identifier) @method
222
+ (#eq? @method "find"))
223
+ arguments: (arguments (object (pair
224
+ key: (property_identifier) @key
225
+ (#eq? @key "$where")
226
+ value: (_) @sink)))) @match
227
+
228
+ - id: template-literal-sql
229
+ sink-class: sql-injection
230
+ query: |
231
+ (call_expression
232
+ function: (member_expression
233
+ property: (property_identifier) @method
234
+ (#match? @method "^(query|execute|raw)$"))
235
+ arguments: (arguments (template_string) @sink (#match? @sink "SELECT|INSERT|UPDATE|DELETE|UNION")))
236
+
237
+ - id: child_process.exec
238
+ sink-class: command-injection
239
+ query: |
240
+ (call_expression
241
+ function: (member_expression
242
+ object: (identifier) @obj
243
+ property: (property_identifier) @prop
244
+ (#eq? @obj "child_process")
245
+ (#eq? @prop "exec"))
246
+ arguments: (arguments (_) @sink)) @match
247
+
248
+ - id: child_process.execSync
249
+ sink-class: command-injection
250
+ query: |
251
+ (call_expression
252
+ function: (member_expression
253
+ object: (identifier) @obj
254
+ property: (property_identifier) @prop
255
+ (#eq? @obj "child_process")
256
+ (#eq? @prop "execSync"))
257
+ arguments: (arguments (_) @sink)) @match
258
+
259
+ - id: exec
260
+ sink-class: command-injection
261
+ query: |
262
+ (call_expression
263
+ function: (identifier) @func
264
+ (#eq? @func "exec")
265
+ arguments: (arguments (_) @sink)) @match
266
+
267
+ - id: fs.readFile-path
268
+ sink-class: path-traversal
269
+ query: |
270
+ (call_expression
271
+ function: (member_expression
272
+ object: (identifier) @obj
273
+ property: (property_identifier) @prop
274
+ (#eq? @obj "fs")
275
+ (#eq? @prop "readFile"))
276
+ arguments: (arguments (_) @sink)) @match
277
+
278
+ - id: fs.writeFile-path
279
+ sink-class: path-traversal
280
+ query: |
281
+ (call_expression
282
+ function: (member_expression
283
+ object: (identifier) @obj
284
+ property: (property_identifier) @prop
285
+ (#eq? @obj "fs")
286
+ (#eq? @prop "writeFile"))
287
+ arguments: (arguments (_) @sink)) @match
288
+
289
+ - id: res.sendFile
290
+ sink-class: path-traversal
291
+ query: |
292
+ (call_expression
293
+ function: (member_expression
294
+ object: (identifier) @obj
295
+ property: (property_identifier) @prop
296
+ (#eq? @obj "res")
297
+ (#eq? @prop "sendFile"))
298
+ arguments: (arguments (_) @sink)) @match
299
+
300
+ - id: res.download
301
+ sink-class: path-traversal
302
+ query: |
303
+ (call_expression
304
+ function: (member_expression
305
+ object: (identifier) @obj
306
+ property: (property_identifier) @prop
307
+ (#eq? @obj "res")
308
+ (#eq? @prop "download"))
309
+ arguments: (arguments (_) @sink)) @match
310
+
311
+ - id: express.static
312
+ sink-class: path-traversal
313
+ query: |
314
+ (call_expression
315
+ function: (member_expression
316
+ object: (identifier) @obj
317
+ property: (property_identifier) @prop
318
+ (#eq? @obj "express")
319
+ (#eq? @prop "static"))
320
+ arguments: (arguments (_) @sink)) @match
321
+
322
+ - id: res.redirect
323
+ sink-class: url-injection
324
+ query: |
325
+ (call_expression
326
+ function: (member_expression
327
+ object: (identifier) @obj
328
+ property: (property_identifier) @prop
329
+ (#eq? @obj "res")
330
+ (#eq? @prop "redirect"))
331
+ arguments: (arguments (_) @sink)) @match
332
+
333
+ - id: location.href
334
+ sink-class: url-injection
335
+ query: |
336
+ (assignment_expression
337
+ left: (member_expression
338
+ object: (member_expression
339
+ property: (property_identifier) @locProp
340
+ (#eq? @locProp "location"))
341
+ property: (property_identifier) @hrefProp
342
+ (#eq? @hrefProp "href"))
343
+ right: (_) @sink) @match
344
+
345
+ - id: Object.assign-pollution
346
+ sink-class: prototype-pollution
347
+ query: |
348
+ (call_expression
349
+ function: (member_expression
350
+ object: (identifier) @obj
351
+ property: (property_identifier) @prop
352
+ (#eq? @obj "Object")
353
+ (#eq? @prop "assign"))
354
+ arguments: (arguments (_) @first (_) @sink)) @match
355
+
356
+ - id: merge-deep
357
+ sink-class: prototype-pollution
358
+ query: |
359
+ (call_expression
360
+ function: (identifier) @func
361
+ (#match? @func "^(merge|extend|mergeDeep)$")
362
+ arguments: (arguments (_) @first (_) @sink)) @match
363
+
364
+ sanitisers:
365
+ - id: encodeURIComponent
366
+ sanitises: [xss, url-injection]
367
+ autofix-safety: global
368
+ query: |
369
+ (call_expression
370
+ function: (identifier) @func
371
+ (#eq? @func "encodeURIComponent")) @sanitiser
372
+
373
+ - id: JSON.stringify
374
+ sanitises: [xss]
375
+ autofix-safety: global
376
+ query: |
377
+ (call_expression
378
+ function: (member_expression
379
+ object: (identifier) @obj
380
+ property: (property_identifier) @prop
381
+ (#eq? @obj "JSON")
382
+ (#eq? @prop "stringify"))) @sanitiser
383
+
384
+ - id: DOMPurify.sanitize
385
+ sanitises: [xss]
386
+ autofix-safety: requires-import
387
+ query: |
388
+ (call_expression
389
+ function: (member_expression
390
+ object: (identifier) @obj
391
+ property: (property_identifier) @prop
392
+ (#eq? @obj "DOMPurify")
393
+ (#eq? @prop "sanitize"))) @sanitiser
394
+
395
+ - id: parameterised-query
396
+ sanitises: [sql-injection]
397
+ query: |
398
+ (call_expression
399
+ function: (member_expression
400
+ property: (property_identifier) @prop
401
+ (#match? @prop "^(query|execute|run)$"))
402
+ arguments: (arguments . (_) @first . (template_string) @params)) @sanitiser
403
+
404
+ - id: parameterised-query-placeholder
405
+ sanitises: [sql-injection]
406
+ query: |
407
+ (call_expression
408
+ function: (member_expression
409
+ property: (property_identifier) @prop
410
+ (#match? @prop "^(query|execute|run)$"))
411
+ arguments: (arguments . (_) @first . (array) @params)) @sanitiser
412
+
413
+ - id: escape-shell-arg
414
+ sanitises: [command-injection]
415
+ query: |
416
+ (call_expression
417
+ function: (member_expression
418
+ property: (property_identifier) @prop
419
+ (#match? @prop "^(escapeShellArg|shellEscape|quote)$"))) @sanitiser
420
+
421
+ - id: Object.freeze-pollution
422
+ sanitises: [prototype-pollution]
423
+ query: |
424
+ (call_expression
425
+ function: (member_expression
426
+ object: (identifier) @obj
427
+ property: (property_identifier) @prop
428
+ (#eq? @obj "Object")
429
+ (#eq? @prop "freeze"))) @sanitiser
430
+
431
+ - id: path.resolve
432
+ sanitises: [path-traversal]
433
+ query: |
434
+ (call_expression
435
+ function: (member_expression
436
+ object: (identifier) @obj
437
+ property: (property_identifier) @prop
438
+ (#eq? @obj "path")
439
+ (#eq? @prop "resolve"))) @sanitiser
@@ -0,0 +1,134 @@
1
+ language: php
2
+ cases:
3
+ - name: "SQLi from $_REQUEST to mysqli_query"
4
+ language: php
5
+ code: |
6
+ <?php
7
+ $id = $_REQUEST['id'];
8
+ $query = "SELECT * FROM users WHERE id = '$id';";
9
+ mysqli_query($conn, $query);
10
+ expect:
11
+ count: 1
12
+ flows:
13
+ - sourceId: superglobal.REQUEST
14
+ sinkId: mysqli_query
15
+
16
+ - name: "SQLi sanitised by prepared statement"
17
+ language: php
18
+ code: |
19
+ <?php
20
+ $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
21
+ $stmt->execute([$_GET['id']]);
22
+ expect:
23
+ count: 0
24
+
25
+ - name: "XSS from $_GET via concat to echo"
26
+ language: php
27
+ code: |
28
+ <?php
29
+ $html .= '<pre>' . $_GET['name'] . '</pre>';
30
+ echo $html;
31
+ expect:
32
+ count: 1
33
+ flows:
34
+ - sourceId: superglobal.GET
35
+ sinkId: echo
36
+
37
+ - name: "XSS from $_POST to printf"
38
+ language: php
39
+ code: |
40
+ <?php
41
+ printf('<div>%s</div>', $_POST['msg']);
42
+ expect:
43
+ count: 1
44
+ flows:
45
+ - sourceId: superglobal.POST
46
+ sinkId: printf
47
+
48
+ - name: "XSS from $_GET via short echo"
49
+ language: php
50
+ code: |
51
+ <?= $_GET['label'] ?>
52
+ expect:
53
+ count: 1
54
+ flows:
55
+ - sourceId: superglobal.GET
56
+ sinkId: short-echo
57
+
58
+ - name: "XSS sanitised by htmlspecialchars"
59
+ language: php
60
+ code: |
61
+ <?php
62
+ $x = htmlspecialchars($_GET['x']);
63
+ echo $x;
64
+ expect:
65
+ count: 0
66
+
67
+ - name: "Command injection from $_GET to system"
68
+ language: php
69
+ code: |
70
+ <?php
71
+ system($_GET['cmd']);
72
+ expect:
73
+ count: 1
74
+ flows:
75
+ - sourceId: superglobal.GET
76
+ sinkId: system
77
+
78
+ - name: "Command injection sanitised by escapeshellarg"
79
+ language: php
80
+ code: |
81
+ <?php
82
+ system(escapeshellarg($_GET['cmd']));
83
+ expect:
84
+ count: 0
85
+
86
+ - name: "Path traversal via include"
87
+ language: php
88
+ code: |
89
+ <?php
90
+ include($_GET['page']);
91
+ expect:
92
+ count: 1
93
+ flows:
94
+ - sourceId: superglobal.GET
95
+ sinkId: include
96
+
97
+ - name: "Path traversal sanitised by basename"
98
+ language: php
99
+ code: |
100
+ <?php
101
+ include(basename($_GET['page']));
102
+ expect:
103
+ count: 0
104
+
105
+ - name: "Open redirect via header"
106
+ language: php
107
+ code: |
108
+ <?php
109
+ header('location: ' . $_GET['redirect']);
110
+ expect:
111
+ count: 1
112
+ flows:
113
+ - sourceId: superglobal.GET
114
+ sinkId: header
115
+
116
+ - name: "No source match — zero flows"
117
+ language: php
118
+ code: |
119
+ <?php
120
+ echo "hello world";
121
+ expect:
122
+ count: 0
123
+
124
+ - name: "encodeURIComponent equivalent does not cover sql-injection"
125
+ language: php
126
+ code: |
127
+ <?php
128
+ $q = htmlspecialchars($_GET['id']);
129
+ mysqli_query($conn, $q);
130
+ expect:
131
+ count: 1
132
+ flows:
133
+ - sourceId: superglobal.GET
134
+ sinkId: mysqli_query