yinzerflow 0.4.4 → 0.5.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/README.md +31 -26
- package/docs/configuration/configuration.md +815 -0
- package/docs/core/core-concepts.md +801 -0
- package/docs/core/error-handling.md +391 -153
- package/docs/core/logging.md +426 -68
- package/docs/modules/body-parsing.md +561 -0
- package/docs/modules/cors.md +369 -0
- package/docs/modules/index.md +125 -0
- package/docs/modules/ip-security.md +280 -0
- package/docs/modules/rate-limiting.md +795 -0
- package/index.d.ts +278 -76
- package/index.js +18 -18
- package/index.js.map +17 -8
- package/package.json +5 -3
- package/docs/configuration/advanced-configuration-options.md +0 -302
- package/docs/configuration/configuration-patterns.md +0 -500
- package/docs/core/context.md +0 -230
- package/docs/core/examples.md +0 -444
- package/docs/core/request.md +0 -161
- package/docs/core/response.md +0 -212
- package/docs/core/routes.md +0 -720
- package/docs/quick-reference.md +0 -346
- package/docs/security/body-parsing.md +0 -296
- package/docs/security/cors.md +0 -189
- package/docs/security/ip-security.md +0 -234
- package/docs/security/security-overview.md +0 -282
- package/docs/start-here.md +0 -184
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
# 📖 Body Parsing Security
|
|
2
|
+
|
|
3
|
+
YinzerFlow provides comprehensive body parsing with built-in security protections against DoS attacks, prototype pollution, and memory exhaustion vulnerabilities. The body parser automatically handles JSON, file uploads, and URL-encoded form data with configurable security limits.
|
|
4
|
+
|
|
5
|
+
For detailed configuration examples and patterns, see [Configuration Guide](../configuration/configuration.md).
|
|
6
|
+
|
|
7
|
+
# ⚙️ Usage
|
|
8
|
+
|
|
9
|
+
## 🎛️ Settings
|
|
10
|
+
|
|
11
|
+
### json.maxSize — @default <span style="color: #2ecc71">`262144`</span> (256KB)
|
|
12
|
+
|
|
13
|
+
Maximum JSON request body size in bytes.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
const app = new YinzerFlow({
|
|
17
|
+
bodyParser: {
|
|
18
|
+
json: {
|
|
19
|
+
maxSize: 262144 // 256KB limit
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
<aside>
|
|
26
|
+
|
|
27
|
+
Options: `number` (in bytes)
|
|
28
|
+
|
|
29
|
+
- Minimum: `1024` (1KB)
|
|
30
|
+
- Recommended: `262144` (256KB) for APIs
|
|
31
|
+
- Maximum: Depends on use case, but avoid values over 10MB
|
|
32
|
+
</aside>
|
|
33
|
+
|
|
34
|
+
### json.maxDepth — @default <span style="color: #2ecc71">`10`</span>
|
|
35
|
+
|
|
36
|
+
Maximum nesting depth to prevent stack overflow attacks.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const app = new YinzerFlow({
|
|
40
|
+
bodyParser: {
|
|
41
|
+
json: {
|
|
42
|
+
maxDepth: 10 // Prevent deep nesting
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
<aside>
|
|
49
|
+
|
|
50
|
+
Options: `number`
|
|
51
|
+
|
|
52
|
+
- Minimum: `1`
|
|
53
|
+
- Recommended: `10` for most APIs
|
|
54
|
+
- Maximum: `50` (higher values increase stack overflow risk)
|
|
55
|
+
</aside>
|
|
56
|
+
|
|
57
|
+
### json.allowPrototypeProperties — @default <span style="color: #e74c3c">`false`</span>
|
|
58
|
+
|
|
59
|
+
Allow dangerous prototype properties (⚠️ Security Risk).
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const app = new YinzerFlow({
|
|
63
|
+
bodyParser: {
|
|
64
|
+
json: {
|
|
65
|
+
allowPrototypeProperties: false // ✅ Always keep false!
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
<aside>
|
|
72
|
+
|
|
73
|
+
Options: `boolean`
|
|
74
|
+
|
|
75
|
+
- `false`: Block prototype pollution (default, secure)
|
|
76
|
+
- `true`: Allow prototype properties (⚠️ Security Risk)
|
|
77
|
+
</aside>
|
|
78
|
+
|
|
79
|
+
### json.maxKeys — @default <span style="color: #2ecc71">`1000`</span>
|
|
80
|
+
|
|
81
|
+
Maximum object keys to prevent memory exhaustion.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const app = new YinzerFlow({
|
|
85
|
+
bodyParser: {
|
|
86
|
+
json: {
|
|
87
|
+
maxKeys: 1000 // Prevent memory exhaustion
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
<aside>
|
|
94
|
+
|
|
95
|
+
Options: `number`
|
|
96
|
+
|
|
97
|
+
- Minimum: `10`
|
|
98
|
+
- Recommended: `1000` for most APIs
|
|
99
|
+
- Maximum: `10000` (higher values increase memory usage)
|
|
100
|
+
</aside>
|
|
101
|
+
|
|
102
|
+
### json.maxStringLength — @default <span style="color: #2ecc71">`1048576`</span> (1MB)
|
|
103
|
+
|
|
104
|
+
Maximum length of JSON string values.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const app = new YinzerFlow({
|
|
108
|
+
bodyParser: {
|
|
109
|
+
json: {
|
|
110
|
+
maxStringLength: 1048576 // 1MB string limit
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
<aside>
|
|
117
|
+
|
|
118
|
+
Options: `number` (in bytes)
|
|
119
|
+
|
|
120
|
+
- Minimum: `100`
|
|
121
|
+
- Recommended: `1048576` (1MB) for most APIs
|
|
122
|
+
- Maximum: `10485760` (10MB) for large text fields
|
|
123
|
+
</aside>
|
|
124
|
+
|
|
125
|
+
### json.maxArrayLength — @default <span style="color: #2ecc71">`10000`</span>
|
|
126
|
+
|
|
127
|
+
Maximum number of array elements.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const app = new YinzerFlow({
|
|
131
|
+
bodyParser: {
|
|
132
|
+
json: {
|
|
133
|
+
maxArrayLength: 10000 // Prevent large arrays
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
<aside>
|
|
140
|
+
|
|
141
|
+
Options: `number`
|
|
142
|
+
|
|
143
|
+
- Minimum: `10`
|
|
144
|
+
- Recommended: `10000` for most APIs
|
|
145
|
+
- Maximum: `100000` (higher values increase memory usage)
|
|
146
|
+
</aside>
|
|
147
|
+
|
|
148
|
+
### fileUploads.maxFileSize — @default <span style="color: #2ecc71">`10485760`</span> (10MB)
|
|
149
|
+
|
|
150
|
+
Maximum size per individual file.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const app = new YinzerFlow({
|
|
154
|
+
bodyParser: {
|
|
155
|
+
fileUploads: {
|
|
156
|
+
maxFileSize: 10485760 // 10MB per file
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
<aside>
|
|
163
|
+
|
|
164
|
+
Options: `number` (in bytes)
|
|
165
|
+
|
|
166
|
+
- Minimum: `1024` (1KB)
|
|
167
|
+
- Recommended: `10485760` (10MB) for most use cases
|
|
168
|
+
- Maximum: `1073741824` (1GB) for large file handling
|
|
169
|
+
</aside>
|
|
170
|
+
|
|
171
|
+
### fileUploads.maxTotalSize — @default <span style="color: #2ecc71">`52428800`</span> (50MB)
|
|
172
|
+
|
|
173
|
+
Maximum total size of all files in a single request.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const app = new YinzerFlow({
|
|
177
|
+
bodyParser: {
|
|
178
|
+
fileUploads: {
|
|
179
|
+
maxTotalSize: 52428800 // 50MB total
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
<aside>
|
|
186
|
+
|
|
187
|
+
Options: `number` (in bytes)
|
|
188
|
+
|
|
189
|
+
- Minimum: `1024` (1KB)
|
|
190
|
+
- Recommended: `52428800` (50MB) for most use cases
|
|
191
|
+
- Maximum: `1073741824` (1GB) for large file uploads
|
|
192
|
+
</aside>
|
|
193
|
+
|
|
194
|
+
### fileUploads.maxFiles — @default <span style="color: #2ecc71">`10`</span>
|
|
195
|
+
|
|
196
|
+
Maximum number of files per request.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
const app = new YinzerFlow({
|
|
200
|
+
bodyParser: {
|
|
201
|
+
fileUploads: {
|
|
202
|
+
maxFiles: 10 // Reasonable file count
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
<aside>
|
|
209
|
+
|
|
210
|
+
Options: `number`
|
|
211
|
+
|
|
212
|
+
- Minimum: `1`
|
|
213
|
+
- Recommended: `10` for most use cases
|
|
214
|
+
- Maximum: `100` (higher values increase processing time)
|
|
215
|
+
</aside>
|
|
216
|
+
|
|
217
|
+
### fileUploads.allowedExtensions — @default <span style="color: #2ecc71">`[]`</span>
|
|
218
|
+
|
|
219
|
+
Allowed file extensions (empty array allows all).
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const app = new YinzerFlow({
|
|
223
|
+
bodyParser: {
|
|
224
|
+
fileUploads: {
|
|
225
|
+
allowedExtensions: ['.jpg', '.png', '.pdf', '.txt'] // Specific types only
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
<aside>
|
|
232
|
+
|
|
233
|
+
Options: `string[]`
|
|
234
|
+
|
|
235
|
+
- `[]`: Allow all extensions (default)
|
|
236
|
+
- `['.jpg', '.png', '.pdf']`: Specific file types only
|
|
237
|
+
- `['.txt', '.md', '.json']`: Document types only
|
|
238
|
+
</aside>
|
|
239
|
+
|
|
240
|
+
### fileUploads.blockedExtensions — @default <span style="color: #2ecc71">`['.exe', '.bat', '.cmd', '.scr', '.pif', '.com']`</span>
|
|
241
|
+
|
|
242
|
+
Blocked file extensions for security.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const app = new YinzerFlow({
|
|
246
|
+
bodyParser: {
|
|
247
|
+
fileUploads: {
|
|
248
|
+
blockedExtensions: ['.exe', '.bat', '.cmd'] // Block dangerous files
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
<aside>
|
|
255
|
+
|
|
256
|
+
Options: `string[]`
|
|
257
|
+
|
|
258
|
+
- `[]`: No blocked extensions (less secure)
|
|
259
|
+
- `['.exe', '.bat', '.cmd']`: Block executable files (recommended)
|
|
260
|
+
- `['.exe', '.bat', '.cmd', '.scr', '.pif', '.com']`: Comprehensive blocking (default)
|
|
261
|
+
</aside>
|
|
262
|
+
|
|
263
|
+
### fileUploads.maxFilenameLength — @default <span style="color: #2ecc71">`255`</span>
|
|
264
|
+
|
|
265
|
+
Maximum filename length to prevent path issues.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const app = new YinzerFlow({
|
|
269
|
+
bodyParser: {
|
|
270
|
+
fileUploads: {
|
|
271
|
+
maxFilenameLength: 255 // Standard filename limit
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
<aside>
|
|
278
|
+
|
|
279
|
+
Options: `number`
|
|
280
|
+
|
|
281
|
+
- Minimum: `10`
|
|
282
|
+
- Recommended: `255` (standard filesystem limit)
|
|
283
|
+
- Maximum: `500` (higher values increase processing overhead)
|
|
284
|
+
</aside>
|
|
285
|
+
|
|
286
|
+
### urlEncoded.maxSize — @default <span style="color: #2ecc71">`1048576`</span> (1MB)
|
|
287
|
+
|
|
288
|
+
Maximum form data size.
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
const app = new YinzerFlow({
|
|
292
|
+
bodyParser: {
|
|
293
|
+
urlEncoded: {
|
|
294
|
+
maxSize: 1048576 // 1MB form data limit
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
<aside>
|
|
301
|
+
|
|
302
|
+
Options: `number` (in bytes)
|
|
303
|
+
|
|
304
|
+
- Minimum: `1024` (1KB)
|
|
305
|
+
- Recommended: `1048576` (1MB) for most forms
|
|
306
|
+
- Maximum: `10485760` (10MB) for large forms
|
|
307
|
+
</aside>
|
|
308
|
+
|
|
309
|
+
### urlEncoded.maxFields — @default <span style="color: #2ecc71">`1000`</span>
|
|
310
|
+
|
|
311
|
+
Maximum form fields to prevent DoS attacks.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
const app = new YinzerFlow({
|
|
315
|
+
bodyParser: {
|
|
316
|
+
urlEncoded: {
|
|
317
|
+
maxFields: 1000 // Prevent DoS through many fields
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
<aside>
|
|
324
|
+
|
|
325
|
+
Options: `number`
|
|
326
|
+
|
|
327
|
+
- Minimum: `10`
|
|
328
|
+
- Recommended: `1000` for most forms
|
|
329
|
+
- Maximum: `10000` (higher values increase processing time)
|
|
330
|
+
</aside>
|
|
331
|
+
|
|
332
|
+
### urlEncoded.maxFieldNameLength — @default <span style="color: #2ecc71">`100`</span>
|
|
333
|
+
|
|
334
|
+
Maximum field name length.
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
const app = new YinzerFlow({
|
|
338
|
+
bodyParser: {
|
|
339
|
+
urlEncoded: {
|
|
340
|
+
maxFieldNameLength: 100 // Reasonable field names
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
<aside>
|
|
347
|
+
|
|
348
|
+
Options: `number`
|
|
349
|
+
|
|
350
|
+
- Minimum: `5`
|
|
351
|
+
- Recommended: `100` for most forms
|
|
352
|
+
- Maximum: `500` (higher values increase processing overhead)
|
|
353
|
+
</aside>
|
|
354
|
+
|
|
355
|
+
### urlEncoded.maxFieldLength — @default <span style="color: #2ecc71">`1048576`</span> (1MB)
|
|
356
|
+
|
|
357
|
+
Maximum field value length.
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const app = new YinzerFlow({
|
|
361
|
+
bodyParser: {
|
|
362
|
+
urlEncoded: {
|
|
363
|
+
maxFieldLength: 1048576 // 1MB per field
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
<aside>
|
|
370
|
+
|
|
371
|
+
Options: `number` (in bytes)
|
|
372
|
+
|
|
373
|
+
- Minimum: `100`
|
|
374
|
+
- Recommended: `1048576` (1MB) for most fields
|
|
375
|
+
- Maximum: `10485760` (10MB) for large text fields
|
|
376
|
+
</aside>
|
|
377
|
+
|
|
378
|
+
# ✨ Best Practices
|
|
379
|
+
|
|
380
|
+
- **Set appropriate size limits** based on your use case
|
|
381
|
+
- **Keep `allowPrototypeProperties: false`** for JSON parsing security
|
|
382
|
+
- **Block dangerous file extensions** for file uploads
|
|
383
|
+
- **Use reasonable field limits** to prevent DoS attacks
|
|
384
|
+
- **Test with large payloads** to verify limits work correctly
|
|
385
|
+
- **Monitor memory usage** with high limits
|
|
386
|
+
|
|
387
|
+
# 💻 Examples
|
|
388
|
+
|
|
389
|
+
### Production API
|
|
390
|
+
|
|
391
|
+
**Use Case:** Secure API with strict body parsing limits
|
|
392
|
+
|
|
393
|
+
**Description:** Production-ready body parsing configuration with conservative limits, blocked dangerous file types, and comprehensive security protections for maximum security.
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
397
|
+
|
|
398
|
+
const app = new YinzerFlow({
|
|
399
|
+
port: 3000,
|
|
400
|
+
bodyParser: {
|
|
401
|
+
json: {
|
|
402
|
+
maxSize: 131072, // 128KB - smaller for strict APIs
|
|
403
|
+
maxDepth: 5, // Shallow nesting only
|
|
404
|
+
allowPrototypeProperties: false, // Always keep false!
|
|
405
|
+
maxKeys: 100, // Fewer keys allowed
|
|
406
|
+
maxStringLength: 10240, // 10KB strings max
|
|
407
|
+
maxArrayLength: 100 // Small arrays only
|
|
408
|
+
},
|
|
409
|
+
fileUploads: {
|
|
410
|
+
maxFileSize: 1048576, // 1MB files only
|
|
411
|
+
maxTotalSize: 5242880, // 5MB total
|
|
412
|
+
maxFiles: 3, // Very few files
|
|
413
|
+
allowedExtensions: ['.jpg', '.png', '.pdf'], // Specific types only
|
|
414
|
+
blockedExtensions: ['.exe', '.bat', '.cmd', '.scr', '.pif', '.com'],
|
|
415
|
+
maxFilenameLength: 50 // Short filenames
|
|
416
|
+
},
|
|
417
|
+
urlEncoded: {
|
|
418
|
+
maxSize: 32768, // 32KB forms only
|
|
419
|
+
maxFields: 50, // Fewer fields
|
|
420
|
+
maxFieldNameLength: 50, // Shorter field names
|
|
421
|
+
maxFieldLength: 10240 // 10KB per field
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
app.post('/api/data', ({ request }) => {
|
|
427
|
+
const data = request.body; // Parsed and validated
|
|
428
|
+
|
|
429
|
+
return { success: true, received: data };
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
await app.listen();
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Dev API
|
|
436
|
+
|
|
437
|
+
**Use Case:** Development server with relaxed body parsing limits
|
|
438
|
+
|
|
439
|
+
**Description:** Development configuration with larger limits, permissive file uploads, and relaxed restrictions for easier testing and debugging.
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
443
|
+
|
|
444
|
+
const app = new YinzerFlow({
|
|
445
|
+
port: 3000,
|
|
446
|
+
bodyParser: {
|
|
447
|
+
json: {
|
|
448
|
+
maxSize: 1048576, // 1MB for development
|
|
449
|
+
maxDepth: 20, // Deeper nesting for testing
|
|
450
|
+
allowPrototypeProperties: false, // Still keep secure!
|
|
451
|
+
maxKeys: 5000, // More keys for development
|
|
452
|
+
maxStringLength: 10485760, // 10MB strings for testing
|
|
453
|
+
maxArrayLength: 50000 // Large arrays for testing
|
|
454
|
+
},
|
|
455
|
+
fileUploads: {
|
|
456
|
+
maxFileSize: 104857600, // 100MB for development
|
|
457
|
+
maxTotalSize: 524288000, // 500MB total
|
|
458
|
+
maxFiles: 50, // More files for testing
|
|
459
|
+
allowedExtensions: [], // Allow all extensions in dev
|
|
460
|
+
blockedExtensions: [], // No blocking in dev
|
|
461
|
+
maxFilenameLength: 500 // Longer filenames for testing
|
|
462
|
+
},
|
|
463
|
+
urlEncoded: {
|
|
464
|
+
maxSize: 10485760, // 10MB for development
|
|
465
|
+
maxFields: 10000, // More fields for testing
|
|
466
|
+
maxFieldNameLength: 500, // Longer field names
|
|
467
|
+
maxFieldLength: 10485760 // 10MB per field
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
app.post('/api/test', ({ request }) => {
|
|
473
|
+
const data = request.body;
|
|
474
|
+
return { message: 'Development mode', data };
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
await app.listen();
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## 🚀 Performance Notes
|
|
481
|
+
|
|
482
|
+
- **Early size validation**: Prevents unnecessary processing of oversized requests
|
|
483
|
+
- **Memory limits**: Configurable limits prevent memory exhaustion
|
|
484
|
+
- **Processing overhead**: Minimal impact on request processing time
|
|
485
|
+
- **File upload limits**: Prevent DoS through large file uploads
|
|
486
|
+
|
|
487
|
+
## 🔒 Security Notes
|
|
488
|
+
|
|
489
|
+
YinzerFlow implements comprehensive security measures to prevent body parsing vulnerabilities:
|
|
490
|
+
|
|
491
|
+
### 🛡️ JSON DoS Attack Prevention
|
|
492
|
+
- **Problem**: Large or deeply nested JSON can cause memory exhaustion and stack overflow attacks
|
|
493
|
+
- **YinzerFlow Solution**: Configurable size limits, nesting depth limits, key count restrictions, and string/array length limits prevent resource exhaustion
|
|
494
|
+
|
|
495
|
+
### 🛡️ Prototype Pollution Protection
|
|
496
|
+
- **Problem**: Malicious JSON can pollute JavaScript prototypes using `__proto__`, `constructor`, and `prototype` properties
|
|
497
|
+
- **YinzerFlow Solution**: Blocks dangerous properties by default with `allowPrototypeProperties: false` and validates all object keys
|
|
498
|
+
|
|
499
|
+
### 🛡️ File Upload Security
|
|
500
|
+
- **Problem**: Malicious file uploads can execute code, consume server resources, or bypass security controls
|
|
501
|
+
- **YinzerFlow Solution**: File type filtering, size limits, filename validation, and extension-based security controls
|
|
502
|
+
|
|
503
|
+
### 🛡️ Memory Exhaustion Protection
|
|
504
|
+
- **Problem**: Large form data, arrays, or objects can exhaust server memory and cause crashes
|
|
505
|
+
- **YinzerFlow Solution**: Configurable limits on strings, arrays, fields, object keys, and total request sizes
|
|
506
|
+
|
|
507
|
+
### 🛡️ Request Size Validation
|
|
508
|
+
- **Problem**: Extremely large requests can cause DoS through resource exhaustion
|
|
509
|
+
- **YinzerFlow Solution**: Content-type specific size limits with early validation before full parsing
|
|
510
|
+
|
|
511
|
+
## 🔧 Troubleshooting
|
|
512
|
+
|
|
513
|
+
### JSON Parsing Fails
|
|
514
|
+
- **Problem**: Invalid JSON syntax or exceeds limits
|
|
515
|
+
- **Fix**: Check JSON syntax and size limits
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
// ❌ Wrong - invalid JSON
|
|
519
|
+
const invalidJson = '{ "name": "John", "age": }';
|
|
520
|
+
|
|
521
|
+
// ✅ Correct - valid JSON
|
|
522
|
+
const validJson = '{ "name": "John", "age": 30 }';
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### File Upload Rejected
|
|
526
|
+
- **Problem**: File too large or blocked extension
|
|
527
|
+
- **Fix**: Check file size and extension configuration
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
// ❌ Wrong - file too large
|
|
531
|
+
fileUploads: { maxFileSize: 1048576 } // 1MB limit
|
|
532
|
+
// Uploading 2MB file
|
|
533
|
+
|
|
534
|
+
// ✅ Correct - increase limit or reduce file size
|
|
535
|
+
fileUploads: { maxFileSize: 2097152 } // 2MB limit
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Form Data Too Large
|
|
539
|
+
- **Problem**: Form exceeds size or field limits
|
|
540
|
+
- **Fix**: Check form size and field configuration
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
// ❌ Wrong - too many fields
|
|
544
|
+
urlEncoded: { maxFields: 100 }
|
|
545
|
+
// Form has 150 fields
|
|
546
|
+
|
|
547
|
+
// ✅ Correct - increase limit or reduce fields
|
|
548
|
+
urlEncoded: { maxFields: 200 }
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Prototype Pollution Warning
|
|
552
|
+
- **Problem**: `allowPrototypeProperties: true` enables dangerous properties
|
|
553
|
+
- **Fix**: Keep this setting false for security
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
// ❌ Wrong - enables prototype pollution
|
|
557
|
+
json: { allowPrototypeProperties: true }
|
|
558
|
+
|
|
559
|
+
// ✅ Correct - blocks prototype pollution
|
|
560
|
+
json: { allowPrototypeProperties: false }
|
|
561
|
+
```
|