seaworthycode 1.1.1 → 1.1.4

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 +269 -59
  2. package/dist/index.js.map +1 -1
  3. package/package.json +16 -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,483 @@
1
+ # Documented exclusion: Prototype-pollution is excluded as Rust has no prototype chain.
2
+ # attribution: CWE-79
3
+ attribution: CWE-79
4
+ language: rust
5
+ applies-to: []
6
+
7
+ sources:
8
+ - id: axum.extract.Json
9
+ class: http-body
10
+ query: |
11
+ (parameter
12
+ pattern: (tuple_struct_pattern)
13
+ type: (generic_type
14
+ type: [
15
+ (type_identifier) @type
16
+ (scoped_type_identifier name: (type_identifier) @type)
17
+ ]
18
+ (#eq? @type "Json"))) @source
19
+
20
+ - id: axum.extract.Form
21
+ class: http-body
22
+ query: |
23
+ (parameter
24
+ pattern: (tuple_struct_pattern)
25
+ type: (generic_type
26
+ type: [
27
+ (type_identifier) @type
28
+ (scoped_type_identifier name: (type_identifier) @type)
29
+ ]
30
+ (#eq? @type "Form"))) @source
31
+
32
+ - id: axum.extract.Query
33
+ class: http-params
34
+ query: |
35
+ (parameter
36
+ pattern: (tuple_struct_pattern)
37
+ type: (generic_type
38
+ type: [
39
+ (type_identifier) @type
40
+ (scoped_type_identifier name: (type_identifier) @type)
41
+ ]
42
+ (#eq? @type "Query"))) @source
43
+
44
+ - id: axum.extract.Path
45
+ class: http-params
46
+ query: |
47
+ (parameter
48
+ pattern: (tuple_struct_pattern)
49
+ type: (generic_type
50
+ type: [
51
+ (type_identifier) @type
52
+ (scoped_type_identifier name: (type_identifier) @type)
53
+ ]
54
+ (#eq? @type "Path"))) @source
55
+
56
+ - id: axum.http.HeaderMap
57
+ class: header
58
+ query: |
59
+ (parameter
60
+ type: [
61
+ (type_identifier) @type
62
+ (scoped_type_identifier name: (type_identifier) @type)
63
+ ]
64
+ (#eq? @type "HeaderMap")) @source
65
+
66
+ - id: axum.extract.CookieJar
67
+ class: cookie
68
+ query: |
69
+ (parameter
70
+ type: [
71
+ (type_identifier) @type
72
+ (scoped_type_identifier name: (type_identifier) @type)
73
+ ]
74
+ (#eq? @type "CookieJar")) @source
75
+
76
+ - id: actix.web.Json
77
+ class: http-body
78
+ query: |
79
+ (parameter
80
+ pattern: (identifier)
81
+ type: (generic_type
82
+ type: [
83
+ (type_identifier) @type
84
+ (scoped_type_identifier name: (type_identifier) @type)
85
+ ]
86
+ (#eq? @type "Json"))) @source
87
+
88
+ - id: actix.web.Form
89
+ class: http-body
90
+ query: |
91
+ (parameter
92
+ pattern: (identifier)
93
+ type: (generic_type
94
+ type: [
95
+ (type_identifier) @type
96
+ (scoped_type_identifier name: (type_identifier) @type)
97
+ ]
98
+ (#eq? @type "Form"))) @source
99
+
100
+ - id: actix.web.Query
101
+ class: http-params
102
+ query: |
103
+ (parameter
104
+ pattern: (identifier)
105
+ type: (generic_type
106
+ type: [
107
+ (type_identifier) @type
108
+ (scoped_type_identifier name: (type_identifier) @type)
109
+ ]
110
+ (#eq? @type "Query"))) @source
111
+
112
+ - id: std.env.var
113
+ class: env-var
114
+ query: |
115
+ (call_expression
116
+ function: [
117
+ (field_expression
118
+ field: (field_identifier) @func)
119
+ (scoped_identifier
120
+ name: (identifier) @func)
121
+ ]
122
+ (#match? @func "^(var|var_os)$")) @source
123
+
124
+ - id: std.env.args
125
+ class: process-argv
126
+ query: |
127
+ (call_expression
128
+ function: [
129
+ (field_expression
130
+ field: (field_identifier) @func)
131
+ (scoped_identifier
132
+ name: (identifier) @func)
133
+ ]
134
+ (#match? @func "^(args|args_os)$")) @source
135
+
136
+ - id: std.io.stdin
137
+ class: stdin
138
+ query: |
139
+ [
140
+ (call_expression
141
+ function: [
142
+ (field_expression
143
+ field: (field_identifier) @func)
144
+ (scoped_identifier
145
+ name: (identifier) @func)
146
+ ]
147
+ (#eq? @func "stdin")) @source
148
+ (call_expression
149
+ function: (field_expression
150
+ field: (field_identifier) @method
151
+ (#eq? @method "read_line"))
152
+ arguments: (arguments
153
+ (reference_expression
154
+ value: (identifier) @source)))
155
+ ]
156
+
157
+ - id: reqwest.response.text
158
+ class: network-response
159
+ query: |
160
+ (call_expression
161
+ function: (field_expression
162
+ field: (field_identifier) @method
163
+ (#eq? @method "text"))) @source
164
+
165
+ - id: reqwest.response.json
166
+ class: network-response
167
+ query: |
168
+ (call_expression
169
+ function: (field_expression
170
+ field: (field_identifier) @method
171
+ (#eq? @method "json"))) @source
172
+
173
+ - id: actix.HttpRequest.headers
174
+ class: header
175
+ query: |
176
+ (call_expression
177
+ function: (field_expression
178
+ field: (field_identifier) @method
179
+ (#eq? @method "headers"))) @source
180
+
181
+ - id: std.fs.read_to_string
182
+ class: fs-read
183
+ query: |
184
+ (call_expression
185
+ function: [
186
+ (field_expression
187
+ field: (field_identifier) @func)
188
+ (scoped_identifier
189
+ name: (identifier) @func)
190
+ ]
191
+ (#match? @func "^(read|read_to_string)$")) @source
192
+
193
+ sinks:
194
+ - id: std.process.Command.new
195
+ sink-class: command-injection
196
+ query: |
197
+ (call_expression
198
+ function: (scoped_identifier
199
+ path: [
200
+ (identifier) @path
201
+ (scoped_identifier name: (identifier) @path)
202
+ ]
203
+ (#eq? @path "Command")
204
+ name: (identifier) @func
205
+ (#eq? @func "new"))
206
+ arguments: (arguments (_) @sink .)) @match
207
+
208
+ - id: std.process.Command.arg
209
+ sink-class: command-injection
210
+ query: |
211
+ (call_expression
212
+ function: (field_expression
213
+ field: (field_identifier) @method
214
+ (#eq? @method "arg"))
215
+ arguments: (arguments (_) @sink)) @match
216
+
217
+ - id: std.process.Command.code-exec
218
+ sink-class: code-execution
219
+ query: |
220
+ (call_expression
221
+ function: (scoped_identifier
222
+ path: [
223
+ (identifier) @path
224
+ (scoped_identifier name: (identifier) @path)
225
+ ]
226
+ (#eq? @path "Command")
227
+ name: (identifier) @func
228
+ (#eq? @func "new"))
229
+ arguments: (arguments (_) @sink .)) @match
230
+
231
+ - id: libloading.Library.new
232
+ sink-class: code-execution
233
+ query: |
234
+ (call_expression
235
+ function: (scoped_identifier
236
+ path: [
237
+ (identifier) @path
238
+ (scoped_identifier name: (identifier) @path)
239
+ ]
240
+ (#eq? @path "Library")
241
+ name: (identifier) @func
242
+ (#eq? @func "new"))
243
+ arguments: (arguments (_) @sink)) @match
244
+
245
+ - id: sqlx.query
246
+ sink-class: sql-injection
247
+ query: |
248
+ (call_expression
249
+ function: [
250
+ (field_expression
251
+ field: (field_identifier) @func)
252
+ (scoped_identifier
253
+ name: (identifier) @func)
254
+ ]
255
+ (#eq? @func "query")
256
+ arguments: (arguments (_) @sink .)) @match
257
+
258
+ - id: sqlx.query_as
259
+ sink-class: sql-injection
260
+ query: |
261
+ (call_expression
262
+ function: [
263
+ (field_expression
264
+ field: (field_identifier) @func)
265
+ (scoped_identifier
266
+ name: (identifier) @func)
267
+ ]
268
+ (#eq? @func "query_as")
269
+ arguments: (arguments (_) @sink .)) @match
270
+
271
+ - id: diesel.sql_query
272
+ sink-class: sql-injection
273
+ query: |
274
+ (call_expression
275
+ function: [
276
+ (field_expression
277
+ field: (field_identifier) @func)
278
+ (scoped_identifier
279
+ name: (identifier) @func)
280
+ ]
281
+ (#eq? @func "sql_query")
282
+ arguments: (arguments (_) @sink .)) @match
283
+
284
+ - id: format.sql-sqli
285
+ sink-class: sql-injection
286
+ query: |
287
+ (macro_invocation
288
+ macro: (identifier) @name
289
+ (#eq? @name "format")
290
+ (token_tree
291
+ (string_literal) @sink
292
+ (#match? @sink "SELECT|INSERT|UPDATE|DELETE|UNION"))) @match
293
+
294
+ - id: std.fs.File.open
295
+ sink-class: path-traversal
296
+ query: |
297
+ (call_expression
298
+ function: [
299
+ (field_expression
300
+ field: (field_identifier) @func)
301
+ (scoped_identifier
302
+ name: (identifier) @func)
303
+ ]
304
+ (#match? @func "^(open|read|read_to_string|remove_file)$")
305
+ arguments: (arguments (_) @sink .)) @match
306
+
307
+ - id: std.fs.write
308
+ sink-class: path-traversal
309
+ query: |
310
+ (call_expression
311
+ function: [
312
+ (field_expression
313
+ field: (field_identifier) @func)
314
+ (scoped_identifier
315
+ name: (identifier) @func)
316
+ ]
317
+ (#match? @func "^(write|create_dir_all)$")
318
+ arguments: (arguments (_) @sink .)) @match
319
+
320
+ - id: axum.response.Html
321
+ sink-class: xss
322
+ query: |
323
+ (call_expression
324
+ function: [
325
+ (identifier) @func
326
+ (field_expression
327
+ field: (field_identifier) @func)
328
+ (scoped_identifier
329
+ name: (identifier) @func)
330
+ ]
331
+ (#eq? @func "Html")
332
+ arguments: (arguments (_) @sink)) @match
333
+
334
+ - id: actix.HttpResponse.body
335
+ sink-class: xss
336
+ query: |
337
+ (call_expression
338
+ function: (field_expression
339
+ field: (field_identifier) @method
340
+ (#eq? @method "body"))
341
+ arguments: (arguments (_) @sink)) @match
342
+
343
+ - id: axum.response.Redirect
344
+ sink-class: url-injection
345
+ query: |
346
+ (call_expression
347
+ function: [
348
+ (field_expression
349
+ field: (field_identifier) @method)
350
+ (scoped_identifier
351
+ name: (identifier) @method)
352
+ ]
353
+ (#eq? @method "to")
354
+ arguments: (arguments (_) @sink)) @match
355
+
356
+ - id: actix.HttpResponse.redirect
357
+ sink-class: url-injection
358
+ query: |
359
+ (call_expression
360
+ function: (field_expression
361
+ field: (field_identifier) @method
362
+ (#eq? @method "insert_header"))
363
+ arguments: (arguments
364
+ (tuple_expression
365
+ (_) @name
366
+ (_) @sink
367
+ (#match? @name "Location")))) @match
368
+
369
+ sanitisers:
370
+ - id: str.parse.i32
371
+ sanitises: [sql-injection]
372
+ autofix-safety: global
373
+ query: |
374
+ (call_expression
375
+ function: (generic_function
376
+ function: (field_expression
377
+ field: (field_identifier) @method
378
+ (#eq? @method "parse"))
379
+ type_arguments: (type_arguments
380
+ [
381
+ (type_identifier) @type
382
+ (primitive_type) @type
383
+ ]
384
+ (#eq? @type "i32")))) @sanitiser
385
+
386
+ - id: str.parse.f64
387
+ sanitises: [sql-injection]
388
+ autofix-safety: global
389
+ query: |
390
+ (call_expression
391
+ function: (generic_function
392
+ function: (field_expression
393
+ field: (field_identifier) @method
394
+ (#eq? @method "parse"))
395
+ type_arguments: (type_arguments
396
+ [
397
+ (type_identifier) @type
398
+ (primitive_type) @type
399
+ ]
400
+ (#eq? @type "f64")))) @sanitiser
401
+
402
+ - id: str.parse.bool
403
+ sanitises: [sql-injection]
404
+ autofix-safety: global
405
+ query: |
406
+ (call_expression
407
+ function: (generic_function
408
+ function: (field_expression
409
+ field: (field_identifier) @method
410
+ (#eq? @method "parse"))
411
+ type_arguments: (type_arguments
412
+ [
413
+ (type_identifier) @type
414
+ (primitive_type) @type
415
+ ]
416
+ (#eq? @type "bool")))) @sanitiser
417
+
418
+ - id: html_escape.encode_safe
419
+ sanitises: [xss]
420
+ autofix-safety: requires-import
421
+ query: |
422
+ (call_expression
423
+ function: [
424
+ (field_expression
425
+ field: (field_identifier) @func)
426
+ (scoped_identifier
427
+ name: (identifier) @func)
428
+ ]
429
+ (#match? @func "^(encode_safe|encode_text)$")) @sanitiser
430
+
431
+ - id: sqlx.query.bind
432
+ sanitises: [sql-injection]
433
+ autofix-safety: global
434
+ query: |
435
+ (call_expression
436
+ function: (field_expression
437
+ field: (field_identifier) @method
438
+ (#eq? @method "bind"))) @sanitiser
439
+
440
+ - id: diesel.sql_query.bind
441
+ sanitises: [sql-injection]
442
+ autofix-safety: global
443
+ query: |
444
+ (call_expression
445
+ function: (generic_function
446
+ function: (field_expression
447
+ field: (field_identifier) @method
448
+ (#eq? @method "bind")))) @sanitiser
449
+
450
+ - id: std.path.Path.canonicalize
451
+ sanitises: [path-traversal]
452
+ autofix-safety: requires-import
453
+ query: |
454
+ (call_expression
455
+ function: (field_expression
456
+ field: (field_identifier) @method
457
+ (#eq? @method "canonicalize"))) @sanitiser
458
+
459
+ - id: url.Url.parse
460
+ sanitises: [url-injection]
461
+ autofix-safety: requires-import
462
+ query: |
463
+ (call_expression
464
+ function: [
465
+ (field_expression
466
+ field: (field_identifier) @func)
467
+ (scoped_identifier
468
+ name: (identifier) @func)
469
+ ]
470
+ (#eq? @func "parse")) @sanitiser
471
+
472
+ - id: shell_words.join
473
+ sanitises: [command-injection]
474
+ autofix-safety: requires-import
475
+ query: |
476
+ (call_expression
477
+ function: [
478
+ (field_expression
479
+ field: (field_identifier) @func)
480
+ (scoped_identifier
481
+ name: (identifier) @func)
482
+ ]
483
+ (#eq? @func "join")) @sanitiser
@@ -0,0 +1,140 @@
1
+ language: tsx
2
+ cases:
3
+ - name: "TSX — direct XSS flow from req.body to res.send"
4
+ language: tsx
5
+ code: |
6
+ const x = req.body;
7
+ res.send(x);
8
+ expect:
9
+ count: 1
10
+ flows:
11
+ - sourceId: req.body
12
+ sinkId: res.send
13
+
14
+ - name: "TSX — SQL injection from req.query"
15
+ language: tsx
16
+ code: |
17
+ const q = req.query.id;
18
+ db.query("SELECT * FROM users WHERE id = " + q);
19
+ expect:
20
+ count: 1
21
+ flows:
22
+ - sourceId: req.query
23
+ sinkId: db.query
24
+
25
+ - name: "TSX — no source match returns zero flows"
26
+ language: tsx
27
+ code: |
28
+ console.log("hello world");
29
+ expect:
30
+ count: 0
31
+
32
+ - name: "TSX — dangerouslySetInnerHTML XSS from req.body"
33
+ language: tsx
34
+ code: |
35
+ export default function Page() {
36
+ return <div dangerouslySetInnerHTML={{ __html: req.body }} />;
37
+ }
38
+ expect:
39
+ count: 1
40
+ flows:
41
+ - sourceId: req.body
42
+ sinkId: dangerouslySetInnerHTML
43
+
44
+ - name: "TSX — dangerouslySetInnerHTML safe static __html"
45
+ language: tsx
46
+ code: |
47
+ export default function Page() {
48
+ return <div dangerouslySetInnerHTML={{ __html: "<p>safe</p>" }} />;
49
+ }
50
+ expect:
51
+ count: 0
52
+
53
+ - name: "TSX — path traversal fs.readFile in server component"
54
+ language: tsx
55
+ code: |
56
+ export default function Page() {
57
+ fs.readFile(req.params.file);
58
+ return <div />;
59
+ }
60
+ expect:
61
+ count: 1
62
+ flows:
63
+ - sourceId: req.params
64
+ sinkId: fs.readFile-path
65
+
66
+ - name: "TSX — command injection exec in server component"
67
+ language: tsx
68
+ code: |
69
+ export default function Page() {
70
+ exec(req.query.cmd);
71
+ return <div />;
72
+ }
73
+ expect:
74
+ count: 1
75
+ flows:
76
+ - sourceId: req.query
77
+ sinkId: exec
78
+
79
+ - name: "TSX — open redirect via Next redirect()"
80
+ language: tsx
81
+ code: |
82
+ export default function Page() {
83
+ redirect(req.query.next);
84
+ return <div />;
85
+ }
86
+ expect:
87
+ count: 1
88
+ flows:
89
+ - sourceId: req.query
90
+ sinkId: next.redirect
91
+
92
+ - name: "TSX — open redirect via Link href"
93
+ language: tsx
94
+ code: |
95
+ export default function Page() {
96
+ const url = req.query.next;
97
+ return <Link href={url} />;
98
+ }
99
+ expect:
100
+ count: 1
101
+ flows:
102
+ - sourceId: req.query
103
+ sinkId: jsx-href
104
+
105
+ - name: "TSX — prototype pollution merge in client component"
106
+ language: tsx
107
+ code: |
108
+ export default function Page() {
109
+ const target = {};
110
+ merge(target, req.body);
111
+ return <div />;
112
+ }
113
+ expect:
114
+ count: 1
115
+ flows:
116
+ - sourceId: req.body
117
+ sinkId: merge-deep
118
+
119
+ - name: "TSX — formData.get to SQLi in server action"
120
+ language: tsx
121
+ code: |
122
+ export async function submit(formData: FormData) {
123
+ const id = formData.get("id");
124
+ db.query("SELECT * FROM users WHERE id = " + id);
125
+ }
126
+ expect:
127
+ count: 1
128
+ flows:
129
+ - sourceId: formData.get
130
+ sinkId: db.query
131
+
132
+ - name: "TSX — DOMPurify sanitises dangerouslySetInnerHTML"
133
+ language: tsx
134
+ code: |
135
+ export default function Page() {
136
+ const html = DOMPurify.sanitize(req.body);
137
+ return <div dangerouslySetInnerHTML={{ __html: html }} />;
138
+ }
139
+ expect:
140
+ count: 0
@@ -0,0 +1,51 @@
1
+ # attribution: CWE-79
2
+ # JSX-only taint rules (supplement-only). Plain TypeScript grammar cannot compile these queries.
3
+ # Shared Node/Next sinks (e.g. next.redirect, res.send) live in typescript.yaml with applies-to: [tsx].
4
+ # Do not duplicate sink IDs from typescript.yaml here — the loader rejects duplicate IDs on merge.
5
+ attribution: CWE-79
6
+ language: tsx
7
+ supplement-only: true
8
+
9
+ sources:
10
+ - id: formData.get
11
+ class: http-body
12
+ query: |
13
+ (call_expression
14
+ function: (member_expression
15
+ object: (identifier) @obj
16
+ property: (property_identifier) @prop
17
+ (#eq? @obj "formData")
18
+ (#eq? @prop "get"))) @source
19
+
20
+ sinks:
21
+ - id: dangerouslySetInnerHTML
22
+ sink-class: xss
23
+ query: |
24
+ (jsx_attribute
25
+ (property_identifier) @prop
26
+ (#eq? @prop "dangerouslySetInnerHTML")
27
+ (jsx_expression
28
+ (object
29
+ (pair
30
+ key: (property_identifier) @key
31
+ (#eq? @key "__html")
32
+ value: (_) @sink)))) @match
33
+
34
+ - id: dangerouslySetInnerHTML-spread
35
+ sink-class: xss
36
+ query: |
37
+ (jsx_attribute
38
+ (property_identifier) @prop
39
+ (#eq? @prop "dangerouslySetInnerHTML")
40
+ (jsx_expression
41
+ (spread_element (_) @sink))) @match
42
+
43
+ - id: jsx-href
44
+ sink-class: url-injection
45
+ query: |
46
+ (jsx_attribute
47
+ (property_identifier) @prop
48
+ (#eq? @prop "href")
49
+ (jsx_expression (_) @sink)) @match
50
+
51
+ sanitisers: []