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,111 @@
1
+ rule-id: ops.insecure-file-permissions
2
+
3
+ cases:
4
+ - name: triggers on fs.chmod with insecure mode in javascript
5
+ language: javascript
6
+ code: |
7
+ const fs = require('fs')
8
+ fs.chmod('file.txt', 0o777)
9
+ expect:
10
+ count: 1
11
+ severity: low
12
+
13
+ - name: triggers on fs.chmod with insecure mode in typescript
14
+ language: typescript
15
+ code: |
16
+ import fs from 'fs'
17
+ fs.chmod('/etc/shadow', 0o666)
18
+ expect:
19
+ count: 1
20
+ severity: low
21
+
22
+ - name: triggers on fs.chmod with insecure mode in tsx
23
+ language: tsx
24
+ code: |
25
+ import fs from 'fs'
26
+ fs.chmod('config.json', 0o777)
27
+ expect:
28
+ count: 1
29
+ severity: low
30
+
31
+ - name: ignores fs.chmod with secure mode in typescript
32
+ language: typescript
33
+ code: |
34
+ import fs from 'fs'
35
+ fs.chmod('/etc/shadow', 0o644)
36
+ expect:
37
+ count: 0
38
+
39
+ - name: ignores fs.chmod with secure mode in tsx
40
+ language: tsx
41
+ code: |
42
+ import fs from 'fs'
43
+ fs.chmod('config.json', 0o600)
44
+ expect:
45
+ count: 0
46
+
47
+ - name: ignores unrelated fs operation
48
+ language: javascript
49
+ code: |
50
+ const fs = require('fs')
51
+ fs.readFile('file.txt', callback)
52
+ expect:
53
+ count: 0
54
+ - name: triggers on os.chmod with insecure mode in python
55
+ language: python
56
+ code: |
57
+ import os
58
+ os.chmod("config.json", 0o777)
59
+ expect:
60
+ count: 1
61
+ severity: low
62
+ - name: triggers on chmod 777 in bash
63
+ language: bash
64
+ code: |
65
+ chmod 777 ./config
66
+ expect:
67
+ count: 1
68
+ severity: low
69
+ - name: ignores os.chmod with secure mode in python
70
+ language: python
71
+ code: |
72
+ import os
73
+ os.chmod("config.json", 0o644)
74
+ expect:
75
+ count: 0
76
+ - name: ignores unrelated python os call
77
+ language: python
78
+ code: |
79
+ import os
80
+ os.remove("file.txt")
81
+ expect:
82
+ count: 0
83
+ - name: ignores chmod 600 in bash
84
+ language: bash
85
+ code: |
86
+ chmod 600 ./config
87
+ expect:
88
+ count: 0
89
+
90
+ - name: triggers on insecure permissions in rust
91
+ language: rust
92
+ code: |
93
+ Permissions::from_mode(0o777)
94
+ expect:
95
+ count: 1
96
+ severity: low
97
+
98
+ - name: ignores secure permissions in rust
99
+ language: rust
100
+ code: |
101
+ Permissions::from_mode(0o644)
102
+ expect:
103
+ count: 0
104
+
105
+ - name: triggers on chmod 777 in ruby
106
+ language: ruby
107
+ code: |
108
+ File.chmod(0777, "config.yml")
109
+ expect:
110
+ count: 1
111
+ severity: low
@@ -0,0 +1,91 @@
1
+ # source: clean-room
2
+ # licence: MIT
3
+ # vendored-at: 2026-05-20
4
+ # verified-by: Seaworthy team
5
+ # attribution: CWE-276
6
+ id: ops.insecure-file-permissions
7
+ severity: low
8
+ category: ops
9
+ min-tier: pro
10
+ languages: [javascript, typescript, tsx, python, bash, rust, ruby]
11
+
12
+ copy:
13
+ name-key: checks.insecure-file-permissions.name
14
+ description-key: checks.insecure-file-permissions.description
15
+ message-key: checks.insecure-file-permissions.message
16
+ degraded-key: checks.insecure-file-permissions.degraded
17
+ remediation-key: remediation.ops.insecure-file-permissions
18
+
19
+ confidence: low
20
+
21
+ queries:
22
+ javascript: |
23
+ (call_expression
24
+ function: (member_expression
25
+ object: (identifier) @obj
26
+ property: (property_identifier) @method)
27
+ arguments: (arguments
28
+ (number) @perm)
29
+ (#eq? @obj "fs")
30
+ (#eq? @method "chmod")
31
+ (#match? @perm "0o?[0-7][2367][0-7]|0o?[0-7][0-7][2367]")) @match
32
+ typescript: |
33
+ (call_expression
34
+ function: (member_expression
35
+ object: (identifier) @obj
36
+ property: (property_identifier) @method)
37
+ arguments: (arguments
38
+ (number) @perm)
39
+ (#eq? @obj "fs")
40
+ (#eq? @method "chmod")
41
+ (#match? @perm "0o?[0-7][2367][0-7]|0o?[0-7][0-7][2367]")) @match
42
+ tsx: |
43
+ (call_expression
44
+ function: (member_expression
45
+ object: (identifier) @obj
46
+ property: (property_identifier) @method)
47
+ arguments: (arguments
48
+ (number) @perm)
49
+ (#eq? @obj "fs")
50
+ (#eq? @method "chmod")
51
+ (#match? @perm "0o?[0-7][2367][0-7]|0o?[0-7][0-7][2367]")) @match
52
+ python: |
53
+ (call
54
+ function: (attribute
55
+ object: (identifier) @obj
56
+ attribute: (identifier) @method)
57
+ arguments: (argument_list
58
+ (integer) @perm)
59
+ (#eq? @obj "os")
60
+ (#eq? @method "chmod")
61
+ (#match? @perm "0o?[0-7][2367][0-7]|0o?[0-7][0-7][2367]")) @match
62
+ bash: |
63
+ (command
64
+ name: (command_name (word) @cmd)
65
+ argument: (_) @perm
66
+ (#eq? @cmd "chmod")
67
+ (#match? @perm "^(777|666|a\\+wx|a\\+w)$")) @match
68
+ rust: |
69
+ (call_expression
70
+ function: [
71
+ (field_expression
72
+ field: (field_identifier) @func
73
+ (#eq? @func "from_mode"))
74
+ (scoped_identifier
75
+ name: (identifier) @func
76
+ (#eq? @func "from_mode"))
77
+ ]
78
+ arguments: (arguments
79
+ (integer_literal) @perm
80
+ (#match? @perm "0o?[0-7][2367][0-7]|0o?[0-7][0-7][2367]"))) @match
81
+
82
+ ruby: |
83
+ (call
84
+ receiver: (constant) @recv (#eq? @recv "File")
85
+ method: (identifier) @method
86
+ (#eq? @method "chmod")
87
+ arguments: (argument_list
88
+ (integer) @perm
89
+ (#match? @perm "0o?[0-7][2367][0-7]|0o?[0-7][0-7][2367]"))) @match
90
+
91
+ message-captures: [match]
@@ -0,0 +1,54 @@
1
+ rule-id: resilience.missing-memory-limit
2
+
3
+ cases:
4
+ - name: triggers on Buffer.alloc with variable size in javascript
5
+ language: javascript
6
+ code: |
7
+ Buffer.alloc(userInput.length)
8
+ expect:
9
+ count: 1
10
+ severity: low
11
+
12
+ - name: triggers on Buffer.alloc with expression size in typescript
13
+ language: typescript
14
+ code: |
15
+ Buffer.alloc(size * 2)
16
+ expect:
17
+ count: 1
18
+ severity: low
19
+
20
+ - name: triggers on Buffer.alloc with identifier size in tsx
21
+ language: tsx
22
+ code: |
23
+ Buffer.alloc(bufSize)
24
+ expect:
25
+ count: 1
26
+ severity: low
27
+
28
+ - name: ignores fixed-size Buffer.alloc
29
+ language: javascript
30
+ code: |
31
+ Buffer.alloc(1024)
32
+ expect:
33
+ count: 0
34
+
35
+ - name: ignores fixed-size Buffer.alloc in typescript
36
+ language: typescript
37
+ code: |
38
+ Buffer.alloc(1024)
39
+ expect:
40
+ count: 0
41
+
42
+ - name: ignores unrelated buffer usage
43
+ language: javascript
44
+ code: |
45
+ const buf = Buffer.from("hello")
46
+ expect:
47
+ count: 0
48
+
49
+ - name: ignores unrelated buffer usage in typescript
50
+ language: typescript
51
+ code: |
52
+ const buf = Buffer.from("hello")
53
+ expect:
54
+ count: 0
@@ -0,0 +1,59 @@
1
+ # source: clean-room
2
+ # licence: MIT
3
+ # vendored-at: 2026-05-20
4
+ # verified-by: Seaworthy team
5
+ # attribution: CWE-770
6
+ id: resilience.missing-memory-limit
7
+ severity: low
8
+ category: resilience
9
+ min-tier: pro
10
+ languages: [javascript, typescript, tsx]
11
+
12
+ copy:
13
+ name-key: checks.missing-memory-limit.name
14
+ description-key: checks.missing-memory-limit.description
15
+ message-key: checks.missing-memory-limit.message
16
+ degraded-key: checks.missing-memory-limit.degraded
17
+ remediation-key: remediation.resilience.missing-memory-limit
18
+
19
+ confidence: low
20
+
21
+ queries:
22
+ javascript: |
23
+ (call_expression
24
+ function: (member_expression
25
+ object: (identifier) @obj
26
+ property: (property_identifier) @method)
27
+ arguments: (arguments
28
+ [(identifier) @size
29
+ (member_expression) @size
30
+ (call_expression) @size
31
+ (binary_expression) @size])
32
+ (#eq? @obj "Buffer")
33
+ (#eq? @method "alloc")) @match
34
+ typescript: |
35
+ (call_expression
36
+ function: (member_expression
37
+ object: (identifier) @obj
38
+ property: (property_identifier) @method)
39
+ arguments: (arguments
40
+ [(identifier) @size
41
+ (member_expression) @size
42
+ (call_expression) @size
43
+ (binary_expression) @size])
44
+ (#eq? @obj "Buffer")
45
+ (#eq? @method "alloc")) @match
46
+ tsx: |
47
+ (call_expression
48
+ function: (member_expression
49
+ object: (identifier) @obj
50
+ property: (property_identifier) @method)
51
+ arguments: (arguments
52
+ [(identifier) @size
53
+ (member_expression) @size
54
+ (call_expression) @size
55
+ (binary_expression) @size])
56
+ (#eq? @obj "Buffer")
57
+ (#eq? @method "alloc")) @match
58
+
59
+ message-captures: [match]
@@ -0,0 +1,179 @@
1
+ rule-id: resilience.missing-timeout-config
2
+
3
+ cases:
4
+ - name: triggers on fetch in javascript
5
+ language: javascript
6
+ code: |
7
+ fetch("/api/data")
8
+ expect:
9
+ count: 1
10
+ severity: low
11
+
12
+ - name: triggers on fetch in typescript
13
+ language: typescript
14
+ code: |
15
+ fetch("/api/users")
16
+ expect:
17
+ count: 1
18
+ severity: low
19
+
20
+ - name: triggers on fetch in tsx
21
+ language: tsx
22
+ code: |
23
+ fetch("/api/items")
24
+ expect:
25
+ count: 1
26
+ severity: low
27
+
28
+ - name: ignores fetch with explicit signal timeout
29
+ language: javascript
30
+ code: |
31
+ const controller = AbortSignal.timeout(5000)
32
+ fetch("/api/data", { signal: controller })
33
+ expect:
34
+ count: 0
35
+
36
+ - name: ignores fetch with explicit signal timeout in typescript
37
+ language: typescript
38
+ code: |
39
+ const controller = AbortSignal.timeout(5000)
40
+ fetch("/api/data", { signal: controller })
41
+ expect:
42
+ count: 0
43
+
44
+ - name: ignores fetch with signal shorthand
45
+ language: javascript
46
+ code: |
47
+ const signal = AbortSignal.timeout(5000)
48
+ fetch("/api/data", { signal })
49
+ expect:
50
+ count: 0
51
+
52
+ - name: ignores fetch with signal shorthand in typescript
53
+ language: typescript
54
+ code: |
55
+ const signal = AbortSignal.timeout(5000)
56
+ fetch("/api/data", { signal })
57
+ expect:
58
+ count: 0
59
+
60
+ - name: ignores unrelated method
61
+ language: javascript
62
+ code: |
63
+ axios.post("/api", data)
64
+ expect:
65
+ count: 0
66
+
67
+ - name: ignores unrelated method in typescript
68
+ language: typescript
69
+ code: |
70
+ axios.post("/api", data)
71
+ expect:
72
+ count: 0
73
+
74
+ - name: triggers on requests.get without timeout in python
75
+ language: python
76
+ code: |
77
+ requests.get("https://example.com")
78
+ expect:
79
+ count: 1
80
+ severity: low
81
+ - name: triggers on httpx.post without timeout in python
82
+ language: python
83
+ code: |
84
+ httpx.post("https://api.example.com", json=data)
85
+ expect:
86
+ count: 1
87
+ severity: low
88
+ - name: triggers on curl without timeout in bash
89
+ language: bash
90
+ code: |
91
+ curl https://example.com
92
+ expect:
93
+ count: 1
94
+ severity: low
95
+ - name: ignores requests.get with timeout in python
96
+ language: python
97
+ code: |
98
+ requests.get("https://example.com", timeout=30)
99
+ expect:
100
+ count: 0
101
+ - name: ignores unrelated python call
102
+ language: python
103
+ code: |
104
+ print("hello")
105
+ expect:
106
+ count: 0
107
+ - name: ignores curl with max time in bash
108
+ language: bash
109
+ code: |
110
+ curl --max-time 5 https://example.com
111
+ expect:
112
+ count: 0
113
+
114
+ - name: triggers on reqwest get without timeout in rust
115
+ language: rust
116
+ code: |
117
+ reqwest::get("https://example.com")
118
+ expect:
119
+ count: 1
120
+ severity: low
121
+
122
+ - name: triggers on TcpStream connect without timeout in rust
123
+ language: rust
124
+ code: |
125
+ std::net::TcpStream::connect("127.0.0.1:8080")
126
+ expect:
127
+ count: 1
128
+ severity: low
129
+
130
+ - name: ignores unrelated rust call
131
+ language: rust
132
+ code: |
133
+ println!("hello")
134
+ expect:
135
+ count: 0
136
+
137
+ - name: triggers on RestTemplate getForObject in java
138
+ language: java
139
+ code: |
140
+ class T {
141
+ void f(org.springframework.web.client.RestTemplate rt) {
142
+ rt.getForObject("https://example.com", String.class);
143
+ }
144
+ }
145
+ expect:
146
+ count: 1
147
+ severity: low
148
+
149
+ - name: ignores RestTemplate with timeouts configured via builder in java
150
+ language: java
151
+ code: |
152
+ class T {
153
+ void f() {
154
+ org.springframework.web.client.RestTemplate rt = new org.springframework.boot.web.client.RestTemplateBuilder()
155
+ .setConnectTimeout(java.time.Duration.ofSeconds(5))
156
+ .setReadTimeout(java.time.Duration.ofSeconds(5))
157
+ .build();
158
+ rt.getForObject("https://example.com", String.class);
159
+ }
160
+ }
161
+ expect:
162
+ count: 0
163
+
164
+ - name: triggers on Net::HTTP.get without timeout in ruby
165
+ language: ruby
166
+ code: |
167
+ Net::HTTP.get(URI("https://api.example.com"))
168
+ expect:
169
+ count: 1
170
+ severity: low
171
+
172
+ - name: ignores Net::HTTP with timeouts in ruby
173
+ language: ruby
174
+ code: |
175
+ Net::HTTP.start("example.com", open_timeout: 10, read_timeout: 10) do |http|
176
+ http.get("/")
177
+ end
178
+ expect:
179
+ count: 0
@@ -0,0 +1,124 @@
1
+ # source: clean-room
2
+ # licence: MIT
3
+ # vendored-at: 2026-05-20
4
+ # verified-by: Seaworthy team
5
+ # attribution: CWE-400
6
+ id: resilience.missing-timeout-config
7
+ severity: low
8
+ category: resilience
9
+ min-tier: pro
10
+ languages: [javascript, typescript, tsx, python, bash, rust, java, ruby]
11
+
12
+ copy:
13
+ name-key: checks.missing-timeout-config.name
14
+ description-key: checks.missing-timeout-config.description
15
+ message-key: checks.missing-timeout-config.message
16
+ degraded-key: checks.missing-timeout-config.degraded
17
+ remediation-key: remediation.resilience.missing-timeout-config
18
+
19
+ confidence: medium
20
+
21
+ queries:
22
+ javascript: |
23
+ ((call_expression
24
+ function: (identifier) @func
25
+ (#eq? @func "fetch")) @match
26
+ (#not-match? @match "signal(\\s*:|(?=\\s*[,}]))"))
27
+ typescript: |
28
+ ((call_expression
29
+ function: (identifier) @func
30
+ (#eq? @func "fetch")) @match
31
+ (#not-match? @match "signal(\\s*:|(?=\\s*[,}]))"))
32
+ tsx: |
33
+ ((call_expression
34
+ function: (identifier) @func
35
+ (#eq? @func "fetch")) @match
36
+ (#not-match? @match "signal(\\s*:|(?=\\s*[,}]))"))
37
+ python: |
38
+ ((call
39
+ function: (attribute
40
+ object: (identifier) @obj
41
+ attribute: (identifier) @method)
42
+ arguments: (argument_list
43
+ (string) @url)
44
+ (#match? @obj "^(requests|httpx|aiohttp)$")
45
+ (#match? @method "^(get|post|put|patch|delete|head|options)$")) @match
46
+ (#not-match? @match "timeout\\s*="))
47
+ bash: |
48
+ ((command
49
+ name: (command_name (word) @cmd)
50
+ (#match? @cmd "^(curl|wget)$")) @match
51
+ (#not-match? @match "(--max-time|--connect-timeout|--timeout|timeout\s+)"))
52
+
53
+ rust: |
54
+ (call_expression
55
+ function: (scoped_identifier
56
+ path: (identifier) @reqwest_path
57
+ name: (identifier) @reqwest_func)
58
+ (#eq? @reqwest_path "reqwest")
59
+ (#match? @reqwest_func "^(get|post|put|patch|delete|head|options)$")) @match
60
+ (call_expression
61
+ function: (scoped_identifier
62
+ path: (scoped_identifier) @tcp_path
63
+ name: (identifier) @tcp_func)
64
+ (#match? @tcp_path "TcpStream$")
65
+ (#eq? @tcp_func "connect")) @match
66
+ java: |
67
+ ((method_declaration
68
+ parameters: (formal_parameters
69
+ (formal_parameter
70
+ type: [
71
+ (type_identifier) @type
72
+ (scoped_type_identifier) @type
73
+ ]
74
+ name: (identifier) @obj))
75
+ body: (block
76
+ (expression_statement
77
+ (method_invocation
78
+ object: (identifier) @recv
79
+ name: (identifier) @method (#match? @method "^(getForObject|postForObject|exchange|execute)$")
80
+ (#match? @type "(RestTemplate|AsyncRestTemplate|WebClient|HttpClient|HttpComponentsClient)$")
81
+ ) @match))) @scope
82
+ (#not-match? @scope "[tT][iI][mM][eE][oO][uU][tT]"))
83
+
84
+ ((block
85
+ (local_variable_declaration
86
+ type: [
87
+ (type_identifier) @type
88
+ (scoped_type_identifier) @type
89
+ ]
90
+ declarator: (variable_declarator
91
+ name: (identifier) @obj))
92
+ (expression_statement
93
+ (method_invocation
94
+ object: (identifier) @recv
95
+ name: (identifier) @method (#match? @method "^(getForObject|postForObject|exchange|execute)$")
96
+ (#match? @type "(RestTemplate|AsyncRestTemplate|WebClient|HttpClient|HttpComponentsClient)$")) @match)) @scope
97
+ (#not-match? @scope "[tT][iI][mM][eE][oO][uU][tT]"))
98
+
99
+ ((class_body
100
+ (field_declaration
101
+ type: [
102
+ (type_identifier) @type
103
+ (scoped_type_identifier) @type
104
+ ]
105
+ declarator: (variable_declarator
106
+ name: (identifier) @obj))
107
+ (method_declaration
108
+ body: (block
109
+ (expression_statement
110
+ (method_invocation
111
+ object: (identifier) @recv
112
+ name: (identifier) @method (#match? @method "^(getForObject|postForObject|exchange|execute)$")
113
+ (#match? @type "(RestTemplate|AsyncRestTemplate|WebClient|HttpClient|HttpComponentsClient)$")) @match)))) @scope
114
+ (#not-match? @scope "[tT][iI][mM][eE][oO][uU][tT]"))
115
+
116
+ ruby: |
117
+ ((call
118
+ receiver: (scope_resolution
119
+ scope: (constant) @scope (#eq? @scope "Net")
120
+ name: (constant) @name (#eq? @name "HTTP"))
121
+ method: (identifier) @method (#match? @method "^(get|get_response|post|start)$")) @match
122
+ (#not-match? @match "timeout"))
123
+
124
+ message-captures: [match]