@xenos1996/usat 1.2.0 → 1.3.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/dist/bootstrap/catalog.d.ts +41 -0
- package/dist/bootstrap/catalog.d.ts.map +1 -0
- package/dist/bootstrap/catalog.js +366 -0
- package/dist/bootstrap/catalog.js.map +1 -0
- package/dist/bootstrap/index.d.ts +36 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +174 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +49 -0
- package/dist/cli.js.map +1 -1
- package/dist/engine/audit.d.ts.map +1 -1
- package/dist/engine/audit.js +18 -1
- package/dist/engine/audit.js.map +1 -1
- package/dist/util/project.d.ts +10 -0
- package/dist/util/project.d.ts.map +1 -1
- package/dist/util/project.js +19 -4
- package/dist/util/project.js.map +1 -1
- package/docs/adr/0012-self-extension-via-bootstrap.md +56 -0
- package/docs/adr/README.md +14 -13
- package/docs/configuration.md +14 -0
- package/docs/reference/cli.md +5 -0
- package/docs/rule-packs.md +17 -0
- package/package.json +1 -1
- package/rules/core/security.yaml +3 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { RuleClass, Severity } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Bootstrap knowledge: starter checks for languages USAT detects but ships
|
|
4
|
+
* no stack pack for. Every entry is a *proposal*, never a verdict — the
|
|
5
|
+
* generator emits packs for human review, and nothing it writes is
|
|
6
|
+
* registered or trusted until reviewed (see ADR-0012).
|
|
7
|
+
*
|
|
8
|
+
* Curation bar for inclusion here: the pattern must be dangerous wherever
|
|
9
|
+
* it appears (not merely smelly), with a false-positive rate low enough
|
|
10
|
+
* that a first run does not teach the user to ignore the tool. Presence
|
|
11
|
+
* checks ("is X used?") are excluded on purpose — without applicability
|
|
12
|
+
* facts they punish projects that simply have no passwords/sessions.
|
|
13
|
+
*/
|
|
14
|
+
export interface BootstrapCheck {
|
|
15
|
+
id: string;
|
|
16
|
+
title: string;
|
|
17
|
+
severity: Severity;
|
|
18
|
+
ruleClass: RuleClass;
|
|
19
|
+
kind: 'grep_wrong' | 'grep_absent' | 'grep_present' | 'grep_deprecated' | 'file_exists' | 'manual';
|
|
20
|
+
pattern?: string;
|
|
21
|
+
include?: string[];
|
|
22
|
+
exclude?: string[];
|
|
23
|
+
files?: string[];
|
|
24
|
+
why: string;
|
|
25
|
+
remediation: string;
|
|
26
|
+
evidence?: string;
|
|
27
|
+
references?: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface BootstrapLang {
|
|
30
|
+
/** e.g. 'php' — matches the `lang:` fact suffix. */
|
|
31
|
+
lang: string;
|
|
32
|
+
/** e.g. 'stacks/php' — the pack id the generated file will carry. */
|
|
33
|
+
packId: string;
|
|
34
|
+
title: string;
|
|
35
|
+
description: string;
|
|
36
|
+
/** Framework facts worth adding detectors for next (printed, not applied). */
|
|
37
|
+
frameworkHints: string[];
|
|
38
|
+
checks: BootstrapCheck[];
|
|
39
|
+
}
|
|
40
|
+
export declare const BOOTSTRAP_CATALOG: BootstrapLang[];
|
|
41
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/bootstrap/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvD;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EACF,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,iBAAiB,GAAG,aAAa,GAAG,QAAQ,CAAC;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAID,eAAO,MAAM,iBAAiB,EAAE,aAAa,EAuY5C,CAAC"}
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
const TEST_EXCLUDES = ['**/*.test.*', '**/*.spec.*', '**/test/**', '**/tests/**'];
|
|
2
|
+
export const BOOTSTRAP_CATALOG = [
|
|
3
|
+
{
|
|
4
|
+
lang: 'php',
|
|
5
|
+
packId: 'stacks/php',
|
|
6
|
+
title: 'PHP',
|
|
7
|
+
description: 'Starter checks for PHP projects. Generated — review every pattern before trusting.',
|
|
8
|
+
frameworkHints: [
|
|
9
|
+
'laravel (composer.json: laravel/framework), symfony (symfony/http-kernel), wordpress (wp-load.php)',
|
|
10
|
+
],
|
|
11
|
+
checks: [
|
|
12
|
+
{
|
|
13
|
+
id: 'PHP-001',
|
|
14
|
+
title: 'No dynamic code execution',
|
|
15
|
+
severity: 'HIGH',
|
|
16
|
+
ruleClass: 'security',
|
|
17
|
+
kind: 'grep_wrong',
|
|
18
|
+
pattern: '(eval\\s*\\(|assert\\s*\\(\\s*["\']|create_function\\s*\\()',
|
|
19
|
+
include: ['**/*.php'],
|
|
20
|
+
exclude: [...TEST_EXCLUDES],
|
|
21
|
+
why: 'eval() and string assert() execute arbitrary code; create_function() is removed in PHP 8 and fatal when called.',
|
|
22
|
+
remediation: 'Use closures or a dispatch table instead of eval; replace create_function with anonymous functions.',
|
|
23
|
+
references: ['CWE-95'],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 'PHP-002',
|
|
27
|
+
title: 'No shell execution from application code',
|
|
28
|
+
severity: 'HIGH',
|
|
29
|
+
ruleClass: 'security',
|
|
30
|
+
kind: 'grep_wrong',
|
|
31
|
+
pattern: '(shell_exec\\s*\\(|passthru\\s*\\(|popen\\s*\\(|proc_open\\s*\\()',
|
|
32
|
+
include: ['**/*.php'],
|
|
33
|
+
exclude: [...TEST_EXCLUDES],
|
|
34
|
+
why: 'Shelling out with composed strings is command injection waiting for input.',
|
|
35
|
+
remediation: 'Use PHP-native APIs (filesystem, process control with argument arrays). If unavoidable, escapeshellarg every argument.',
|
|
36
|
+
references: ['CWE-78'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'PHP-003',
|
|
40
|
+
title: 'No unsafe unserialize()',
|
|
41
|
+
severity: 'HIGH',
|
|
42
|
+
ruleClass: 'security',
|
|
43
|
+
kind: 'grep_wrong',
|
|
44
|
+
pattern: 'unserialize\\s*\\(',
|
|
45
|
+
include: ['**/*.php'],
|
|
46
|
+
exclude: [...TEST_EXCLUDES],
|
|
47
|
+
why: 'unserialize() on untrusted data is PHP object injection. Verify the source is never user-controlled.',
|
|
48
|
+
remediation: 'Prefer json_decode with assoc arrays; pass allowed_classes: false where unserialize is unavoidable.',
|
|
49
|
+
references: ['CWE-502'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'PHP-004',
|
|
53
|
+
title: 'No extract() over superglobals',
|
|
54
|
+
severity: 'HIGH',
|
|
55
|
+
ruleClass: 'security',
|
|
56
|
+
kind: 'grep_wrong',
|
|
57
|
+
pattern: 'extract\\s*\\(\\s*\\$_(GET|POST|REQUEST|COOKIE)',
|
|
58
|
+
include: ['**/*.php'],
|
|
59
|
+
exclude: [...TEST_EXCLUDES],
|
|
60
|
+
why: 'extract() over request data lets callers overwrite any in-scope variable, including guards.',
|
|
61
|
+
remediation: 'Read explicit keys from the superglobal instead of importing the whole array.',
|
|
62
|
+
references: ['CWE-915'],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'PHP-005',
|
|
66
|
+
title: 'Dependencies are locked',
|
|
67
|
+
severity: 'MEDIUM',
|
|
68
|
+
ruleClass: 'supply-chain',
|
|
69
|
+
kind: 'file_exists',
|
|
70
|
+
files: ['composer.lock'],
|
|
71
|
+
why: 'An unlocked composer.json installs whatever is newest at deploy time — unreviewed code in production.',
|
|
72
|
+
remediation: 'Commit composer.lock and install with --no-dev --optimize-autoloader in CI.',
|
|
73
|
+
references: ['CWE-829'],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'PHP-006',
|
|
77
|
+
title: 'Authentication and session handling reviewed',
|
|
78
|
+
severity: 'HIGH',
|
|
79
|
+
ruleClass: 'security',
|
|
80
|
+
kind: 'manual',
|
|
81
|
+
why: 'No pattern can confirm passwords are hashed, sessions rotate, and cookies are HttpOnly + Secure + SameSite.',
|
|
82
|
+
remediation: 'Verify password_hash/password_verify, session_regenerate_id on login, and cookie flags.',
|
|
83
|
+
evidence: 'Login handler file:line, hashing call, session cookie attributes.',
|
|
84
|
+
references: ['ASVS-2.4.1', 'ASVS-3.2.2'],
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
lang: 'ruby',
|
|
90
|
+
packId: 'stacks/ruby',
|
|
91
|
+
title: 'Ruby',
|
|
92
|
+
description: 'Starter checks for Ruby projects. Generated — review every pattern before trusting.',
|
|
93
|
+
frameworkHints: ['rails (Gemfile: rails, config/application.rb)', 'sinatra (sinatra gem)'],
|
|
94
|
+
checks: [
|
|
95
|
+
{
|
|
96
|
+
id: 'RB-001',
|
|
97
|
+
title: 'No dynamic code or shell execution',
|
|
98
|
+
severity: 'HIGH',
|
|
99
|
+
ruleClass: 'security',
|
|
100
|
+
kind: 'grep_wrong',
|
|
101
|
+
pattern: '(`|eval\\s*\\(|exec\\s*\\(|system\\s*\\()',
|
|
102
|
+
include: ['**/*.rb'],
|
|
103
|
+
exclude: [...TEST_EXCLUDES],
|
|
104
|
+
why: 'Backticks, eval, exec, and system with composed strings are code and command injection.',
|
|
105
|
+
remediation: 'Use Open3 with argument arrays; replace eval with data-driven dispatch.',
|
|
106
|
+
references: ['CWE-95', 'CWE-78'],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: 'RB-002',
|
|
110
|
+
title: 'No unsafe deserialization',
|
|
111
|
+
severity: 'HIGH',
|
|
112
|
+
ruleClass: 'security',
|
|
113
|
+
kind: 'grep_wrong',
|
|
114
|
+
pattern: '(YAML\\.load\\s*\\(|Marshal\\.load\\s*\\(|Oj\\.load\\s*\\()',
|
|
115
|
+
include: ['**/*.rb'],
|
|
116
|
+
exclude: [...TEST_EXCLUDES],
|
|
117
|
+
why: 'YAML.load/Marshal.load instantiate arbitraryRuby objects. Verify trusted source or switch to safe_load with permitted classes.',
|
|
118
|
+
remediation: 'Use YAML.safe_load (allowlisted classes) and Oj.strict / Oj.safe modes.',
|
|
119
|
+
references: ['CWE-502'],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'RB-003',
|
|
123
|
+
title: 'No interpolated SQL',
|
|
124
|
+
severity: 'HIGH',
|
|
125
|
+
ruleClass: 'security',
|
|
126
|
+
kind: 'grep_wrong',
|
|
127
|
+
pattern: '(execute\\s*\\(.*#\\{|find_by_sql\\s*\\(.*#\\{|where\\s*\\(["\'].*#\\{)',
|
|
128
|
+
include: ['**/*.rb'],
|
|
129
|
+
exclude: [...TEST_EXCLUDES, '**/db/migrate/**', '**/db/schema.rb'],
|
|
130
|
+
why: '#{} inside a SQL string interpolates before the driver sees it — parameterisation never happens.',
|
|
131
|
+
remediation: 'Use bound parameters (where(id: x), exec_query with binds) or sanitized arrays.',
|
|
132
|
+
references: ['CWE-89'],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'RB-004',
|
|
136
|
+
title: 'Dependencies are locked',
|
|
137
|
+
severity: 'MEDIUM',
|
|
138
|
+
ruleClass: 'supply-chain',
|
|
139
|
+
kind: 'file_exists',
|
|
140
|
+
files: ['Gemfile.lock'],
|
|
141
|
+
why: 'An unlocked Gemfile installs whatever is newest at deploy time.',
|
|
142
|
+
remediation: 'Commit Gemfile.lock and install with --deployment --without development test in CI.',
|
|
143
|
+
references: ['CWE-829'],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'RB-005',
|
|
147
|
+
title: 'Mass assignment and auth reviewed',
|
|
148
|
+
severity: 'HIGH',
|
|
149
|
+
ruleClass: 'security',
|
|
150
|
+
kind: 'manual',
|
|
151
|
+
why: 'Strong parameters, auth scoping, and CSRF coverage cannot be confirmed by grep.',
|
|
152
|
+
remediation: 'Verify permit() lists, before_action scoping, and protect_from_forgery on state-changing endpoints.',
|
|
153
|
+
evidence: 'Controller file:line of the permit list, auth filter, and CSRF configuration.',
|
|
154
|
+
references: ['ASVS-4.2.1', 'ASVS-5.1.2'],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
lang: 'cpp',
|
|
160
|
+
packId: 'stacks/cpp',
|
|
161
|
+
title: 'C / C++',
|
|
162
|
+
description: 'Starter checks for C and C++ projects. Generated — review every pattern before trusting.',
|
|
163
|
+
frameworkHints: [
|
|
164
|
+
'cmake (CMakeLists.txt), meson (meson.build), bazel (BUILD/WORKSPACE), autotools (configure.ac)',
|
|
165
|
+
],
|
|
166
|
+
checks: [
|
|
167
|
+
{
|
|
168
|
+
id: 'CPP-001',
|
|
169
|
+
title: 'No banned string/memory functions',
|
|
170
|
+
severity: 'HIGH',
|
|
171
|
+
ruleClass: 'security',
|
|
172
|
+
kind: 'grep_wrong',
|
|
173
|
+
pattern: '\\b(strcpy|strcat|sprintf|gets)\\s*\\(',
|
|
174
|
+
include: ['**/*.{c,h,cc,cpp,cxx,hpp}'],
|
|
175
|
+
exclude: [...TEST_EXCLUDES],
|
|
176
|
+
why: 'Unbounded copies into fixed buffers are the classic overflow primitive; gets() cannot be used safely at all.',
|
|
177
|
+
remediation: 'Use strncpy/strncat/snprintf (C) or std::string/absl/span (C++); delete every gets call.',
|
|
178
|
+
references: ['CWE-120', 'CWE-787'],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: 'CPP-002',
|
|
182
|
+
title: 'No shell execution from application code',
|
|
183
|
+
severity: 'HIGH',
|
|
184
|
+
ruleClass: 'security',
|
|
185
|
+
kind: 'grep_wrong',
|
|
186
|
+
pattern: '\\b(system|popen)\\s*\\(',
|
|
187
|
+
include: ['**/*.{c,h,cc,cpp,cxx,hpp}'],
|
|
188
|
+
exclude: [...TEST_EXCLUDES],
|
|
189
|
+
why: 'system()/popen() invoke a shell; composed commands are command injection.',
|
|
190
|
+
remediation: 'Use exec-family calls with argument vectors (fork+execve, posix_spawn) and no shell.',
|
|
191
|
+
references: ['CWE-78'],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: 'CPP-003',
|
|
195
|
+
title: 'No unbounded scanf input',
|
|
196
|
+
severity: 'MEDIUM',
|
|
197
|
+
ruleClass: 'security',
|
|
198
|
+
kind: 'grep_wrong',
|
|
199
|
+
pattern: 'scanf\\s*\\(\\s*"%s"',
|
|
200
|
+
include: ['**/*.{c,h,cc,cpp,cxx,hpp}'],
|
|
201
|
+
exclude: [...TEST_EXCLUDES],
|
|
202
|
+
why: 'scanf("%s") writes unbounded input into the target buffer.',
|
|
203
|
+
remediation: 'Give every %s a field width ("%255s") or read lines with getline/fgets and parse.',
|
|
204
|
+
references: ['CWE-120'],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: 'CPP-004',
|
|
208
|
+
title: 'Build is described in a manifest',
|
|
209
|
+
severity: 'MEDIUM',
|
|
210
|
+
ruleClass: 'operations',
|
|
211
|
+
kind: 'file_exists',
|
|
212
|
+
files: [
|
|
213
|
+
'CMakeLists.txt',
|
|
214
|
+
'Makefile',
|
|
215
|
+
'meson.build',
|
|
216
|
+
'configure.ac',
|
|
217
|
+
'BUILD',
|
|
218
|
+
'BUILD.bazel',
|
|
219
|
+
],
|
|
220
|
+
why: 'An undocumented build means flags, defines, and warnings differ per machine.',
|
|
221
|
+
remediation: 'Check in a manifest with warnings enabled (-Wall -Wextra -Werror where feasible) and sanitizer presets.',
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
id: 'CPP-005',
|
|
225
|
+
title: 'Memory ownership reviewed',
|
|
226
|
+
severity: 'HIGH',
|
|
227
|
+
ruleClass: 'security',
|
|
228
|
+
kind: 'manual',
|
|
229
|
+
why: 'Use-after-free, double-free, and lifetime escapes need ownership reasoning no pattern provides.',
|
|
230
|
+
remediation: 'Prefer RAII/smart pointers; document ownership at every raw new/malloc boundary; run ASan+UBSan in CI.',
|
|
231
|
+
evidence: 'Ownership notes for new modules, sanitizer CI job, suppression-free sanitizer log.',
|
|
232
|
+
references: ['CWE-416', 'CWE-415'],
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
lang: 'csharp',
|
|
238
|
+
packId: 'stacks/csharp',
|
|
239
|
+
title: 'C# / .NET',
|
|
240
|
+
description: 'Starter checks for C# projects. Generated — review every pattern before trusting.',
|
|
241
|
+
frameworkHints: [
|
|
242
|
+
'aspnet (*.csproj referencing Microsoft.AspNetCore), efcore (EntityFrameworkCore)',
|
|
243
|
+
],
|
|
244
|
+
checks: [
|
|
245
|
+
{
|
|
246
|
+
id: 'CS-001',
|
|
247
|
+
title: 'No insecure deserializers',
|
|
248
|
+
severity: 'HIGH',
|
|
249
|
+
ruleClass: 'security',
|
|
250
|
+
kind: 'grep_deprecated',
|
|
251
|
+
pattern: '(BinaryFormatter|LosFormatter|ObjectStateFormatter|SoapFormatter)',
|
|
252
|
+
include: ['**/*.cs'],
|
|
253
|
+
exclude: [...TEST_EXCLUDES],
|
|
254
|
+
why: 'These deserializers execute attacker-controlled type graphs on.NET Framework and are discouraged everywhere.',
|
|
255
|
+
remediation: 'Use System.Text.Json or XmlSerializer with a restricted reader; treat any BinaryFormatter hit as a finding.',
|
|
256
|
+
references: ['CWE-502'],
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: 'CS-002',
|
|
260
|
+
title: 'No concatenated process arguments',
|
|
261
|
+
severity: 'HIGH',
|
|
262
|
+
ruleClass: 'security',
|
|
263
|
+
kind: 'grep_wrong',
|
|
264
|
+
pattern: 'Process\\.Start\\s*\\([^)]*\\+',
|
|
265
|
+
include: ['**/*.cs'],
|
|
266
|
+
exclude: [...TEST_EXCLUDES],
|
|
267
|
+
why: 'A Process.Start argument string built with + passes through shell parsing on part of the input.',
|
|
268
|
+
remediation: 'Set ProcessStartInfo.ArgumentList entries individually with UseShellExecute = false.',
|
|
269
|
+
references: ['CWE-78'],
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
id: 'CS-003',
|
|
273
|
+
title: 'Dependencies are locked',
|
|
274
|
+
severity: 'MEDIUM',
|
|
275
|
+
ruleClass: 'supply-chain',
|
|
276
|
+
kind: 'file_exists',
|
|
277
|
+
files: ['packages.lock.json'],
|
|
278
|
+
why: 'Without lock files, restores float to newest compatible packages at build time.',
|
|
279
|
+
remediation: 'Enable lock files (RestorePackagesWithLockFile / Continuous) and commit them.',
|
|
280
|
+
references: ['CWE-829'],
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: 'CS-004',
|
|
284
|
+
title: 'Hash algorithm choices inventoried',
|
|
285
|
+
severity: 'MEDIUM',
|
|
286
|
+
ruleClass: 'security',
|
|
287
|
+
kind: 'manual',
|
|
288
|
+
why: 'MD5/SHA1 appear legitimately for checksums and illegitimately for passwords — only a human can classify each use.',
|
|
289
|
+
remediation: 'List every hash call site; passwords go to PBKDF2/bcrypt/Argon2 via ASP.NET Identity or equivalent.',
|
|
290
|
+
evidence: 'File:line per hash use with password-vs-checksum classification.',
|
|
291
|
+
references: ['CWE-327', 'CWE-916'],
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
id: 'CS-005',
|
|
295
|
+
title: 'Authorization reviewed per endpoint',
|
|
296
|
+
severity: 'HIGH',
|
|
297
|
+
ruleClass: 'security',
|
|
298
|
+
kind: 'manual',
|
|
299
|
+
why: '[Authorize] placement and policy names cannot be verified by pattern.',
|
|
300
|
+
remediation: 'Default-deny with FallbackPolicy or explicit [Authorize] everywhere; verify resource-level checks, not just authentication.',
|
|
301
|
+
evidence: 'Fallback policy or endpoint audit file:line, plus one ownership check.',
|
|
302
|
+
references: ['ASVS-4.2.1'],
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
lang: 'swift',
|
|
308
|
+
packId: 'stacks/swift',
|
|
309
|
+
title: 'Swift',
|
|
310
|
+
description: 'Starter checks for Swift projects. Generated — review every pattern before trusting.',
|
|
311
|
+
frameworkHints: [
|
|
312
|
+
'vapor (Package.swift: .package(url: ...vapor...)), swiftui (import SwiftUI), combine',
|
|
313
|
+
],
|
|
314
|
+
checks: [
|
|
315
|
+
{
|
|
316
|
+
id: 'SW-001',
|
|
317
|
+
title: 'No force-unwrap or force-try in application code',
|
|
318
|
+
severity: 'MEDIUM',
|
|
319
|
+
ruleClass: 'correctness',
|
|
320
|
+
kind: 'grep_wrong',
|
|
321
|
+
pattern: '(try!\\s|as!\\s)',
|
|
322
|
+
include: ['**/*.swift'],
|
|
323
|
+
exclude: [...TEST_EXCLUDES],
|
|
324
|
+
why: 'try!/as! turn recoverable failures into crashes. Tests may keep them; shipped code should not.',
|
|
325
|
+
remediation: 'Handle errors with do/catch or propagate with try; replace as! with as? plus a guard.',
|
|
326
|
+
references: ['CWE-754'],
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: 'SW-002',
|
|
330
|
+
title: 'App Transport Security is not disabled',
|
|
331
|
+
severity: 'HIGH',
|
|
332
|
+
ruleClass: 'security',
|
|
333
|
+
kind: 'grep_wrong',
|
|
334
|
+
pattern: '(NSAllowsArbitraryLoads|NSExceptionAllowsInsecureHTTPLoads)',
|
|
335
|
+
include: ['**/*.plist', '**/*.swift'],
|
|
336
|
+
exclude: [...TEST_EXCLUDES],
|
|
337
|
+
why: 'Disabling ATS reopens plaintext HTTP for the whole app or exception domains.',
|
|
338
|
+
remediation: 'Remove the exception keys; pin exception domains narrowly with justification if truly required.',
|
|
339
|
+
references: ['CWE-319'],
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
id: 'SW-003',
|
|
343
|
+
title: 'Dependencies are pinned',
|
|
344
|
+
severity: 'MEDIUM',
|
|
345
|
+
ruleClass: 'supply-chain',
|
|
346
|
+
kind: 'file_exists',
|
|
347
|
+
files: ['Package.resolved'],
|
|
348
|
+
why: 'An unpinned Package.swift resolves newest compatibles at build time.',
|
|
349
|
+
remediation: 'Commit Package.resolved so every build resolves identically.',
|
|
350
|
+
references: ['CWE-829'],
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
id: 'SW-004',
|
|
354
|
+
title: 'Secrets live in the Keychain with data protection',
|
|
355
|
+
severity: 'HIGH',
|
|
356
|
+
ruleClass: 'security',
|
|
357
|
+
kind: 'manual',
|
|
358
|
+
why: 'UserDefaults/plist storage of tokens and missing file-protection classes need a human to confirm.',
|
|
359
|
+
remediation: 'Store credentials via SecItem with kSecAttrAccessibleWhenUnlockedThisDeviceOnly or stronger; set NSFileProtectionComplete.',
|
|
360
|
+
evidence: 'SecItem call sites file:line, UserDefaults keys inventory, file-protection settings.',
|
|
361
|
+
references: ['ASVS-2.10.1', 'MASVS-STORAGE'],
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
},
|
|
365
|
+
];
|
|
366
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/bootstrap/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Facts } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Self-extension: USAT auditing stacks it ships no pack for.
|
|
4
|
+
*
|
|
5
|
+
* Detection already names the language (`lang:php`); what is missing is the
|
|
6
|
+
* *rules*. `bootstrapPacks` turns that gap into a starter pack per
|
|
7
|
+
* uncovered language: curated high-signal checks from the catalog, or a
|
|
8
|
+
* clearly-marked generic fallback when the language is unknown even here.
|
|
9
|
+
*
|
|
10
|
+
* Fail-closed by design (see ADR-0012):
|
|
11
|
+
* - Nothing is registered in `rules/index.yaml` automatically.
|
|
12
|
+
* - Every emitted file carries a REVIEW-REQUIRED header.
|
|
13
|
+
* - The CLI prints; it only writes with an explicit `--out`.
|
|
14
|
+
*/
|
|
15
|
+
export interface BootstrapPack {
|
|
16
|
+
/** e.g. 'stacks/php' — the id the file will carry. */
|
|
17
|
+
packId: string;
|
|
18
|
+
/** e.g. 'stacks/php.yaml' — relative filename for `--out <dir>`. */
|
|
19
|
+
filename: string;
|
|
20
|
+
yaml: string;
|
|
21
|
+
}
|
|
22
|
+
export interface BootstrapOutcome {
|
|
23
|
+
packs: BootstrapPack[];
|
|
24
|
+
/** Languages already covered by a shipped pack (nothing to do). */
|
|
25
|
+
coveredLangs: string[];
|
|
26
|
+
/** Languages generated from curated catalog entries. */
|
|
27
|
+
generatedLangs: string[];
|
|
28
|
+
/** Languages generated from the generic fallback (extra review needed). */
|
|
29
|
+
fallbackLangs: string[];
|
|
30
|
+
/** Human next-steps, printed after the packs. */
|
|
31
|
+
notes: string[];
|
|
32
|
+
}
|
|
33
|
+
export declare function bootstrapPacks(facts: Facts): BootstrapOutcome;
|
|
34
|
+
/** Write generated packs: `--out <dir>` for any count, `--out <file>` for one. */
|
|
35
|
+
export declare function writeBootstrapPacks(outcome: BootstrapOutcome, out: string): void;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,mEAAmE;IACnE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,wDAAwD;IACxD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2EAA2E;IAC3E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iDAAiD;IACjD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAeD,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAuB7D;AAuID,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAehF"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { stringify as stringifyYaml } from 'yaml';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { BOOTSTRAP_CATALOG } from './catalog.js';
|
|
5
|
+
/** Detected languages with a shipped stack pack — no bootstrap needed. */
|
|
6
|
+
const COVERED_LANGS = {
|
|
7
|
+
typescript: 'stacks/node-typescript',
|
|
8
|
+
javascript: 'stacks/node-typescript',
|
|
9
|
+
python: 'stacks/python',
|
|
10
|
+
go: 'stacks/go',
|
|
11
|
+
rust: 'stacks/rust',
|
|
12
|
+
java: 'stacks/jvm',
|
|
13
|
+
kotlin: 'stacks/jvm',
|
|
14
|
+
scala: 'stacks/jvm',
|
|
15
|
+
solidity: 'stacks/solidity',
|
|
16
|
+
};
|
|
17
|
+
export function bootstrapPacks(facts) {
|
|
18
|
+
const langs = [...facts.flags]
|
|
19
|
+
.filter((f) => f.startsWith('lang:'))
|
|
20
|
+
.map((f) => f.slice('lang:'.length))
|
|
21
|
+
.sort();
|
|
22
|
+
const outcome = {
|
|
23
|
+
packs: [],
|
|
24
|
+
coveredLangs: [],
|
|
25
|
+
generatedLangs: [],
|
|
26
|
+
fallbackLangs: [],
|
|
27
|
+
notes: [],
|
|
28
|
+
};
|
|
29
|
+
for (const lang of langs) {
|
|
30
|
+
if (COVERED_LANGS[lang]) {
|
|
31
|
+
outcome.coveredLangs.push(lang);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const entry = BOOTSTRAP_CATALOG.find((e) => e.lang === lang);
|
|
35
|
+
outcome.packs.push(entry ? renderCatalogPack(entry) : renderFallbackPack(lang));
|
|
36
|
+
(entry ? outcome.generatedLangs : outcome.fallbackLangs).push(lang);
|
|
37
|
+
}
|
|
38
|
+
outcome.notes = buildNotes(outcome);
|
|
39
|
+
return outcome;
|
|
40
|
+
}
|
|
41
|
+
const REVIEW_HEADER = `# =============================================================================
|
|
42
|
+
# GENERATED by \`usat bootstrap\` — REVIEW REQUIRED before use.
|
|
43
|
+
# This pack is a starting proposal, not an audit verdict. Before trusting it:
|
|
44
|
+
# 1. Read every pattern. Delete any that misfires on your codebase.
|
|
45
|
+
# 2. Audit one project WITH the problem and one WITHOUT it (see
|
|
46
|
+
# CONTRIBUTING.md "Testing a rule"); both runs must behave.
|
|
47
|
+
# 3. Add FP/FN regression tests to tests/rules.test.ts.
|
|
48
|
+
# 4. Register the reviewed file in rules/index.yaml.
|
|
49
|
+
# Until then it stays out of the index and out of every score.
|
|
50
|
+
# =============================================================================
|
|
51
|
+
`;
|
|
52
|
+
function renderCatalogPack(entry) {
|
|
53
|
+
const doc = {
|
|
54
|
+
id: entry.packId,
|
|
55
|
+
title: entry.title,
|
|
56
|
+
section: 'S15',
|
|
57
|
+
section_title: 'Platform-Specific',
|
|
58
|
+
description: `${entry.description} (bootstrap v0.1 — unreviewed)`,
|
|
59
|
+
version: '0.1.0-bootstrap',
|
|
60
|
+
skip_when: { all: [{ fact: `lang:${entry.lang}`, op: 'absent' }] },
|
|
61
|
+
rules: entry.checks.map(renderCheck),
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
packId: entry.packId,
|
|
65
|
+
filename: `${entry.packId}.yaml`,
|
|
66
|
+
yaml: `${REVIEW_HEADER}${stringifyYaml(doc)}`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Last resort for languages with no curated knowledge: judgement prompts. */
|
|
70
|
+
function renderFallbackPack(lang) {
|
|
71
|
+
const prefix = lang.slice(0, 3).toUpperCase();
|
|
72
|
+
const packId = `stacks/${lang}`;
|
|
73
|
+
const doc = {
|
|
74
|
+
id: packId,
|
|
75
|
+
title: lang,
|
|
76
|
+
section: 'S15',
|
|
77
|
+
section_title: 'Platform-Specific',
|
|
78
|
+
description: `Fallback prompts for ${lang} — USAT has no curated checks for this language yet. Human review carries this pack. (bootstrap v0.1 — unreviewed)`,
|
|
79
|
+
version: '0.1.0-bootstrap',
|
|
80
|
+
skip_when: { all: [{ fact: `lang:${lang}`, op: 'absent' }] },
|
|
81
|
+
rules: [
|
|
82
|
+
{
|
|
83
|
+
id: `${prefix}-001`,
|
|
84
|
+
title: 'Security-sensitive operations reviewed',
|
|
85
|
+
section: 'S15',
|
|
86
|
+
section_title: 'Platform-Specific',
|
|
87
|
+
severity: 'HIGH',
|
|
88
|
+
class: 'security',
|
|
89
|
+
check: { kind: 'manual' },
|
|
90
|
+
why: `No automated ${lang} checks exist yet; dangerous operations need human review.`,
|
|
91
|
+
remediation: `Review ${lang} entry points for injection, auth gaps, and secret handling.`,
|
|
92
|
+
evidence: `File:line of each reviewed sink plus the verdict.`,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: `${prefix}-002`,
|
|
96
|
+
title: 'Dependencies and build reviewed',
|
|
97
|
+
section: 'S15',
|
|
98
|
+
section_title: 'Platform-Specific',
|
|
99
|
+
severity: 'MEDIUM',
|
|
100
|
+
class: 'supply-chain',
|
|
101
|
+
check: { kind: 'manual' },
|
|
102
|
+
why: `Dependency pinning and build provenance for ${lang} are unverified.`,
|
|
103
|
+
remediation: 'Pin and lock dependencies; verify the lockfile is committed.',
|
|
104
|
+
evidence: 'Lockfile path, or the decision that none applies.',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
return { packId, filename: `${packId}.yaml`, yaml: `${REVIEW_HEADER}${stringifyYaml(doc)}` };
|
|
109
|
+
}
|
|
110
|
+
const BOOTSTRAP_CHECK_BUILDERS = {
|
|
111
|
+
grep_wrong: (c) => grepCheck('grep_wrong', c),
|
|
112
|
+
grep_absent: (c) => grepCheck('grep_absent', c),
|
|
113
|
+
grep_present: (c) => grepCheck('grep_present', c),
|
|
114
|
+
grep_deprecated: (c) => grepCheck('grep_deprecated', c),
|
|
115
|
+
file_exists: (c) => ({ kind: 'file_exists', files: c.files ?? [] }),
|
|
116
|
+
manual: () => ({ kind: 'manual' }),
|
|
117
|
+
};
|
|
118
|
+
function grepCheck(kind, c) {
|
|
119
|
+
return {
|
|
120
|
+
kind,
|
|
121
|
+
pattern: c.pattern ?? '',
|
|
122
|
+
include: c.include ?? [],
|
|
123
|
+
...(c.exclude ? { exclude: c.exclude } : {}),
|
|
124
|
+
flags: 'i',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function renderCheck(c) {
|
|
128
|
+
return {
|
|
129
|
+
id: c.id,
|
|
130
|
+
title: c.title,
|
|
131
|
+
section: 'S15',
|
|
132
|
+
section_title: 'Platform-Specific',
|
|
133
|
+
severity: c.severity,
|
|
134
|
+
class: c.ruleClass,
|
|
135
|
+
check: BOOTSTRAP_CHECK_BUILDERS[c.kind](c),
|
|
136
|
+
why: c.why,
|
|
137
|
+
remediation: c.remediation,
|
|
138
|
+
...(c.evidence ? { evidence: c.evidence } : {}),
|
|
139
|
+
...(c.references ? { references: c.references } : {}),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function buildNotes(outcome) {
|
|
143
|
+
const notes = [];
|
|
144
|
+
if (outcome.coveredLangs.length > 0) {
|
|
145
|
+
notes.push(`already covered (no action): ${outcome.coveredLangs.join(', ')}`);
|
|
146
|
+
}
|
|
147
|
+
for (const lang of outcome.generatedLangs) {
|
|
148
|
+
const entry = BOOTSTRAP_CATALOG.find((e) => e.lang === lang);
|
|
149
|
+
notes.push(`${lang}: curated starter pack generated (${entry.checks.length} checks). ` +
|
|
150
|
+
`Suggested framework detectors next: ${entry.frameworkHints.join('; ')}.`);
|
|
151
|
+
}
|
|
152
|
+
for (const lang of outcome.fallbackLangs) {
|
|
153
|
+
notes.push(`${lang}: no curated knowledge — generic judgement prompts generated. ` +
|
|
154
|
+
'Author real checks from this codebase before trusting any score.');
|
|
155
|
+
}
|
|
156
|
+
notes.push('Next: review each file, test against good/bad fixtures, register in rules/index.yaml.');
|
|
157
|
+
return notes;
|
|
158
|
+
}
|
|
159
|
+
/** Write generated packs: `--out <dir>` for any count, `--out <file>` for one. */
|
|
160
|
+
export function writeBootstrapPacks(outcome, out) {
|
|
161
|
+
if (!out.endsWith('.yaml') && !out.endsWith('.yml')) {
|
|
162
|
+
fs.mkdirSync(out, { recursive: true });
|
|
163
|
+
for (const pack of outcome.packs) {
|
|
164
|
+
fs.writeFileSync(path.join(out, path.basename(pack.filename)), pack.yaml, 'utf8');
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (outcome.packs.length !== 1) {
|
|
169
|
+
throw new Error(`--out points at a file but ${outcome.packs.length} packs were generated — point --out at a directory instead.`);
|
|
170
|
+
}
|
|
171
|
+
fs.mkdirSync(path.dirname(path.resolve(out)), { recursive: true });
|
|
172
|
+
fs.writeFileSync(out, outcome.packs[0].yaml, 'utf8');
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAClD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAA2C,MAAM,cAAc,CAAC;AAoC1F,0EAA0E;AAC1E,MAAM,aAAa,GAA2B;IAC5C,UAAU,EAAE,wBAAwB;IACpC,UAAU,EAAE,wBAAwB;IACpC,MAAM,EAAE,eAAe;IACvB,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,iBAAiB;CAC5B,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,KAAY;IACzC,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;SACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;SACnC,IAAI,EAAE,CAAC;IACV,MAAM,OAAO,GAAqB;QAChC,KAAK,EAAE,EAAE;QACT,YAAY,EAAE,EAAE;QAChB,cAAc,EAAE,EAAE;QAClB,aAAa,EAAE,EAAE;QACjB,KAAK,EAAE,EAAE;KACV,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QAChF,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,aAAa,GAAG;;;;;;;;;;CAUrB,CAAC;AAEF,SAAS,iBAAiB,CAAC,KAAoB;IAC7C,MAAM,GAAG,GAAG;QACV,EAAE,EAAE,KAAK,CAAC,MAAM;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,mBAAmB;QAClC,WAAW,EAAE,GAAG,KAAK,CAAC,WAAW,gCAAgC;QACjE,OAAO,EAAE,iBAAiB;QAC1B,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE;QAClE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;KACrC,CAAC;IACF,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,OAAO;QAChC,IAAI,EAAE,GAAG,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE;KAC9C,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,UAAU,IAAI,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG;QACV,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,mBAAmB;QAClC,WAAW,EAAE,wBAAwB,IAAI,oHAAoH;QAC7J,OAAO,EAAE,iBAAiB;QAC1B,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE;QAC5D,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,GAAG,MAAM,MAAM;gBACnB,KAAK,EAAE,wCAAwC;gBAC/C,OAAO,EAAE,KAAK;gBACd,aAAa,EAAE,mBAAmB;gBAClC,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,UAAU;gBACjB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,GAAG,EAAE,gBAAgB,IAAI,4DAA4D;gBACrF,WAAW,EAAE,UAAU,IAAI,8DAA8D;gBACzF,QAAQ,EAAE,mDAAmD;aAC9D;YACD;gBACE,EAAE,EAAE,GAAG,MAAM,MAAM;gBACnB,KAAK,EAAE,iCAAiC;gBACxC,OAAO,EAAE,KAAK;gBACd,aAAa,EAAE,mBAAmB;gBAClC,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,cAAc;gBACrB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,GAAG,EAAE,+CAA+C,IAAI,kBAAkB;gBAC1E,WAAW,EAAE,8DAA8D;gBAC3E,QAAQ,EAAE,mDAAmD;aAC9D;SACF;KACF,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,OAAO,EAAE,IAAI,EAAE,GAAG,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;AAC/F,CAAC;AAID,MAAM,wBAAwB,GAA0D;IACtF,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;IAC7C,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC;IACjD,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvD,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;IACnE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;CACnC,CAAC;AAEF,SAAS,SAAS,CAAC,IAAY,EAAE,CAAiB;IAChD,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;QACxB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;QACxB,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,KAAK,EAAE,GAAG;KACX,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,CAAiB;IACpC,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,mBAAmB;QAClC,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,KAAK,EAAE,CAAC,CAAC,SAAS;QAClB,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,OAAyB;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,gCAAgC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAE,CAAC;QAC9D,KAAK,CAAC,IAAI,CACR,GAAG,IAAI,qCAAqC,KAAK,CAAC,MAAM,CAAC,MAAM,YAAY;YACzE,uCAAuC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5E,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CACR,GAAG,IAAI,gEAAgE;YACrE,kEAAkE,CACrE,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CACR,uFAAuF,CACxF,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,OAAyB,EAAE,GAAW;IACxE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpF,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,8BAA8B,OAAO,CAAC,KAAK,CAAC,MAAM,6DAA6D,CAChH,CAAC;IACJ,CAAC;IACD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC"}
|