circle-ir 3.51.0 → 3.53.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/configs/sinks/path.yaml +0 -16
- package/configs/sources/file_sources.yaml +32 -0
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +17 -20
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/passes/insecure-cookie-pass.d.ts +23 -23
- package/dist/analysis/passes/insecure-cookie-pass.d.ts.map +1 -1
- package/dist/analysis/passes/insecure-cookie-pass.js +169 -79
- package/dist/analysis/passes/insecure-cookie-pass.js.map +1 -1
- package/dist/analysis/passes/tls-verify-disabled-pass.d.ts +52 -0
- package/dist/analysis/passes/tls-verify-disabled-pass.d.ts.map +1 -0
- package/dist/analysis/passes/tls-verify-disabled-pass.js +247 -0
- package/dist/analysis/passes/tls-verify-disabled-pass.js.map +1 -0
- package/dist/analysis/passes/weak-crypto-pass.d.ts +59 -0
- package/dist/analysis/passes/weak-crypto-pass.d.ts.map +1 -0
- package/dist/analysis/passes/weak-crypto-pass.js +392 -0
- package/dist/analysis/passes/weak-crypto-pass.js.map +1 -0
- package/dist/analysis/passes/weak-hash-pass.d.ts +45 -0
- package/dist/analysis/passes/weak-hash-pass.d.ts.map +1 -0
- package/dist/analysis/passes/weak-hash-pass.js +150 -0
- package/dist/analysis/passes/weak-hash-pass.js.map +1 -0
- package/dist/analysis/passes/weak-random-pass.d.ts +53 -0
- package/dist/analysis/passes/weak-random-pass.d.ts.map +1 -0
- package/dist/analysis/passes/weak-random-pass.js +181 -0
- package/dist/analysis/passes/weak-random-pass.js.map +1 -0
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +28 -13
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +12 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +852 -57
- package/dist/core/circle-ir-core.cjs +25 -26
- package/dist/core/circle-ir-core.js +25 -26
- package/package.json +1 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pass: tls-verify-disabled (CWE-295, category: security)
|
|
3
|
+
*
|
|
4
|
+
* Pattern pass — flags places where TLS certificate / hostname verification
|
|
5
|
+
* is explicitly disabled. This is a *configuration* vulnerability (the bad
|
|
6
|
+
* value is hard-coded, no taint flow is involved).
|
|
7
|
+
*
|
|
8
|
+
* Detection per language:
|
|
9
|
+
* Go:
|
|
10
|
+
* - `&tls.Config{InsecureSkipVerify: true}` (composite literal)
|
|
11
|
+
* - Detected via call argument scan: when the receiver is `tls` and
|
|
12
|
+
* call/composite contains literal `InsecureSkipVerify: true`, OR via
|
|
13
|
+
* a syntactic text scan (composite literals are not always emitted
|
|
14
|
+
* as calls in IR).
|
|
15
|
+
* Python:
|
|
16
|
+
* - `requests.get|post|put|delete|patch|head|options|request(..., verify=False)`
|
|
17
|
+
* - `ssl._create_unverified_context()` / `ssl._create_default_https_context = ssl._create_unverified_context`
|
|
18
|
+
* - `urllib3.disable_warnings(InsecureRequestWarning)` — best-effort hint
|
|
19
|
+
* - `httpx.Client(verify=False)` / `httpx.get(..., verify=False)`
|
|
20
|
+
* JavaScript / TypeScript:
|
|
21
|
+
* - `{ rejectUnauthorized: false }` in https.request / fetch options /
|
|
22
|
+
* node-fetch / axios — text scan on arg expressions
|
|
23
|
+
* - `https.Agent({ rejectUnauthorized: false })`
|
|
24
|
+
* - `process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'` (assignment;
|
|
25
|
+
* detected via call to property assignment — best-effort)
|
|
26
|
+
* Java:
|
|
27
|
+
* - Custom `HostnameVerifier` that returns true unconditionally
|
|
28
|
+
* (lambdas `(h, s) -> true` / anonymous classes) — detected via
|
|
29
|
+
* textual scan on setHostnameVerifier arg expression.
|
|
30
|
+
* - `setHostnameVerifier(NoopHostnameVerifier.INSTANCE)` /
|
|
31
|
+
* `setHostnameVerifier(new AllowAllHostnameVerifier())`
|
|
32
|
+
*
|
|
33
|
+
* Aligned with: gosec G402 (Go), Bandit B501/B502/B504/B505 (Python).
|
|
34
|
+
*/
|
|
35
|
+
// Python HTTP libraries whose calls accept a verify=False kwarg.
|
|
36
|
+
const PY_HTTP_METHODS = new Set([
|
|
37
|
+
'get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'request',
|
|
38
|
+
'send',
|
|
39
|
+
]);
|
|
40
|
+
const PY_HTTP_RECEIVERS = new Set([
|
|
41
|
+
'requests', 'httpx',
|
|
42
|
+
]);
|
|
43
|
+
const VERIFY_FALSE_RE = /\bverify\s*=\s*False\b/;
|
|
44
|
+
const REJECT_UNAUTHORIZED_FALSE_RE = /\brejectUnauthorized\s*:\s*false\b/;
|
|
45
|
+
const INSECURE_SKIP_VERIFY_TRUE_RE = /\bInsecureSkipVerify\s*:\s*true\b/;
|
|
46
|
+
const HOSTNAME_LAMBDA_TRUE_RE = /\(\s*\w+\s*,\s*\w+\s*\)\s*->\s*true\b/;
|
|
47
|
+
const ALLOW_ALL_HOSTNAME_VERIFIERS = new Set([
|
|
48
|
+
'NoopHostnameVerifier.INSTANCE',
|
|
49
|
+
'new AllowAllHostnameVerifier()',
|
|
50
|
+
'new NoopHostnameVerifier()',
|
|
51
|
+
]);
|
|
52
|
+
export class TlsVerifyDisabledPass {
|
|
53
|
+
name = 'tls-verify-disabled';
|
|
54
|
+
category = 'security';
|
|
55
|
+
run(ctx) {
|
|
56
|
+
const { graph, language, code } = ctx;
|
|
57
|
+
const file = graph.ir.meta.file;
|
|
58
|
+
const findings = [];
|
|
59
|
+
// Call-based detection (most precise — uses arg.expression text).
|
|
60
|
+
for (const call of graph.ir.calls) {
|
|
61
|
+
const det = this.detectCall(call, language);
|
|
62
|
+
if (!det)
|
|
63
|
+
continue;
|
|
64
|
+
const line = call.location.line;
|
|
65
|
+
findings.push({ line, language, ...det });
|
|
66
|
+
ctx.addFinding({
|
|
67
|
+
id: `${this.name}-${file}-${line}-${det.pattern}`,
|
|
68
|
+
pass: this.name,
|
|
69
|
+
category: this.category,
|
|
70
|
+
rule_id: this.name,
|
|
71
|
+
cwe: 'CWE-295',
|
|
72
|
+
severity: 'high',
|
|
73
|
+
level: 'error',
|
|
74
|
+
message: `TLS certificate verification disabled via \`${det.pattern}\` in ` +
|
|
75
|
+
`\`${det.api}\`. The connection becomes vulnerable to active ` +
|
|
76
|
+
'man-in-the-middle attacks — any attacker on the network path can ' +
|
|
77
|
+
'present a forged certificate.',
|
|
78
|
+
file,
|
|
79
|
+
line,
|
|
80
|
+
fix: this.fixFor(language, det.pattern),
|
|
81
|
+
evidence: { ...det, language },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// Source-text scan for composite-literal / module-level patterns that
|
|
85
|
+
// do not surface as IR calls (Go `tls.Config{}`, Python ssl globals,
|
|
86
|
+
// Node `NODE_TLS_REJECT_UNAUTHORIZED`).
|
|
87
|
+
for (const extra of this.detectSourceText(code, language)) {
|
|
88
|
+
const dupKey = `${extra.line}-${extra.pattern}`;
|
|
89
|
+
if (findings.some((f) => `${f.line}-${f.pattern}` === dupKey))
|
|
90
|
+
continue;
|
|
91
|
+
findings.push({ ...extra, language });
|
|
92
|
+
ctx.addFinding({
|
|
93
|
+
id: `${this.name}-${file}-${extra.line}-${extra.pattern}`,
|
|
94
|
+
pass: this.name,
|
|
95
|
+
category: this.category,
|
|
96
|
+
rule_id: this.name,
|
|
97
|
+
cwe: 'CWE-295',
|
|
98
|
+
severity: 'high',
|
|
99
|
+
level: 'error',
|
|
100
|
+
message: `TLS certificate verification disabled via \`${extra.pattern}\` ` +
|
|
101
|
+
`(${extra.api}). Vulnerable to active man-in-the-middle.`,
|
|
102
|
+
file,
|
|
103
|
+
line: extra.line,
|
|
104
|
+
fix: this.fixFor(language, extra.pattern),
|
|
105
|
+
evidence: { ...extra, language },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return { findings };
|
|
109
|
+
}
|
|
110
|
+
detectCall(call, language) {
|
|
111
|
+
const method = call.method_name;
|
|
112
|
+
const receiver = call.receiver ?? '';
|
|
113
|
+
if (language === 'python') {
|
|
114
|
+
// requests.get(..., verify=False) etc.
|
|
115
|
+
if (PY_HTTP_RECEIVERS.has(receiver) && PY_HTTP_METHODS.has(method)) {
|
|
116
|
+
for (const arg of call.arguments) {
|
|
117
|
+
const expr = (arg.expression ?? '').trim();
|
|
118
|
+
if (VERIFY_FALSE_RE.test(expr)) {
|
|
119
|
+
return { pattern: 'verify=False', api: `${receiver}.${method}` };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ssl._create_unverified_context()
|
|
124
|
+
if (method === '_create_unverified_context' && receiver === 'ssl') {
|
|
125
|
+
return { pattern: 'ssl._create_unverified_context', api: 'ssl._create_unverified_context()' };
|
|
126
|
+
}
|
|
127
|
+
// httpx.Client(verify=False) — same shape via constructor; receiver is module.
|
|
128
|
+
if (receiver === 'httpx' && method === 'Client') {
|
|
129
|
+
for (const arg of call.arguments) {
|
|
130
|
+
if (VERIFY_FALSE_RE.test(arg.expression ?? '')) {
|
|
131
|
+
return { pattern: 'verify=False', api: 'httpx.Client' };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if (language === 'javascript' || language === 'typescript') {
|
|
138
|
+
// axios.create({httpsAgent: new https.Agent({rejectUnauthorized: false})}),
|
|
139
|
+
// https.request({rejectUnauthorized: false}, ...), fetch(url, {agent: ...})
|
|
140
|
+
// We do an arg-expression text scan because the option commonly appears
|
|
141
|
+
// inside an inline object literal.
|
|
142
|
+
//
|
|
143
|
+
// The JS plugin sometimes surfaces `new https.Agent(...)` with
|
|
144
|
+
// method_name='https.Agent' and receiver=null (rather than receiver='https',
|
|
145
|
+
// method='Agent'). Accept the trailing segment of the dotted name too.
|
|
146
|
+
const lastSeg = method.includes('.') ? method.split('.').pop() ?? '' : method;
|
|
147
|
+
const arglooks = method === 'request' || method === 'get' || method === 'post' ||
|
|
148
|
+
method === 'create' || method === 'Agent' || method === 'fetch' ||
|
|
149
|
+
lastSeg === 'Agent' || lastSeg === 'request' || lastSeg === 'create';
|
|
150
|
+
if (arglooks) {
|
|
151
|
+
for (const arg of call.arguments) {
|
|
152
|
+
if (REJECT_UNAUTHORIZED_FALSE_RE.test(arg.expression ?? '')) {
|
|
153
|
+
return { pattern: 'rejectUnauthorized: false', api: `${receiver || '(global)'}.${method}` };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (language === 'java') {
|
|
160
|
+
// someConn.setHostnameVerifier((h, s) -> true)
|
|
161
|
+
if (method === 'setHostnameVerifier') {
|
|
162
|
+
const arg = call.arguments.find((a) => a.position === 0);
|
|
163
|
+
const expr = (arg?.expression ?? '').trim();
|
|
164
|
+
if (HOSTNAME_LAMBDA_TRUE_RE.test(expr)) {
|
|
165
|
+
return { pattern: '(h,s) -> true', api: 'setHostnameVerifier' };
|
|
166
|
+
}
|
|
167
|
+
for (const v of ALLOW_ALL_HOSTNAME_VERIFIERS) {
|
|
168
|
+
if (expr === v || expr.replace(/\s+/g, '') === v.replace(/\s+/g, '')) {
|
|
169
|
+
return { pattern: v, api: 'setHostnameVerifier' };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
detectSourceText(code, language) {
|
|
178
|
+
const out = [];
|
|
179
|
+
const lines = code.split('\n');
|
|
180
|
+
if (language === 'go') {
|
|
181
|
+
// Look for `InsecureSkipVerify: true` literal anywhere — overwhelmingly
|
|
182
|
+
// appears in tls.Config{} composite literals.
|
|
183
|
+
for (let i = 0; i < lines.length; i++) {
|
|
184
|
+
if (INSECURE_SKIP_VERIFY_TRUE_RE.test(lines[i])) {
|
|
185
|
+
out.push({
|
|
186
|
+
line: i + 1,
|
|
187
|
+
pattern: 'InsecureSkipVerify: true',
|
|
188
|
+
api: 'tls.Config',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (language === 'python') {
|
|
194
|
+
for (let i = 0; i < lines.length; i++) {
|
|
195
|
+
const l = lines[i];
|
|
196
|
+
if (/ssl\._create_default_https_context\s*=\s*ssl\._create_unverified_context/.test(l)) {
|
|
197
|
+
out.push({
|
|
198
|
+
line: i + 1,
|
|
199
|
+
pattern: 'ssl._create_default_https_context = _create_unverified_context',
|
|
200
|
+
api: 'ssl module override',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (language === 'javascript' || language === 'typescript') {
|
|
206
|
+
for (let i = 0; i < lines.length; i++) {
|
|
207
|
+
const l = lines[i];
|
|
208
|
+
if (/process\.env\.NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]0['"]/.test(l)) {
|
|
209
|
+
out.push({
|
|
210
|
+
line: i + 1,
|
|
211
|
+
pattern: 'NODE_TLS_REJECT_UNAUTHORIZED=0',
|
|
212
|
+
api: 'process.env',
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
fixFor(language, pattern) {
|
|
220
|
+
if (pattern.includes('InsecureSkipVerify')) {
|
|
221
|
+
return 'Remove `InsecureSkipVerify: true` — let Go verify the cert. If ' +
|
|
222
|
+
'you need to trust a private CA, set `RootCAs` to a `*x509.CertPool` ' +
|
|
223
|
+
'containing that CA.';
|
|
224
|
+
}
|
|
225
|
+
if (pattern.includes('verify=False')) {
|
|
226
|
+
return 'Remove `verify=False`. To trust a private CA, pass `verify=\'/path/to/ca.pem\'`.';
|
|
227
|
+
}
|
|
228
|
+
if (pattern.includes('rejectUnauthorized')) {
|
|
229
|
+
return 'Remove `rejectUnauthorized: false`. To trust a private CA, set the ' +
|
|
230
|
+
'`ca` option to the CA cert(s). Never disable TLS verification globally.';
|
|
231
|
+
}
|
|
232
|
+
if (pattern.includes('NODE_TLS_REJECT_UNAUTHORIZED')) {
|
|
233
|
+
return 'Remove the `NODE_TLS_REJECT_UNAUTHORIZED=0` assignment — it globally ' +
|
|
234
|
+
'disables TLS verification for every outbound HTTPS request.';
|
|
235
|
+
}
|
|
236
|
+
if (language === 'java') {
|
|
237
|
+
return 'Do not use an always-true HostnameVerifier or AllowAllHostnameVerifier. ' +
|
|
238
|
+
'Use the JVM\'s default verifier; for self-signed certs add the cert to a ' +
|
|
239
|
+
'custom TrustManager that validates the chain.';
|
|
240
|
+
}
|
|
241
|
+
if (pattern.includes('ssl._create_unverified_context')) {
|
|
242
|
+
return 'Do not use `_create_unverified_context()`. Use `ssl.create_default_context()`.';
|
|
243
|
+
}
|
|
244
|
+
return 'Restore TLS certificate and hostname verification.';
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=tls-verify-disabled-pass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls-verify-disabled-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/tls-verify-disabled-pass.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pass: weak-crypto (CWE-327 / CWE-329 / CWE-321 / CWE-326, category: security)
|
|
3
|
+
*
|
|
4
|
+
* Pattern pass — flags use of cryptographically weak symmetric ciphers
|
|
5
|
+
* (DES, 3DES, RC2, RC4, Blowfish), ECB mode, weak RSA key sizes (< 2048),
|
|
6
|
+
* static/zero IVs (CWE-329), hardcoded symmetric keys (CWE-321), and weak
|
|
7
|
+
* AES modes. Like weak-hash, the vulnerability is the *constant algorithm
|
|
8
|
+
* string*, *constant IV bytes*, *literal key material*, or *key-size
|
|
9
|
+
* argument*, not data flow.
|
|
10
|
+
*
|
|
11
|
+
* Detection per language:
|
|
12
|
+
* Java:
|
|
13
|
+
* - `Cipher.getInstance("DES"|"DES/...")` / `"RC4"` / `"RC2"` / `"Blowfish"`
|
|
14
|
+
* - `Cipher.getInstance(".../ECB/...")` — ECB mode
|
|
15
|
+
* - `KeyGenerator.getInstance("DES"|"RC4"|"Blowfish")`
|
|
16
|
+
* - `new IvParameterSpec(new byte[N])` / `new IvParameterSpec(literalBytes)`
|
|
17
|
+
* — static/zero IV (CWE-329, issue #87)
|
|
18
|
+
* - `new SecretKeySpec("literal".getBytes(), ...)` — hardcoded symmetric
|
|
19
|
+
* key (CWE-321, issue #87)
|
|
20
|
+
* - `KeyPairGenerator.initialize(<2048)` — weak RSA key size (CWE-326,
|
|
21
|
+
* issue #87). Detected by literal `< 2048` argument on `initialize`
|
|
22
|
+
* calls whose receiver is a `KeyPairGenerator` (best-effort: matches
|
|
23
|
+
* any `*.initialize(int)` where the literal is below 2048, since
|
|
24
|
+
* 2048+ is also the minimum for DSA / DH and 256+ is correct for EC).
|
|
25
|
+
* Python:
|
|
26
|
+
* - `Crypto.Cipher.DES.new(...)` / `Crypto.Cipher.ARC4.new(...)` /
|
|
27
|
+
* `Crypto.Cipher.Blowfish.new(...)` (pycryptodome / pycrypto)
|
|
28
|
+
* - `cryptography.hazmat.primitives.ciphers.algorithms.{TripleDES,Blowfish,ARC4,IDEA,SEED,CAST5}`
|
|
29
|
+
* - `AES.new(key, AES.MODE_ECB)` — ECB mode argument
|
|
30
|
+
* JavaScript / TypeScript:
|
|
31
|
+
* - `crypto.createCipher(...)` (deprecated; always weak)
|
|
32
|
+
* - `crypto.createCipheriv("des-..."|"rc4"|"bf-..."|"des-ede"|".*-ecb")`
|
|
33
|
+
* Go:
|
|
34
|
+
* - `des.NewCipher(...)` / `des.NewTripleDESCipher(...)` / `rc4.NewCipher(...)`
|
|
35
|
+
* (from `crypto/des` and `crypto/rc4`)
|
|
36
|
+
* - `cipher.NewECBEncrypter(...)` (custom ECB wrappers — best-effort)
|
|
37
|
+
*
|
|
38
|
+
* Aligned with: gosec G401/G405, Bandit B304/B305/B306, OWASP Benchmark `crypto` category.
|
|
39
|
+
*/
|
|
40
|
+
import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js';
|
|
41
|
+
export type WeakCryptoIssue = 'weak-cipher' | 'ecb-mode' | 'deprecated-api' | 'static-iv' | 'hardcoded-key' | 'weak-rsa-key';
|
|
42
|
+
export interface WeakCryptoResult {
|
|
43
|
+
findings: Array<{
|
|
44
|
+
line: number;
|
|
45
|
+
language: string;
|
|
46
|
+
issue: WeakCryptoIssue;
|
|
47
|
+
detail: string;
|
|
48
|
+
api: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
export declare class WeakCryptoPass implements AnalysisPass<WeakCryptoResult> {
|
|
52
|
+
readonly name = "weak-crypto";
|
|
53
|
+
readonly category: "security";
|
|
54
|
+
run(ctx: PassContext): WeakCryptoResult;
|
|
55
|
+
private buildMessage;
|
|
56
|
+
private buildFix;
|
|
57
|
+
private detect;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=weak-crypto-pass.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weak-crypto-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/weak-crypto-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAkI9E,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,UAAU,GACV,gBAAgB,GAChB,WAAW,GACX,eAAe,GACf,cAAc,CAAC;AAYnB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,eAAe,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;CACJ;AAED,qBAAa,cAAe,YAAW,YAAY,CAAC,gBAAgB,CAAC;IACnE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,gBAAgB;IAgCvC,OAAO,CAAC,YAAY;IA0CpB,OAAO,CAAC,QAAQ;IA2BhB,OAAO,CAAC,MAAM;CAqJf"}
|