securenow 4.0.2 → 4.0.5

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.
@@ -0,0 +1,481 @@
1
+ # 🔒 Redaction Examples - See It In Action
2
+
3
+ Real examples of how SecureNow redacts sensitive data across all content types.
4
+
5
+ ---
6
+
7
+ ## JSON Redaction
8
+
9
+ ### Example 1: Login Request
10
+
11
+ **Original Request:**
12
+ ```json
13
+ POST /api/login
14
+ Content-Type: application/json
15
+
16
+ {
17
+ "username": "john@example.com",
18
+ "password": "MySecretPass123!",
19
+ "remember": true,
20
+ "device_id": "abc123"
21
+ }
22
+ ```
23
+
24
+ **Captured in Trace:**
25
+ ```json
26
+ {
27
+ "username": "john@example.com",
28
+ "password": "[REDACTED]",
29
+ "remember": true,
30
+ "device_id": "abc123"
31
+ }
32
+ ```
33
+
34
+ ### Example 2: Payment Request
35
+
36
+ **Original Request:**
37
+ ```json
38
+ POST /api/payment
39
+ Content-Type: application/json
40
+
41
+ {
42
+ "amount": 99.99,
43
+ "currency": "USD",
44
+ "card": {
45
+ "number": "4242424242424242",
46
+ "cvv": "123",
47
+ "expiry": "12/25"
48
+ },
49
+ "billing": {
50
+ "name": "John Doe",
51
+ "email": "john@example.com"
52
+ }
53
+ }
54
+ ```
55
+
56
+ **Captured in Trace:**
57
+ ```json
58
+ {
59
+ "amount": 99.99,
60
+ "currency": "USD",
61
+ "card": "[REDACTED]",
62
+ "billing": {
63
+ "name": "John Doe",
64
+ "email": "john@example.com"
65
+ }
66
+ }
67
+ ```
68
+ *Note: The entire `card` object is redacted because the key contains "card"*
69
+
70
+ ### Example 3: Nested Secrets
71
+
72
+ **Original Request:**
73
+ ```json
74
+ {
75
+ "user": {
76
+ "name": "John",
77
+ "auth": {
78
+ "password": "secret",
79
+ "api_key": "sk_live_abc123"
80
+ }
81
+ },
82
+ "metadata": {
83
+ "session_token": "xyz789"
84
+ }
85
+ }
86
+ ```
87
+
88
+ **Captured in Trace:**
89
+ ```json
90
+ {
91
+ "user": {
92
+ "name": "John",
93
+ "auth": {
94
+ "password": "[REDACTED]",
95
+ "api_key": "[REDACTED]"
96
+ }
97
+ },
98
+ "metadata": {
99
+ "session_token": "[REDACTED]"
100
+ }
101
+ }
102
+ ```
103
+ *Recursive redaction finds sensitive fields at any depth*
104
+
105
+ ---
106
+
107
+ ## GraphQL Redaction
108
+
109
+ ### Example 1: Login Mutation
110
+
111
+ **Original Request:**
112
+ ```graphql
113
+ POST /graphql
114
+ Content-Type: application/graphql
115
+
116
+ mutation Login {
117
+ login(
118
+ email: "john@example.com",
119
+ password: "MySecretPass123!"
120
+ ) {
121
+ token
122
+ user {
123
+ id
124
+ name
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ **Captured in Trace:**
131
+ ```graphql
132
+ mutation Login {
133
+ login(
134
+ email: "john@example.com",
135
+ password: "[REDACTED]"
136
+ ) {
137
+ token
138
+ user {
139
+ id
140
+ name
141
+ }
142
+ }
143
+ }
144
+ ```
145
+
146
+ ### Example 2: Variables with Secrets
147
+
148
+ **Original Request:**
149
+ ```graphql
150
+ mutation CreateUser($input: UserInput!) {
151
+ createUser(input: $input) {
152
+ id
153
+ }
154
+ }
155
+
156
+ Variables:
157
+ {
158
+ "input": {
159
+ "email": "john@example.com",
160
+ "password": "secret123",
161
+ "api_key": "sk_test_abc"
162
+ }
163
+ }
164
+ ```
165
+
166
+ **Captured in Trace:**
167
+ ```graphql
168
+ mutation CreateUser($input: UserInput!) {
169
+ createUser(input: $input) {
170
+ id
171
+ }
172
+ }
173
+
174
+ Variables:
175
+ {
176
+ "input": {
177
+ "email": "john@example.com",
178
+ "password": "[REDACTED]",
179
+ "api_key": "[REDACTED]"
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### Example 3: Multiple Sensitive Fields
185
+
186
+ **Original Request:**
187
+ ```graphql
188
+ mutation UpdateAccount {
189
+ updateAccount(
190
+ id: "123",
191
+ password: "newpass",
192
+ secret: "mysecret",
193
+ api_key: "sk_live_xyz"
194
+ ) {
195
+ success
196
+ }
197
+ }
198
+ ```
199
+
200
+ **Captured in Trace:**
201
+ ```graphql
202
+ mutation UpdateAccount {
203
+ updateAccount(
204
+ id: "123",
205
+ password: "[REDACTED]",
206
+ secret: "[REDACTED]",
207
+ api_key: "[REDACTED]"
208
+ ) {
209
+ success
210
+ }
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Form Data Redaction
217
+
218
+ ### Example 1: Login Form
219
+
220
+ **Original Request:**
221
+ ```http
222
+ POST /api/login
223
+ Content-Type: application/x-www-form-urlencoded
224
+
225
+ username=john&password=secret123&remember=on
226
+ ```
227
+
228
+ **Captured in Trace:**
229
+ ```json
230
+ {
231
+ "username": "john",
232
+ "password": "[REDACTED]",
233
+ "remember": "on"
234
+ }
235
+ ```
236
+
237
+ ### Example 2: Registration Form
238
+
239
+ **Original Request:**
240
+ ```http
241
+ POST /api/register
242
+ Content-Type: application/x-www-form-urlencoded
243
+
244
+ email=john@example.com&password=MyPass123&confirm_password=MyPass123&terms=agree
245
+ ```
246
+
247
+ **Captured in Trace:**
248
+ ```json
249
+ {
250
+ "email": "john@example.com",
251
+ "password": "[REDACTED]",
252
+ "confirm_password": "[REDACTED]",
253
+ "terms": "agree"
254
+ }
255
+ ```
256
+ *Note: "confirm_password" is redacted because it contains "password"*
257
+
258
+ ---
259
+
260
+ ## Multipart (NOT Captured)
261
+
262
+ ### Example: File Upload
263
+
264
+ **Original Request:**
265
+ ```http
266
+ POST /api/upload
267
+ Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
268
+
269
+ ------WebKitFormBoundary
270
+ Content-Disposition: form-data; name="file"; filename="document.pdf"
271
+ Content-Type: application/pdf
272
+
273
+ [Binary PDF data...]
274
+ ------WebKitFormBoundary
275
+ Content-Disposition: form-data; name="description"
276
+
277
+ Important document
278
+ ------WebKitFormBoundary--
279
+ ```
280
+
281
+ **Captured in Trace:**
282
+ ```json
283
+ {
284
+ "http.request.body": "[MULTIPART - NOT CAPTURED]",
285
+ "http.request.body.type": "multipart",
286
+ "http.request.body.note": "File uploads not captured by design"
287
+ }
288
+ ```
289
+ *Multipart data is NOT captured at all - too large and unnecessary*
290
+
291
+ ---
292
+
293
+ ## Custom Sensitive Fields
294
+
295
+ ### Configure Custom Fields
296
+
297
+ ```bash
298
+ # .env.local
299
+ SECURENOW_SENSITIVE_FIELDS=email,phone,address,ssn,credit_card
300
+ ```
301
+
302
+ ### Example with Custom Fields
303
+
304
+ **Original Request:**
305
+ ```json
306
+ {
307
+ "name": "John Doe",
308
+ "email": "john@example.com",
309
+ "phone": "+1-555-0123",
310
+ "address": "123 Main St",
311
+ "credit_card": "4242424242424242"
312
+ }
313
+ ```
314
+
315
+ **Captured in Trace:**
316
+ ```json
317
+ {
318
+ "name": "John Doe",
319
+ "email": "[REDACTED]",
320
+ "phone": "[REDACTED]",
321
+ "address": "[REDACTED]",
322
+ "credit_card": "[REDACTED]"
323
+ }
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Field Matching Rules
329
+
330
+ ### Case-Insensitive Matching
331
+
332
+ These all get redacted if "password" is in the sensitive list:
333
+ - `password` → `[REDACTED]`
334
+ - `Password` → `[REDACTED]`
335
+ - `PASSWORD` → `[REDACTED]`
336
+ - `user_password` → `[REDACTED]`
337
+ - `passwordHash` → `[REDACTED]`
338
+
339
+ ### Partial Matching (Substring)
340
+
341
+ If "token" is sensitive, these get redacted:
342
+ - `token` → `[REDACTED]`
343
+ - `access_token` → `[REDACTED]`
344
+ - `refresh_token` → `[REDACTED]`
345
+ - `oauth_token` → `[REDACTED]`
346
+ - `stripe_token` → `[REDACTED]`
347
+
348
+ ### Built-in Sensitive Fields (20+)
349
+
350
+ ```javascript
351
+ [
352
+ 'password', 'passwd', 'pwd',
353
+ 'secret', 'token', 'api_key', 'apikey',
354
+ 'access_token', 'auth', 'credentials',
355
+ 'mysql_pwd', 'stripeToken',
356
+ 'card', 'cardnumber', 'ccv', 'cvc', 'cvv',
357
+ 'ssn', 'pin'
358
+ ]
359
+ ```
360
+
361
+ ---
362
+
363
+ ## Edge Cases
364
+
365
+ ### 1. Empty Values
366
+
367
+ **Original:**
368
+ ```json
369
+ { "password": "" }
370
+ ```
371
+
372
+ **Captured:**
373
+ ```json
374
+ { "password": "[REDACTED]" }
375
+ ```
376
+ *Even empty sensitive fields are redacted*
377
+
378
+ ### 2. Null Values
379
+
380
+ **Original:**
381
+ ```json
382
+ { "password": null }
383
+ ```
384
+
385
+ **Captured:**
386
+ ```json
387
+ { "password": "[REDACTED]" }
388
+ ```
389
+
390
+ ### 3. Numeric Passwords
391
+
392
+ **Original:**
393
+ ```json
394
+ { "password": 123456 }
395
+ ```
396
+
397
+ **Captured:**
398
+ ```json
399
+ { "password": "[REDACTED]" }
400
+ ```
401
+
402
+ ### 4. Array of Objects
403
+
404
+ **Original:**
405
+ ```json
406
+ {
407
+ "users": [
408
+ { "name": "John", "password": "pass1" },
409
+ { "name": "Jane", "password": "pass2" }
410
+ ]
411
+ }
412
+ ```
413
+
414
+ **Captured:**
415
+ ```json
416
+ {
417
+ "users": [
418
+ { "name": "John", "password": "[REDACTED]" },
419
+ { "name": "Jane", "password": "[REDACTED]" }
420
+ ]
421
+ }
422
+ ```
423
+
424
+ ---
425
+
426
+ ## Verification
427
+
428
+ ### Test Your Redaction
429
+
430
+ 1. **Enable body capture:**
431
+ ```bash
432
+ SECURENOW_CAPTURE_BODY=1
433
+ ```
434
+
435
+ 2. **Make a test request:**
436
+ ```bash
437
+ curl -X POST http://localhost:3000/api/test \
438
+ -H "Content-Type: application/json" \
439
+ -d '{"username":"test","password":"secret123"}'
440
+ ```
441
+
442
+ 3. **Check SigNoz:**
443
+ - Find the trace
444
+ - Look for `http.request.body`
445
+ - Verify password shows `[REDACTED]`
446
+
447
+ ### Debug Redaction
448
+
449
+ Enable debug logging:
450
+ ```bash
451
+ OTEL_LOG_LEVEL=debug npm run dev
452
+ ```
453
+
454
+ You'll see:
455
+ ```
456
+ [securenow] 📝 Request body capture: ENABLED (max: 10240 bytes, redacting 23 sensitive fields)
457
+ ```
458
+
459
+ ---
460
+
461
+ ## 🎉 Summary
462
+
463
+ **Redaction works on ALL content types:**
464
+
465
+ | Type | Redaction | Method |
466
+ |------|-----------|--------|
467
+ | **JSON** | ✅ Yes | Object property matching |
468
+ | **GraphQL** | ✅ Yes | Regex pattern matching |
469
+ | **Form Data** | ✅ Yes | Parsed then object matching |
470
+ | **Multipart** | ❌ N/A | Not captured at all |
471
+
472
+ **Protection:**
473
+ - 20+ built-in sensitive fields
474
+ - Custom fields support
475
+ - Case-insensitive matching
476
+ - Substring matching (e.g., "password" matches "user_password")
477
+ - Recursive (works at any nesting level)
478
+ - Fast (< 1ms overhead)
479
+
480
+ **Your data is safe!** 🔒
481
+