mastercontroller 1.3.8 → 1.3.10

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,1805 @@
1
+ # Security Architecture
2
+
3
+ **MasterController Security Layer** - Comprehensive security middleware and utilities protecting against OWASP Top 10 vulnerabilities.
4
+
5
+ ---
6
+
7
+ ## 📋 Table of Contents
8
+
9
+ 1. [Overview](#overview)
10
+ 2. [Security Modules](#security-modules)
11
+ 3. [Architecture & Integration](#architecture--integration)
12
+ 4. [CSRF Protection](#csrf-protection)
13
+ 5. [Rate Limiting](#rate-limiting)
14
+ 6. [Session Security](#session-security)
15
+ 7. [Input Validation](#input-validation)
16
+ 8. [XSS Prevention](#xss-prevention)
17
+ 9. [Event Handler Validation](#event-handler-validation)
18
+ 10. [Content Security Policy](#content-security-policy)
19
+ 11. [Configuration Guide](#configuration-guide)
20
+ 12. [Best Practices](#best-practices)
21
+
22
+ ---
23
+
24
+ ## Overview
25
+
26
+ The MasterController security layer provides **defense-in-depth** protection through multiple coordinated modules. Every HTTP request passes through security middleware that validates, sanitizes, and enforces security policies before reaching application code.
27
+
28
+ ### Key Features
29
+
30
+ - ✅ **CSRF Protection** - Token-based validation for state-changing requests
31
+ - ✅ **Rate Limiting** - Prevents brute force and DoS attacks
32
+ - ✅ **Session Security** - Hijacking detection via fingerprinting
33
+ - ✅ **Input Validation** - SQL/NoSQL/command injection detection
34
+ - ✅ **XSS Prevention** - Multi-layer HTML sanitization
35
+ - ✅ **Event Validation** - Component @event security
36
+ - ✅ **CSP Management** - Content Security Policy with nonce support
37
+ - ✅ **Security Headers** - X-Frame-Options, HSTS, etc.
38
+
39
+ ### Threat Coverage (OWASP Top 10)
40
+
41
+ | Threat | Protection | Module |
42
+ |--------|-----------|---------|
43
+ | **A01: Broken Access Control** | CSRF tokens, session validation | SecurityMiddleware, SessionSecurity |
44
+ | **A02: Cryptographic Failures** | Secure session management | SessionSecurity |
45
+ | **A03: Injection** | SQL/NoSQL/command detection | MasterValidator |
46
+ | **A04: Insecure Design** | Defense-in-depth architecture | All modules |
47
+ | **A05: Security Misconfiguration** | Automatic enforcement | SecurityEnforcement |
48
+ | **A06: Vulnerable Components** | Event handler validation | EventHandlerValidator |
49
+ | **A07: Auth Failures** | Session fingerprinting | SessionSecurity |
50
+ | **A08: Data Integrity** | Input sanitization | MasterSanitizer |
51
+ | **A09: Security Logging** | Comprehensive logging | All modules |
52
+ | **A10: SSRF** | URL validation | MasterValidator |
53
+
54
+ ---
55
+
56
+ ## Security Modules
57
+
58
+ ### 1. SecurityMiddleware.js (15 KB)
59
+
60
+ **Purpose:** Central security orchestration - CSRF, rate limiting, security headers, CORS
61
+
62
+ **Key Features:**
63
+ - CSRF token generation and validation
64
+ - Per-client rate limiting with time windows
65
+ - Security headers (X-Frame-Options, X-Content-Type-Options, etc.)
66
+ - CORS preflight handling
67
+ - Request logging and security auditing
68
+
69
+ **Used By:** MasterRouter.js (called on every HTTP request)
70
+
71
+ ---
72
+
73
+ ### 2. SessionSecurity.js (14 KB)
74
+
75
+ **Purpose:** Secure session management with hijacking detection
76
+
77
+ **Key Features:**
78
+ - Session fingerprinting (IP + User-Agent)
79
+ - Session regeneration on auth changes
80
+ - Session timeout enforcement
81
+ - Concurrent session detection
82
+ - Session fixation prevention
83
+
84
+ **Used By:** MasterAction.js (session creation/validation)
85
+
86
+ ---
87
+
88
+ ### 3. MasterValidator.js (13 KB)
89
+
90
+ **Purpose:** Input validation for injection attacks
91
+
92
+ **Key Features:**
93
+ - SQL injection detection (UNION, DROP, etc.)
94
+ - NoSQL injection detection (MongoDB operators)
95
+ - Command injection detection (shell metacharacters)
96
+ - Path traversal detection (../, directory escape)
97
+ - URL validation with protocol whitelist
98
+ - Email validation
99
+
100
+ **Used By:** MasterAction.js (validates user input before processing)
101
+
102
+ ---
103
+
104
+ ### 4. MasterSanitizer.js (11 KB)
105
+
106
+ **Purpose:** XSS prevention via HTML sanitization
107
+
108
+ **Key Features:**
109
+ - Dangerous tag removal (`<script>`, `<iframe>`, etc.)
110
+ - Event attribute removal (`onclick`, `onerror`, etc.)
111
+ - Protocol sanitization (blocks `javascript:`, `data:`)
112
+ - Whitelist-based approach
113
+ - CSS sanitization (removes `expression()`, `url()`)
114
+
115
+ **Used By:** MasterAction.js (sanitizes HTML before rendering)
116
+
117
+ ---
118
+
119
+ ### 5. EventHandlerValidator.js (12 KB)
120
+
121
+ **Purpose:** Validates @event bindings in Web Components
122
+
123
+ **Key Features:**
124
+ - Validates event handler syntax
125
+ - Checks for dangerous patterns
126
+ - Prevents arbitrary code execution
127
+ - Component security enforcement
128
+
129
+ **Used By:** runtime-ssr.cjs (SSR component rendering)
130
+
131
+ ---
132
+
133
+ ### 6. CSPConfig.js (7.8 KB)
134
+
135
+ **Purpose:** Content Security Policy configuration
136
+
137
+ **Key Features:**
138
+ - Development preset (permissive for debugging)
139
+ - Production preset (strict CSP)
140
+ - CDN preset (trusted external sources)
141
+ - Nonce generation for inline scripts
142
+ - CSP header generation
143
+
144
+ **Used By:** SecurityMiddleware.js (CSP header injection)
145
+
146
+ ---
147
+
148
+ ### 7. SecurityEnforcement.js (6.8 KB)
149
+
150
+ **Purpose:** Automatic security policy enforcement
151
+
152
+ **Key Features:**
153
+ - Auto-enables CSRF in production
154
+ - Auto-enables rate limiting
155
+ - Enforces security headers
156
+ - Validates security configuration
157
+ - Production hardening checks
158
+
159
+ **Used By:** MasterControl.js (initialization time)
160
+
161
+ ---
162
+
163
+ ## Architecture & Integration
164
+
165
+ ### Request Flow
166
+
167
+ ```
168
+ HTTP Request
169
+
170
+ [SecurityMiddleware]
171
+
172
+ ┌─────────────────────────────────┐
173
+ │ 1. Rate Limiting │ → Block if exceeded
174
+ │ 2. CORS Preflight │ → Return 200 if OPTIONS
175
+ │ 3. Security Headers │ → Inject headers
176
+ │ 4. CSRF Validation (POST/PUT) │ → Block if invalid
177
+ └─────────────────────────────────┘
178
+
179
+ [MasterRouter] → Route Resolution
180
+
181
+ [MasterAction] → Controller Method
182
+
183
+ ┌─────────────────────────────────┐
184
+ │ Input Validation │ → MasterValidator
185
+ │ Input Sanitization │ → MasterSanitizer
186
+ │ Session Security │ → SessionSecurity
187
+ └─────────────────────────────────┘
188
+
189
+ [View Rendering]
190
+
191
+ ┌─────────────────────────────────┐
192
+ │ Event Handler Validation │ → EventHandlerValidator
193
+ │ CSP Nonce Injection │ → CSPConfig
194
+ └─────────────────────────────────┘
195
+
196
+ HTTP Response
197
+ ```
198
+
199
+ ### Initialization in MasterControl.js
200
+
201
+ ```javascript
202
+ // Line 305-319: Security module registration
203
+ this.internalModules = [
204
+ "MasterTools",
205
+ "MasterAction",
206
+ "MasterRouter",
207
+ "MasterValidator", // ← Input validation
208
+ "MasterSanitizer", // ← XSS prevention
209
+ "SessionSecurity", // ← Session management
210
+ "SecurityMiddleware", // ← Central security
211
+ "SecurityEnforcement", // ← Auto-enforcement
212
+ "CSPConfig", // ← CSP management
213
+ "EventHandlerValidator" // ← Component security
214
+ ];
215
+
216
+ // Line 324-336: Module loading
217
+ this.moduleRegistry = {
218
+ validator: './MasterValidator',
219
+ sanitizer: './MasterSanitizer',
220
+ sessionSecurity: './security/SessionSecurity',
221
+ securityMiddleware: './security/SecurityMiddleware',
222
+ securityEnforcement: './security/SecurityEnforcement',
223
+ cspConfig: './security/CSPConfig',
224
+ eventValidator: './security/EventHandlerValidator'
225
+ };
226
+ ```
227
+
228
+ ### Integration in MasterRouter.js
229
+
230
+ ```javascript
231
+ // Line 95-110: Security middleware execution
232
+ routeMiddleware(requestObject, _loadEmit, routeList, middlewareList) {
233
+ // 1. Execute security middleware FIRST
234
+ this._master.securityMiddleware.checkRequest(requestObject);
235
+
236
+ // 2. Rate limiting
237
+ if (this._master.securityMiddleware.isRateLimited(requestObject)) {
238
+ requestObject.response.writeHead(429, {'Content-Type': 'text/plain'});
239
+ requestObject.response.end('Too Many Requests');
240
+ return;
241
+ }
242
+
243
+ // 3. CSRF validation for state-changing methods
244
+ if (['POST', 'PUT', 'DELETE'].includes(requestObject.request.method)) {
245
+ if (!this._master.securityMiddleware.validateCSRF(requestObject)) {
246
+ requestObject.response.writeHead(403, {'Content-Type': 'text/plain'});
247
+ requestObject.response.end('CSRF validation failed');
248
+ return;
249
+ }
250
+ }
251
+
252
+ // 4. Continue to route processing
253
+ this.processRoute(requestObject, _loadEmit, routeList);
254
+ }
255
+ ```
256
+
257
+ ---
258
+
259
+ ## CSRF Protection
260
+
261
+ ### Business Logic
262
+
263
+ **CSRF (Cross-Site Request Forgery)** protection prevents attackers from making unauthorized requests on behalf of authenticated users.
264
+
265
+ #### How It Works
266
+
267
+ 1. **Token Generation** - Server generates unique token per session
268
+ 2. **Token Embedding** - Token embedded in forms/AJAX headers
269
+ 3. **Token Validation** - Server validates token on state-changing requests
270
+ 4. **Token Rotation** - Tokens rotate periodically for security
271
+
272
+ ### Workflow
273
+
274
+ ```
275
+ User Visits Page
276
+
277
+ [SecurityMiddleware.generateCSRFToken()]
278
+
279
+ Token stored in session: {
280
+ token: "abc123...",
281
+ timestamp: 1706534400000
282
+ }
283
+
284
+ Token embedded in HTML:
285
+ <input type="hidden" name="_csrf" value="abc123...">
286
+
287
+ User Submits Form
288
+
289
+ [SecurityMiddleware.validateCSRF()]
290
+
291
+ ✓ Token matches session
292
+ ✓ Token not expired (< 1 hour)
293
+ ✓ Token used only once
294
+
295
+ Request Processed
296
+ ```
297
+
298
+ ### Implementation
299
+
300
+ **SecurityMiddleware.js (Lines 45-120)**
301
+
302
+ ```javascript
303
+ generateCSRFToken(sessionId) {
304
+ // Generate cryptographically secure token
305
+ const token = crypto.randomBytes(32).toString('hex');
306
+
307
+ // Store in session
308
+ this.csrfTokens.set(sessionId, {
309
+ token: token,
310
+ timestamp: Date.now(),
311
+ used: false
312
+ });
313
+
314
+ return token;
315
+ }
316
+
317
+ validateCSRF(requestObject) {
318
+ const sessionId = requestObject.session.id;
319
+ const submittedToken = requestObject.body._csrf ||
320
+ requestObject.headers['x-csrf-token'];
321
+
322
+ const storedData = this.csrfTokens.get(sessionId);
323
+
324
+ // Validation checks
325
+ if (!storedData) return false;
326
+ if (storedData.token !== submittedToken) return false;
327
+ if (storedData.used) return false; // One-time use
328
+ if (Date.now() - storedData.timestamp > 3600000) return false; // 1 hour expiry
329
+
330
+ // Mark as used
331
+ storedData.used = true;
332
+
333
+ return true;
334
+ }
335
+ ```
336
+
337
+ ### Usage in Controllers
338
+
339
+ ```javascript
340
+ class FormController {
341
+ // Display form with CSRF token
342
+ showForm(obj) {
343
+ const csrfToken = this.generateCSRFToken();
344
+ this.returnView({ csrfToken });
345
+ }
346
+
347
+ // Process form with CSRF validation
348
+ submitForm(obj) {
349
+ // CSRF automatically validated by SecurityMiddleware
350
+ // If we reach here, token was valid
351
+
352
+ const data = this.params;
353
+ // Process form...
354
+ }
355
+ }
356
+ ```
357
+
358
+ ### HTML Template
359
+
360
+ ```html
361
+ <form method="POST" action="/form/submit">
362
+ <!-- CSRF token (auto-validated on submit) -->
363
+ <input type="hidden" name="_csrf" value="${csrfToken}">
364
+
365
+ <input type="text" name="username">
366
+ <button type="submit">Submit</button>
367
+ </form>
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Rate Limiting
373
+
374
+ ### Business Logic
375
+
376
+ **Rate limiting** prevents brute force attacks, credential stuffing, and DoS by limiting requests per client per time window.
377
+
378
+ #### Strategy
379
+
380
+ - **Time Window:** 15 minutes (configurable)
381
+ - **Max Requests:** 100 per window (configurable)
382
+ - **Client Identification:** IP address + User-Agent
383
+ - **Storage:** In-memory Map (production: Redis)
384
+
385
+ ### Workflow
386
+
387
+ ```
388
+ Request arrives
389
+
390
+ [SecurityMiddleware.isRateLimited()]
391
+
392
+ Identify client: IP + User-Agent hash
393
+
394
+ Check rate limit storage:
395
+ {
396
+ "192.168.1.1:Mozilla/5.0": {
397
+ count: 95,
398
+ windowStart: 1706534400000
399
+ }
400
+ }
401
+
402
+ If count < 100:
403
+ Increment count → Allow request
404
+ If count >= 100:
405
+ Block request → Return 429 Too Many Requests
406
+
407
+ If windowStart > 15 minutes ago:
408
+ Reset count → Allow request
409
+ ```
410
+
411
+ ### Implementation
412
+
413
+ **SecurityMiddleware.js (Lines 125-200)**
414
+
415
+ ```javascript
416
+ isRateLimited(requestObject) {
417
+ // Client identification
418
+ const clientId = this._getClientId(requestObject);
419
+
420
+ const now = Date.now();
421
+ const windowMs = 15 * 60 * 1000; // 15 minutes
422
+ const maxRequests = 100;
423
+
424
+ // Get or create client record
425
+ let clientData = this.rateLimitStore.get(clientId);
426
+
427
+ if (!clientData) {
428
+ clientData = { count: 0, windowStart: now };
429
+ this.rateLimitStore.set(clientId, clientData);
430
+ }
431
+
432
+ // Check if window expired
433
+ if (now - clientData.windowStart > windowMs) {
434
+ clientData.count = 0;
435
+ clientData.windowStart = now;
436
+ }
437
+
438
+ // Increment and check
439
+ clientData.count++;
440
+
441
+ if (clientData.count > maxRequests) {
442
+ logger.warn({
443
+ code: 'RATE_LIMIT_EXCEEDED',
444
+ clientId,
445
+ count: clientData.count
446
+ });
447
+ return true; // Rate limited
448
+ }
449
+
450
+ return false; // Allowed
451
+ }
452
+
453
+ _getClientId(requestObject) {
454
+ const ip = requestObject.request.connection.remoteAddress;
455
+ const ua = requestObject.request.headers['user-agent'] || '';
456
+ return `${ip}:${crypto.createHash('md5').update(ua).digest('hex')}`;
457
+ }
458
+ ```
459
+
460
+ ### Configuration
461
+
462
+ ```javascript
463
+ // config/security.js
464
+ module.exports = {
465
+ rateLimit: {
466
+ enabled: true,
467
+ windowMs: 15 * 60 * 1000, // 15 minutes
468
+ maxRequests: 100, // 100 requests per window
469
+ skipSuccessfulRequests: false,
470
+ skipFailedRequests: false,
471
+ whitelist: ['127.0.0.1'] // Exempt IPs
472
+ }
473
+ };
474
+ ```
475
+
476
+ ---
477
+
478
+ ## Session Security
479
+
480
+ ### Business Logic
481
+
482
+ **Session security** prevents session hijacking, fixation, and unauthorized access through fingerprinting and validation.
483
+
484
+ #### Security Measures
485
+
486
+ 1. **Session Fingerprinting** - Bind session to IP + User-Agent
487
+ 2. **Session Regeneration** - New session ID after authentication
488
+ 3. **Timeout Enforcement** - Sessions expire after inactivity
489
+ 4. **Concurrent Session Detection** - Limit sessions per user
490
+ 5. **Secure Cookie Flags** - HttpOnly, Secure, SameSite
491
+
492
+ ### Workflow
493
+
494
+ ```
495
+ User Logs In
496
+
497
+ [SessionSecurity.createSession()]
498
+
499
+ Generate session ID: crypto.randomBytes(32)
500
+
501
+ Create fingerprint:
502
+ IP: 192.168.1.1
503
+ User-Agent: Mozilla/5.0...
504
+ Hash: sha256(IP + UA)
505
+
506
+ Store session:
507
+ {
508
+ id: "abc123...",
509
+ userId: 42,
510
+ fingerprint: "def456...",
511
+ createdAt: 1706534400000,
512
+ lastActivity: 1706534400000
513
+ }
514
+
515
+ Set secure cookie:
516
+ HttpOnly: true
517
+ Secure: true (HTTPS only)
518
+ SameSite: Strict
519
+
520
+ ---
521
+ User Makes Request
522
+
523
+ [SessionSecurity.validateSession()]
524
+
525
+ Check fingerprint:
526
+ Stored: "def456..."
527
+ Current: "def456..."
528
+ ✓ Match → Continue
529
+ ✗ Mismatch → Destroy session → Redirect to login
530
+
531
+ Check timeout:
532
+ Last activity: 30 minutes ago
533
+ Timeout: 60 minutes
534
+ ✓ Active → Update lastActivity
535
+ ✗ Expired → Destroy session → Redirect to login
536
+
537
+ Request Processed
538
+ ```
539
+
540
+ ### Implementation
541
+
542
+ **SessionSecurity.js (Lines 40-250)**
543
+
544
+ ```javascript
545
+ createSession(userId, requestObject) {
546
+ // Generate secure session ID
547
+ const sessionId = crypto.randomBytes(32).toString('hex');
548
+
549
+ // Create fingerprint
550
+ const fingerprint = this._createFingerprint(requestObject);
551
+
552
+ // Store session
553
+ const session = {
554
+ id: sessionId,
555
+ userId: userId,
556
+ fingerprint: fingerprint,
557
+ createdAt: Date.now(),
558
+ lastActivity: Date.now(),
559
+ data: {}
560
+ };
561
+
562
+ this.sessions.set(sessionId, session);
563
+
564
+ // Set secure cookie
565
+ requestObject.response.setHeader('Set-Cookie',
566
+ `sessionId=${sessionId}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600`
567
+ );
568
+
569
+ logger.info({
570
+ code: 'SESSION_CREATED',
571
+ userId,
572
+ sessionId: sessionId.substring(0, 8) + '...'
573
+ });
574
+
575
+ return sessionId;
576
+ }
577
+
578
+ validateSession(requestObject) {
579
+ const sessionId = this._extractSessionId(requestObject);
580
+ if (!sessionId) return false;
581
+
582
+ const session = this.sessions.get(sessionId);
583
+ if (!session) return false;
584
+
585
+ // Validate fingerprint
586
+ const currentFingerprint = this._createFingerprint(requestObject);
587
+ if (session.fingerprint !== currentFingerprint) {
588
+ logger.warn({
589
+ code: 'SESSION_HIJACK_DETECTED',
590
+ sessionId: sessionId.substring(0, 8) + '...'
591
+ });
592
+ this.destroySession(sessionId);
593
+ return false;
594
+ }
595
+
596
+ // Check timeout (60 minutes)
597
+ const timeout = 60 * 60 * 1000;
598
+ if (Date.now() - session.lastActivity > timeout) {
599
+ logger.info({
600
+ code: 'SESSION_TIMEOUT',
601
+ sessionId: sessionId.substring(0, 8) + '...'
602
+ });
603
+ this.destroySession(sessionId);
604
+ return false;
605
+ }
606
+
607
+ // Update activity
608
+ session.lastActivity = Date.now();
609
+
610
+ return true;
611
+ }
612
+
613
+ _createFingerprint(requestObject) {
614
+ const ip = requestObject.request.connection.remoteAddress;
615
+ const ua = requestObject.request.headers['user-agent'] || '';
616
+ return crypto.createHash('sha256').update(ip + ua).digest('hex');
617
+ }
618
+
619
+ regenerateSession(oldSessionId, requestObject) {
620
+ // Get old session data
621
+ const oldSession = this.sessions.get(oldSessionId);
622
+ if (!oldSession) return null;
623
+
624
+ // Create new session with same data
625
+ const newSessionId = this.createSession(oldSession.userId, requestObject);
626
+ const newSession = this.sessions.get(newSessionId);
627
+ newSession.data = oldSession.data;
628
+
629
+ // Destroy old session
630
+ this.destroySession(oldSessionId);
631
+
632
+ logger.info({
633
+ code: 'SESSION_REGENERATED',
634
+ oldId: oldSessionId.substring(0, 8) + '...',
635
+ newId: newSessionId.substring(0, 8) + '...'
636
+ });
637
+
638
+ return newSessionId;
639
+ }
640
+ ```
641
+
642
+ ### Usage in Authentication
643
+
644
+ ```javascript
645
+ class AuthController {
646
+ async login(obj) {
647
+ const { username, password } = this.params;
648
+
649
+ // Validate credentials
650
+ const user = await User.findByUsername(username);
651
+ if (!user || !user.verifyPassword(password)) {
652
+ return this.returnError(401, 'Invalid credentials');
653
+ }
654
+
655
+ // Create secure session
656
+ const sessionId = this.createSession(user.id, this.__requestObject);
657
+
658
+ // Redirect to dashboard
659
+ this.redirectTo('/dashboard');
660
+ }
661
+
662
+ logout(obj) {
663
+ const sessionId = this._extractSessionId(this.__requestObject);
664
+ this.destroySession(sessionId);
665
+ this.redirectTo('/');
666
+ }
667
+ }
668
+ ```
669
+
670
+ ---
671
+
672
+ ## Input Validation
673
+
674
+ ### Business Logic
675
+
676
+ **Input validation** prevents injection attacks by detecting malicious patterns before data reaches the database or OS.
677
+
678
+ #### Validation Types
679
+
680
+ 1. **SQL Injection** - Detects SQL keywords (UNION, DROP, etc.)
681
+ 2. **NoSQL Injection** - Detects MongoDB operators ($where, $ne, etc.)
682
+ 3. **Command Injection** - Detects shell metacharacters (|, &, `, etc.)
683
+ 4. **Path Traversal** - Detects directory escape (../, ..\, etc.)
684
+ 5. **URL Validation** - Protocol whitelist (http, https only)
685
+
686
+ ### Workflow
687
+
688
+ ```
689
+ User Input Received
690
+
691
+ [MasterValidator.validateInput()]
692
+
693
+ Check for SQL injection:
694
+ "'; DROP TABLE users; --"
695
+ ✗ Contains SQL keywords → REJECT
696
+
697
+ Check for NoSQL injection:
698
+ {"$where": "this.password == 'admin'"}
699
+ ✗ Contains NoSQL operators → REJECT
700
+
701
+ Check for command injection:
702
+ "test | rm -rf /"
703
+ ✗ Contains shell metacharacters → REJECT
704
+
705
+ Check for path traversal:
706
+ "../../../etc/passwd"
707
+ ✗ Contains directory escape → REJECT
708
+
709
+ ✓ All checks passed → ALLOW
710
+ ```
711
+
712
+ ### Implementation
713
+
714
+ **MasterValidator.js (Lines 30-400)**
715
+
716
+ ```javascript
717
+ validateInput(input, type = 'string') {
718
+ if (!input) return { valid: true };
719
+
720
+ // SQL injection check
721
+ const sqlCheck = this._checkSQLInjection(input);
722
+ if (!sqlCheck.valid) {
723
+ logger.warn({
724
+ code: 'SQL_INJECTION_DETECTED',
725
+ input: input.substring(0, 100),
726
+ pattern: sqlCheck.pattern
727
+ });
728
+ return sqlCheck;
729
+ }
730
+
731
+ // NoSQL injection check
732
+ const nosqlCheck = this._checkNoSQLInjection(input);
733
+ if (!nosqlCheck.valid) {
734
+ logger.warn({
735
+ code: 'NOSQL_INJECTION_DETECTED',
736
+ input: input.substring(0, 100)
737
+ });
738
+ return nosqlCheck;
739
+ }
740
+
741
+ // Command injection check
742
+ const cmdCheck = this._checkCommandInjection(input);
743
+ if (!cmdCheck.valid) {
744
+ logger.warn({
745
+ code: 'COMMAND_INJECTION_DETECTED',
746
+ input: input.substring(0, 100)
747
+ });
748
+ return cmdCheck;
749
+ }
750
+
751
+ // Path traversal check
752
+ const pathCheck = this._checkPathTraversal(input);
753
+ if (!pathCheck.valid) {
754
+ logger.warn({
755
+ code: 'PATH_TRAVERSAL_DETECTED',
756
+ input: input.substring(0, 100)
757
+ });
758
+ return pathCheck;
759
+ }
760
+
761
+ return { valid: true };
762
+ }
763
+
764
+ _checkSQLInjection(input) {
765
+ const sqlPatterns = [
766
+ /(\bUNION\b.*\bSELECT\b)/i,
767
+ /(\bDROP\b.*\bTABLE\b)/i,
768
+ /(\bINSERT\b.*\bINTO\b)/i,
769
+ /(\bUPDATE\b.*\bSET\b)/i,
770
+ /(\bDELETE\b.*\bFROM\b)/i,
771
+ /(--[^\r\n]*)/,
772
+ /('.*OR.*'.*=.*')/i,
773
+ /;\s*DROP/i,
774
+ /;\s*EXEC/i,
775
+ /xp_cmdshell/i
776
+ ];
777
+
778
+ for (const pattern of sqlPatterns) {
779
+ if (pattern.test(input)) {
780
+ return {
781
+ valid: false,
782
+ error: 'SQL injection pattern detected',
783
+ pattern: pattern.toString()
784
+ };
785
+ }
786
+ }
787
+
788
+ return { valid: true };
789
+ }
790
+
791
+ _checkNoSQLInjection(input) {
792
+ // Check for MongoDB operators
793
+ const nosqlPatterns = [
794
+ /\$where/i,
795
+ /\$ne/i,
796
+ /\$gt/i,
797
+ /\$lt/i,
798
+ /\$regex/i,
799
+ /\$in/i,
800
+ /\$nin/i,
801
+ /\$or/i,
802
+ /\$and/i
803
+ ];
804
+
805
+ const inputStr = typeof input === 'object' ? JSON.stringify(input) : input;
806
+
807
+ for (const pattern of nosqlPatterns) {
808
+ if (pattern.test(inputStr)) {
809
+ return {
810
+ valid: false,
811
+ error: 'NoSQL injection pattern detected'
812
+ };
813
+ }
814
+ }
815
+
816
+ return { valid: true };
817
+ }
818
+
819
+ _checkCommandInjection(input) {
820
+ const cmdChars = ['|', '&', ';', '`', '$', '(', ')', '<', '>', '\n', '\r'];
821
+
822
+ for (const char of cmdChars) {
823
+ if (input.includes(char)) {
824
+ return {
825
+ valid: false,
826
+ error: 'Command injection character detected',
827
+ char: char
828
+ };
829
+ }
830
+ }
831
+
832
+ return { valid: true };
833
+ }
834
+
835
+ _checkPathTraversal(input) {
836
+ const pathPatterns = [
837
+ /\.\.\//,
838
+ /\.\.\\/,
839
+ /%2e%2e%2f/i,
840
+ /%2e%2e%5c/i,
841
+ /\.\.%2f/i,
842
+ /\.\.%5c/i
843
+ ];
844
+
845
+ for (const pattern of pathPatterns) {
846
+ if (pattern.test(input)) {
847
+ return {
848
+ valid: false,
849
+ error: 'Path traversal pattern detected'
850
+ };
851
+ }
852
+ }
853
+
854
+ return { valid: true };
855
+ }
856
+ ```
857
+
858
+ ### Usage in Controllers
859
+
860
+ ```javascript
861
+ class UserController {
862
+ async search(obj) {
863
+ const query = this.params.q;
864
+
865
+ // Validate input
866
+ const validation = this.validateInput(query, 'string');
867
+ if (!validation.valid) {
868
+ return this.returnError(400, validation.error);
869
+ }
870
+
871
+ // Safe to query database
872
+ const results = await User.search(query);
873
+ this.returnJson(results);
874
+ }
875
+
876
+ async uploadFile(obj) {
877
+ const filename = this.params.filename;
878
+
879
+ // Check for path traversal
880
+ const validation = this.validateInput(filename, 'filename');
881
+ if (!validation.valid) {
882
+ return this.returnError(400, 'Invalid filename');
883
+ }
884
+
885
+ // Safe to write file
886
+ await fs.writeFile(`uploads/${filename}`, fileData);
887
+ }
888
+ }
889
+ ```
890
+
891
+ ---
892
+
893
+ ## XSS Prevention
894
+
895
+ ### Business Logic
896
+
897
+ **XSS (Cross-Site Scripting) prevention** protects against malicious JavaScript injection through multi-layer HTML sanitization.
898
+
899
+ #### Defense Layers
900
+
901
+ 1. **Tag Removal** - Remove dangerous tags (`<script>`, `<iframe>`, `<object>`)
902
+ 2. **Attribute Removal** - Remove event handlers (`onclick`, `onerror`)
903
+ 3. **Protocol Sanitization** - Block dangerous protocols (`javascript:`, `data:`)
904
+ 4. **CSS Sanitization** - Remove CSS expressions
905
+ 5. **Whitelist Approach** - Only allow safe tags/attributes
906
+
907
+ ### Workflow
908
+
909
+ ```
910
+ User Input (HTML)
911
+
912
+ [MasterSanitizer.sanitizeHTML()]
913
+
914
+ Input: "<script>alert('XSS')</script><p onclick='hack()'>Hello</p>"
915
+
916
+ Layer 1: Remove dangerous tags
917
+ → <p onclick='hack()'>Hello</p>
918
+
919
+ Layer 2: Remove event attributes
920
+ → <p>Hello</p>
921
+
922
+ Layer 3: Check protocols
923
+ → (none to check)
924
+
925
+ Layer 4: Sanitize CSS
926
+ → (no inline styles)
927
+
928
+ Output: "<p>Hello</p>"
929
+
930
+ ✓ Safe HTML
931
+ ```
932
+
933
+ ### Implementation
934
+
935
+ **MasterSanitizer.js (Lines 25-350)**
936
+
937
+ ```javascript
938
+ sanitizeHTML(html) {
939
+ if (!html || typeof html !== 'string') return '';
940
+
941
+ let sanitized = html;
942
+
943
+ // Layer 1: Remove dangerous tags
944
+ sanitized = this._removeDangerousTags(sanitized);
945
+
946
+ // Layer 2: Remove event attributes
947
+ sanitized = this._removeEventAttributes(sanitized);
948
+
949
+ // Layer 3: Sanitize protocols
950
+ sanitized = this._sanitizeProtocols(sanitized);
951
+
952
+ // Layer 4: Sanitize CSS
953
+ sanitized = this._sanitizeCSS(sanitized);
954
+
955
+ return sanitized;
956
+ }
957
+
958
+ _removeDangerousTags(html) {
959
+ const dangerousTags = [
960
+ 'script', 'iframe', 'object', 'embed',
961
+ 'applet', 'meta', 'link', 'style',
962
+ 'form', 'input', 'button', 'textarea',
963
+ 'select', 'option', 'base'
964
+ ];
965
+
966
+ let result = html;
967
+
968
+ for (const tag of dangerousTags) {
969
+ // Remove opening and closing tags (case-insensitive)
970
+ const openRegex = new RegExp(`<${tag}[^>]*>`, 'gi');
971
+ const closeRegex = new RegExp(`</${tag}>`, 'gi');
972
+
973
+ result = result.replace(openRegex, '');
974
+ result = result.replace(closeRegex, '');
975
+ }
976
+
977
+ return result;
978
+ }
979
+
980
+ _removeEventAttributes(html) {
981
+ // Remove all event handler attributes
982
+ const eventPattern = /\s+on\w+\s*=\s*["'][^"']*["']/gi;
983
+ return html.replace(eventPattern, '');
984
+ }
985
+
986
+ _sanitizeProtocols(html) {
987
+ // Block dangerous protocols
988
+ const dangerousProtocols = [
989
+ 'javascript:',
990
+ 'data:',
991
+ 'vbscript:',
992
+ 'file:',
993
+ 'about:'
994
+ ];
995
+
996
+ let result = html;
997
+
998
+ for (const protocol of dangerousProtocols) {
999
+ const regex = new RegExp(protocol, 'gi');
1000
+ result = result.replace(regex, '');
1001
+ }
1002
+
1003
+ return result;
1004
+ }
1005
+
1006
+ _sanitizeCSS(html) {
1007
+ // Remove dangerous CSS patterns
1008
+ const dangerousCSS = [
1009
+ /expression\s*\(/gi,
1010
+ /javascript\s*:/gi,
1011
+ /import\s+/gi,
1012
+ /@import/gi,
1013
+ /url\s*\(\s*["']?javascript:/gi
1014
+ ];
1015
+
1016
+ let result = html;
1017
+
1018
+ for (const pattern of dangerousCSS) {
1019
+ result = result.replace(pattern, '');
1020
+ }
1021
+
1022
+ return result;
1023
+ }
1024
+
1025
+ // Whitelist approach for rich text
1026
+ sanitizeRichText(html) {
1027
+ const allowedTags = [
1028
+ 'p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3',
1029
+ 'ul', 'ol', 'li', 'a', 'img', 'blockquote', 'code', 'pre'
1030
+ ];
1031
+
1032
+ const allowedAttributes = {
1033
+ 'a': ['href', 'title', 'target'],
1034
+ 'img': ['src', 'alt', 'width', 'height']
1035
+ };
1036
+
1037
+ // Parse HTML and rebuild with only allowed tags/attributes
1038
+ // (Implementation uses DOM parser or regex)
1039
+
1040
+ return sanitized;
1041
+ }
1042
+ ```
1043
+
1044
+ ### Usage in Controllers
1045
+
1046
+ ```javascript
1047
+ class CommentController {
1048
+ async create(obj) {
1049
+ const content = this.params.content;
1050
+
1051
+ // Sanitize user HTML input
1052
+ const sanitizedContent = this.sanitizeHTML(content);
1053
+
1054
+ // Safe to store and display
1055
+ const comment = await Comment.create({
1056
+ content: sanitizedContent,
1057
+ userId: this.currentUser.id
1058
+ });
1059
+
1060
+ this.returnJson(comment);
1061
+ }
1062
+ }
1063
+ ```
1064
+
1065
+ ### Template Usage
1066
+
1067
+ ```javascript
1068
+ // MasterTemplate automatically sanitizes variables
1069
+ class MasterTemplate {
1070
+ render(template, data) {
1071
+ return template.replace(/\${(\w+)}/g, (match, key) => {
1072
+ const value = data[key];
1073
+ // Automatic HTML escaping
1074
+ return this._escapeHTML(value);
1075
+ });
1076
+ }
1077
+
1078
+ _escapeHTML(str) {
1079
+ const htmlEscapes = {
1080
+ '&': '&amp;',
1081
+ '<': '&lt;',
1082
+ '>': '&gt;',
1083
+ '"': '&quot;',
1084
+ "'": '&#39;'
1085
+ };
1086
+
1087
+ return String(str).replace(/[&<>"']/g, char => htmlEscapes[char]);
1088
+ }
1089
+ }
1090
+ ```
1091
+
1092
+ ---
1093
+
1094
+ ## Event Handler Validation
1095
+
1096
+ ### Business Logic
1097
+
1098
+ **Event handler validation** ensures Web Component `@event` bindings are safe and don't allow arbitrary code execution.
1099
+
1100
+ #### Validation Rules
1101
+
1102
+ 1. **Syntax Validation** - Ensure handler uses correct syntax
1103
+ 2. **Dangerous Pattern Detection** - Block `eval()`, `Function()`, etc.
1104
+ 3. **Scoped Execution** - Handlers can only call controller methods
1105
+ 4. **No Inline Code** - Block inline JavaScript in attributes
1106
+
1107
+ ### Implementation
1108
+
1109
+ **EventHandlerValidator.js (Lines 20-300)**
1110
+
1111
+ ```javascript
1112
+ validateEventHandler(eventName, handlerCode, componentName) {
1113
+ // Check syntax
1114
+ if (!this._isValidSyntax(handlerCode)) {
1115
+ logger.error({
1116
+ code: 'INVALID_EVENT_SYNTAX',
1117
+ component: componentName,
1118
+ event: eventName,
1119
+ handler: handlerCode
1120
+ });
1121
+ return false;
1122
+ }
1123
+
1124
+ // Check for dangerous patterns
1125
+ if (this._containsDangerousPattern(handlerCode)) {
1126
+ logger.error({
1127
+ code: 'DANGEROUS_EVENT_HANDLER',
1128
+ component: componentName,
1129
+ event: eventName
1130
+ });
1131
+ return false;
1132
+ }
1133
+
1134
+ return true;
1135
+ }
1136
+
1137
+ _isValidSyntax(handlerCode) {
1138
+ // Valid: "methodName()" or "obj.methodName()"
1139
+ const validPattern = /^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*\(\)$/;
1140
+ return validPattern.test(handlerCode);
1141
+ }
1142
+
1143
+ _containsDangerousPattern(handlerCode) {
1144
+ const dangerousPatterns = [
1145
+ /eval\(/,
1146
+ /Function\(/,
1147
+ /setTimeout\(/,
1148
+ /setInterval\(/,
1149
+ /new Function/,
1150
+ /constructor/,
1151
+ /__proto__/,
1152
+ /prototype/
1153
+ ];
1154
+
1155
+ return dangerousPatterns.some(pattern => pattern.test(handlerCode));
1156
+ }
1157
+ ```
1158
+
1159
+ ### Usage in SSR
1160
+
1161
+ ```javascript
1162
+ // runtime-ssr.cjs (Lines 450-500)
1163
+ function validateComponentEvents(component) {
1164
+ const eventAttributes = component.getAttributeNames()
1165
+ .filter(attr => attr.startsWith('@'));
1166
+
1167
+ for (const attr of eventAttributes) {
1168
+ const eventName = attr.substring(1); // Remove '@'
1169
+ const handlerCode = component.getAttribute(attr);
1170
+
1171
+ // Validate handler
1172
+ const isValid = eventValidator.validateEventHandler(
1173
+ eventName,
1174
+ handlerCode,
1175
+ component.tagName
1176
+ );
1177
+
1178
+ if (!isValid) {
1179
+ // Remove dangerous handler
1180
+ component.removeAttribute(attr);
1181
+
1182
+ logger.warn({
1183
+ code: 'EVENT_HANDLER_REMOVED',
1184
+ component: component.tagName,
1185
+ event: eventName
1186
+ });
1187
+ }
1188
+ }
1189
+ }
1190
+ ```
1191
+
1192
+ ---
1193
+
1194
+ ## Content Security Policy
1195
+
1196
+ ### Business Logic
1197
+
1198
+ **CSP (Content Security Policy)** defines approved sources for scripts, styles, images, and other resources, preventing XSS and data injection attacks.
1199
+
1200
+ ### Presets
1201
+
1202
+ #### Development Preset (Permissive)
1203
+ ```javascript
1204
+ {
1205
+ 'default-src': ["'self'"],
1206
+ 'script-src': ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
1207
+ 'style-src': ["'self'", "'unsafe-inline'"],
1208
+ 'img-src': ["'self'", "data:", "https:"],
1209
+ 'connect-src': ["'self'", "ws:", "wss:"]
1210
+ }
1211
+ ```
1212
+
1213
+ #### Production Preset (Strict)
1214
+ ```javascript
1215
+ {
1216
+ 'default-src': ["'self'"],
1217
+ 'script-src': ["'self'", "'nonce-{random}'"],
1218
+ 'style-src': ["'self'", "'nonce-{random}'"],
1219
+ 'img-src': ["'self'", "https:"],
1220
+ 'connect-src': ["'self'"],
1221
+ 'object-src': ["'none'"],
1222
+ 'base-uri': ["'self'"],
1223
+ 'form-action': ["'self'"]
1224
+ }
1225
+ ```
1226
+
1227
+ #### CDN Preset
1228
+ ```javascript
1229
+ {
1230
+ 'default-src': ["'self'"],
1231
+ 'script-src': [
1232
+ "'self'",
1233
+ "'nonce-{random}'",
1234
+ "https://cdn.jsdelivr.net",
1235
+ "https://unpkg.com"
1236
+ ],
1237
+ 'style-src': [
1238
+ "'self'",
1239
+ "'nonce-{random}'",
1240
+ "https://fonts.googleapis.com"
1241
+ ],
1242
+ 'font-src': [
1243
+ "'self'",
1244
+ "https://fonts.gstatic.com"
1245
+ ]
1246
+ }
1247
+ ```
1248
+
1249
+ ### Implementation
1250
+
1251
+ **CSPConfig.js (Lines 15-250)**
1252
+
1253
+ ```javascript
1254
+ class CSPConfig {
1255
+ constructor() {
1256
+ this.presets = {
1257
+ development: { /* ... */ },
1258
+ production: { /* ... */ },
1259
+ cdn: { /* ... */ }
1260
+ };
1261
+ }
1262
+
1263
+ generateCSPHeader(preset = 'production', customRules = {}) {
1264
+ const config = { ...this.presets[preset], ...customRules };
1265
+
1266
+ // Generate nonce for inline scripts
1267
+ const nonce = crypto.randomBytes(16).toString('base64');
1268
+
1269
+ // Build CSP directives
1270
+ const directives = [];
1271
+
1272
+ for (const [directive, sources] of Object.entries(config)) {
1273
+ const sourcesStr = sources
1274
+ .map(src => src.replace('{random}', nonce))
1275
+ .join(' ');
1276
+ directives.push(`${directive} ${sourcesStr}`);
1277
+ }
1278
+
1279
+ return {
1280
+ header: directives.join('; '),
1281
+ nonce: nonce
1282
+ };
1283
+ }
1284
+ }
1285
+ ```
1286
+
1287
+ ### Usage in Middleware
1288
+
1289
+ ```javascript
1290
+ // SecurityMiddleware.js
1291
+ checkRequest(requestObject) {
1292
+ // Generate CSP
1293
+ const { header, nonce } = this.cspConfig.generateCSPHeader('production');
1294
+
1295
+ // Inject header
1296
+ requestObject.response.setHeader('Content-Security-Policy', header);
1297
+
1298
+ // Store nonce for template rendering
1299
+ requestObject.cspNonce = nonce;
1300
+ }
1301
+ ```
1302
+
1303
+ ### Template Usage
1304
+
1305
+ ```html
1306
+ <!DOCTYPE html>
1307
+ <html>
1308
+ <head>
1309
+ <!-- Inline script with nonce -->
1310
+ <script nonce="${cspNonce}">
1311
+ console.log('Safe inline script');
1312
+ </script>
1313
+
1314
+ <!-- External script (allowed by CSP) -->
1315
+ <script src="/app.js"></script>
1316
+ </head>
1317
+ </html>
1318
+ ```
1319
+
1320
+ ---
1321
+
1322
+ ## Configuration Guide
1323
+
1324
+ ### Production Configuration
1325
+
1326
+ **config/security.js**
1327
+
1328
+ ```javascript
1329
+ module.exports = {
1330
+ // CSRF Protection
1331
+ csrf: {
1332
+ enabled: true,
1333
+ tokenLength: 32,
1334
+ expiryMs: 3600000, // 1 hour
1335
+ oneTimeUse: true
1336
+ },
1337
+
1338
+ // Rate Limiting
1339
+ rateLimit: {
1340
+ enabled: true,
1341
+ windowMs: 15 * 60 * 1000, // 15 minutes
1342
+ maxRequests: 100, // 100 requests per window
1343
+ whitelist: ['127.0.0.1'], // Exempt IPs
1344
+ storage: 'redis', // redis or memory
1345
+ redisUrl: 'redis://localhost:6379'
1346
+ },
1347
+
1348
+ // Session Security
1349
+ session: {
1350
+ enabled: true,
1351
+ fingerprintEnabled: true,
1352
+ timeoutMs: 60 * 60 * 1000, // 60 minutes
1353
+ regenerateOnAuth: true,
1354
+ maxConcurrentSessions: 3,
1355
+ cookieOptions: {
1356
+ httpOnly: true,
1357
+ secure: true, // HTTPS only
1358
+ sameSite: 'strict',
1359
+ maxAge: 3600
1360
+ }
1361
+ },
1362
+
1363
+ // Input Validation
1364
+ validation: {
1365
+ enabled: true,
1366
+ strictMode: true,
1367
+ logBlocked: true
1368
+ },
1369
+
1370
+ // XSS Prevention
1371
+ sanitization: {
1372
+ enabled: true,
1373
+ allowRichText: false, // Strict sanitization
1374
+ whitelistTags: ['p', 'br', 'strong', 'em']
1375
+ },
1376
+
1377
+ // Content Security Policy
1378
+ csp: {
1379
+ enabled: true,
1380
+ preset: 'production',
1381
+ customRules: {
1382
+ 'script-src': ["'self'", "https://trusted-cdn.com"]
1383
+ },
1384
+ reportUri: '/csp-report'
1385
+ },
1386
+
1387
+ // Security Headers
1388
+ headers: {
1389
+ 'X-Frame-Options': 'DENY',
1390
+ 'X-Content-Type-Options': 'nosniff',
1391
+ 'X-XSS-Protection': '1; mode=block',
1392
+ 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
1393
+ 'Referrer-Policy': 'no-referrer-when-downgrade'
1394
+ }
1395
+ };
1396
+ ```
1397
+
1398
+ ### Initialization
1399
+
1400
+ **config/initializers/security.js**
1401
+
1402
+ ```javascript
1403
+ const master = require('mastercontroller');
1404
+ const securityConfig = require('../security');
1405
+
1406
+ // Initialize security modules
1407
+ master.securityMiddleware.configure(securityConfig);
1408
+ master.sessionSecurity.configure(securityConfig.session);
1409
+ master.cspConfig.setPreset(securityConfig.csp.preset);
1410
+
1411
+ // Enable automatic enforcement
1412
+ master.securityEnforcement.enable({
1413
+ autoCSRF: true,
1414
+ autoRateLimit: true,
1415
+ autoHeaders: true
1416
+ });
1417
+
1418
+ console.log('[Security] Initialized with production configuration');
1419
+ ```
1420
+
1421
+ ---
1422
+
1423
+ ## Best Practices
1424
+
1425
+ ### 1. Always Validate User Input
1426
+
1427
+ ```javascript
1428
+ // ❌ BAD - No validation
1429
+ class UserController {
1430
+ async search(obj) {
1431
+ const query = this.params.q;
1432
+ const results = await User.search(query); // SQL injection risk!
1433
+ this.returnJson(results);
1434
+ }
1435
+ }
1436
+
1437
+ // ✅ GOOD - Validate before use
1438
+ class UserController {
1439
+ async search(obj) {
1440
+ const query = this.params.q;
1441
+
1442
+ // Validate input
1443
+ const validation = this.validateInput(query, 'string');
1444
+ if (!validation.valid) {
1445
+ return this.returnError(400, validation.error);
1446
+ }
1447
+
1448
+ const results = await User.search(query);
1449
+ this.returnJson(results);
1450
+ }
1451
+ }
1452
+ ```
1453
+
1454
+ ### 2. Sanitize HTML Output
1455
+
1456
+ ```javascript
1457
+ // ❌ BAD - Raw HTML from user
1458
+ class CommentController {
1459
+ async show(obj) {
1460
+ const comment = await Comment.findById(this.params.id);
1461
+ // XSS risk if comment.content contains <script>
1462
+ this.returnView({ content: comment.content });
1463
+ }
1464
+ }
1465
+
1466
+ // ✅ GOOD - Sanitize HTML
1467
+ class CommentController {
1468
+ async show(obj) {
1469
+ const comment = await Comment.findById(this.params.id);
1470
+ const sanitized = this.sanitizeHTML(comment.content);
1471
+ this.returnView({ content: sanitized });
1472
+ }
1473
+ }
1474
+ ```
1475
+
1476
+ ### 3. Use CSRF Tokens for State-Changing Requests
1477
+
1478
+ ```javascript
1479
+ // ❌ BAD - No CSRF protection
1480
+ class AccountController {
1481
+ deleteAccount(obj) {
1482
+ // Anyone can call this endpoint!
1483
+ User.delete(this.currentUser.id);
1484
+ this.redirectTo('/');
1485
+ }
1486
+ }
1487
+
1488
+ // ✅ GOOD - CSRF token required
1489
+ class AccountController {
1490
+ showDeleteForm(obj) {
1491
+ const csrfToken = this.generateCSRFToken();
1492
+ this.returnView({ csrfToken });
1493
+ }
1494
+
1495
+ deleteAccount(obj) {
1496
+ // CSRF automatically validated by SecurityMiddleware
1497
+ User.delete(this.currentUser.id);
1498
+ this.redirectTo('/');
1499
+ }
1500
+ }
1501
+ ```
1502
+
1503
+ ### 4. Regenerate Sessions After Authentication
1504
+
1505
+ ```javascript
1506
+ // ❌ BAD - Session fixation risk
1507
+ class AuthController {
1508
+ async login(obj) {
1509
+ const user = await User.authenticate(this.params.username, this.params.password);
1510
+ this.__session.userId = user.id; // Session fixation!
1511
+ this.redirectTo('/dashboard');
1512
+ }
1513
+ }
1514
+
1515
+ // ✅ GOOD - Regenerate session
1516
+ class AuthController {
1517
+ async login(obj) {
1518
+ const user = await User.authenticate(this.params.username, this.params.password);
1519
+
1520
+ // Regenerate session ID
1521
+ const oldSessionId = this.__session.id;
1522
+ const newSessionId = this.regenerateSession(oldSessionId, this.__requestObject);
1523
+
1524
+ this.redirectTo('/dashboard');
1525
+ }
1526
+ }
1527
+ ```
1528
+
1529
+ ### 5. Use Parameterized Queries
1530
+
1531
+ ```javascript
1532
+ // ❌ BAD - SQL injection risk
1533
+ class UserController {
1534
+ async search(obj) {
1535
+ const query = `SELECT * FROM users WHERE name = '${this.params.name}'`;
1536
+ const results = await db.query(query); // Dangerous!
1537
+ this.returnJson(results);
1538
+ }
1539
+ }
1540
+
1541
+ // ✅ GOOD - Parameterized query
1542
+ class UserController {
1543
+ async search(obj) {
1544
+ // ORM handles parameterization
1545
+ const results = await User.where({ name: this.params.name });
1546
+ this.returnJson(results);
1547
+ }
1548
+ }
1549
+ ```
1550
+
1551
+ ### 6. Set Secure Cookie Flags
1552
+
1553
+ ```javascript
1554
+ // ❌ BAD - Insecure cookies
1555
+ response.setHeader('Set-Cookie', `sessionId=${id}; Path=/`);
1556
+
1557
+ // ✅ GOOD - Secure cookies
1558
+ response.setHeader('Set-Cookie',
1559
+ `sessionId=${id}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600`
1560
+ );
1561
+ ```
1562
+
1563
+ ### 7. Use CSP in Production
1564
+
1565
+ ```javascript
1566
+ // ❌ BAD - No CSP
1567
+ // Vulnerable to XSS attacks
1568
+
1569
+ // ✅ GOOD - Strict CSP
1570
+ const { header, nonce } = this.cspConfig.generateCSPHeader('production');
1571
+ response.setHeader('Content-Security-Policy', header);
1572
+ ```
1573
+
1574
+ ### 8. Log Security Events
1575
+
1576
+ ```javascript
1577
+ // ✅ GOOD - Comprehensive logging
1578
+ logger.warn({
1579
+ code: 'RATE_LIMIT_EXCEEDED',
1580
+ ip: requestObject.ip,
1581
+ userAgent: requestObject.headers['user-agent'],
1582
+ count: attempts,
1583
+ timestamp: Date.now()
1584
+ });
1585
+ ```
1586
+
1587
+ ---
1588
+
1589
+ ## Monitoring & Logging
1590
+
1591
+ ### Security Event Codes
1592
+
1593
+ | Code | Description | Severity | Action |
1594
+ |------|-------------|----------|--------|
1595
+ | `CSRF_VALIDATION_FAILED` | CSRF token invalid/missing | HIGH | Block request |
1596
+ | `RATE_LIMIT_EXCEEDED` | Too many requests | MEDIUM | Block request (429) |
1597
+ | `SESSION_HIJACK_DETECTED` | Fingerprint mismatch | CRITICAL | Destroy session |
1598
+ | `SESSION_TIMEOUT` | Session expired | LOW | Redirect to login |
1599
+ | `SQL_INJECTION_DETECTED` | SQL pattern found | CRITICAL | Block + alert |
1600
+ | `NOSQL_INJECTION_DETECTED` | NoSQL operator found | CRITICAL | Block + alert |
1601
+ | `COMMAND_INJECTION_DETECTED` | Shell metachar found | CRITICAL | Block + alert |
1602
+ | `PATH_TRAVERSAL_DETECTED` | Directory escape found | HIGH | Block request |
1603
+ | `XSS_SANITIZED` | Dangerous HTML removed | MEDIUM | Log + sanitize |
1604
+ | `INVALID_EVENT_SYNTAX` | Bad @event handler | MEDIUM | Remove handler |
1605
+ | `CSP_VIOLATION` | CSP rule broken | MEDIUM | Log + investigate |
1606
+
1607
+ ### Log Analysis Queries
1608
+
1609
+ ```bash
1610
+ # Failed CSRF attempts (potential attack)
1611
+ grep "CSRF_VALIDATION_FAILED" logs/security.log | wc -l
1612
+
1613
+ # Rate limit violations by IP
1614
+ grep "RATE_LIMIT_EXCEEDED" logs/security.log | awk '{print $4}' | sort | uniq -c | sort -nr
1615
+
1616
+ # Session hijack attempts
1617
+ grep "SESSION_HIJACK_DETECTED" logs/security.log
1618
+
1619
+ # Injection attack attempts
1620
+ grep -E "(SQL|NOSQL|COMMAND)_INJECTION_DETECTED" logs/security.log
1621
+ ```
1622
+
1623
+ ---
1624
+
1625
+ ## Testing
1626
+
1627
+ ### Security Test Suite
1628
+
1629
+ **test/security/csrf.test.js**
1630
+
1631
+ ```javascript
1632
+ const request = require('supertest');
1633
+ const app = require('../../server');
1634
+
1635
+ describe('CSRF Protection', () => {
1636
+ it('should block POST without CSRF token', async () => {
1637
+ const res = await request(app)
1638
+ .post('/user/create')
1639
+ .send({ name: 'Test' });
1640
+
1641
+ expect(res.status).toBe(403);
1642
+ });
1643
+
1644
+ it('should allow POST with valid CSRF token', async () => {
1645
+ // Get token
1646
+ const tokenRes = await request(app).get('/form');
1647
+ const token = extractCSRFToken(tokenRes.text);
1648
+
1649
+ // Submit with token
1650
+ const res = await request(app)
1651
+ .post('/user/create')
1652
+ .send({ name: 'Test', _csrf: token });
1653
+
1654
+ expect(res.status).toBe(200);
1655
+ });
1656
+ });
1657
+ ```
1658
+
1659
+ **test/security/rate-limit.test.js**
1660
+
1661
+ ```javascript
1662
+ describe('Rate Limiting', () => {
1663
+ it('should block after 100 requests', async () => {
1664
+ // Make 100 requests
1665
+ for (let i = 0; i < 100; i++) {
1666
+ await request(app).get('/');
1667
+ }
1668
+
1669
+ // 101st request should be blocked
1670
+ const res = await request(app).get('/');
1671
+ expect(res.status).toBe(429);
1672
+ });
1673
+ });
1674
+ ```
1675
+
1676
+ ---
1677
+
1678
+ ## Troubleshooting
1679
+
1680
+ ### Common Issues
1681
+
1682
+ #### 1. CSRF Validation Failing
1683
+
1684
+ **Symptom:** Forms return 403 Forbidden
1685
+
1686
+ **Causes:**
1687
+ - Token not included in form
1688
+ - Token expired (> 1 hour)
1689
+ - Session not persisted
1690
+
1691
+ **Solution:**
1692
+ ```javascript
1693
+ // Ensure token is embedded
1694
+ <input type="hidden" name="_csrf" value="${csrfToken}">
1695
+
1696
+ // Check session storage
1697
+ console.log(this.__session.id); // Should be defined
1698
+ ```
1699
+
1700
+ #### 2. Rate Limit Too Aggressive
1701
+
1702
+ **Symptom:** Legitimate users blocked
1703
+
1704
+ **Solution:**
1705
+ ```javascript
1706
+ // Increase limits in config/security.js
1707
+ rateLimit: {
1708
+ windowMs: 15 * 60 * 1000,
1709
+ maxRequests: 200, // Increase from 100
1710
+ whitelist: ['192.168.1.0/24'] // Exempt internal network
1711
+ }
1712
+ ```
1713
+
1714
+ #### 3. Session Hijack False Positives
1715
+
1716
+ **Symptom:** Users logged out unexpectedly
1717
+
1718
+ **Causes:**
1719
+ - Mobile users switching networks
1720
+ - Users behind proxy with rotating IPs
1721
+
1722
+ **Solution:**
1723
+ ```javascript
1724
+ // Disable fingerprinting or use less strict validation
1725
+ session: {
1726
+ fingerprintEnabled: false, // Disable IP check
1727
+ // OR
1728
+ fingerprintStrict: false // Only check User-Agent
1729
+ }
1730
+ ```
1731
+
1732
+ #### 4. CSP Blocking Resources
1733
+
1734
+ **Symptom:** Scripts/styles not loading
1735
+
1736
+ **Solution:**
1737
+ ```javascript
1738
+ // Add trusted sources to CSP
1739
+ csp: {
1740
+ customRules: {
1741
+ 'script-src': ["'self'", "https://trusted-cdn.com"],
1742
+ 'style-src': ["'self'", "https://fonts.googleapis.com"]
1743
+ }
1744
+ }
1745
+
1746
+ // OR use 'unsafe-inline' in development (NOT production!)
1747
+ csp: {
1748
+ preset: 'development'
1749
+ }
1750
+ ```
1751
+
1752
+ ---
1753
+
1754
+ ## Migration Guide
1755
+
1756
+ ### Upgrading Existing Projects
1757
+
1758
+ **Step 1:** Update dependencies
1759
+ ```bash
1760
+ npm install mastercontroller@latest
1761
+ ```
1762
+
1763
+ **Step 2:** Enable security modules in config
1764
+ ```javascript
1765
+ // config/initializers/security.js
1766
+ const securityConfig = require('../security');
1767
+ master.securityMiddleware.configure(securityConfig);
1768
+ ```
1769
+
1770
+ **Step 3:** Add CSRF tokens to forms
1771
+ ```html
1772
+ <input type="hidden" name="_csrf" value="${csrfToken}">
1773
+ ```
1774
+
1775
+ **Step 4:** Update controllers
1776
+ ```javascript
1777
+ class FormController {
1778
+ showForm(obj) {
1779
+ const csrfToken = this.generateCSRFToken();
1780
+ this.returnView({ csrfToken });
1781
+ }
1782
+ }
1783
+ ```
1784
+
1785
+ **Step 5:** Test thoroughly
1786
+ ```bash
1787
+ npm test
1788
+ ```
1789
+
1790
+ ---
1791
+
1792
+ ## Support
1793
+
1794
+ For security issues or questions:
1795
+
1796
+ 1. Review this documentation
1797
+ 2. Check logs: `logs/security.log`
1798
+ 3. Run security tests: `npm run test:security`
1799
+ 4. Report security vulnerabilities privately (do not open public issues)
1800
+
1801
+ ---
1802
+
1803
+ **Last Updated:** 2026-01-29
1804
+ **Version:** 1.0.0
1805
+ **Maintained By:** MasterController Security Team