cyberaudit-skill 3.0.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.
Files changed (60) hide show
  1. package/README.md +77 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +241 -0
  4. package/dist/mcp-server.d.ts +2 -0
  5. package/dist/mcp-server.js +126 -0
  6. package/package.json +58 -0
  7. package/skills/cyberaudit/AGENT-BOOT.md +122 -0
  8. package/skills/cyberaudit/COMMANDS.md +1125 -0
  9. package/skills/cyberaudit/INSTALL.md +311 -0
  10. package/skills/cyberaudit/MASTER.md +194 -0
  11. package/skills/cyberaudit/README.md +154 -0
  12. package/skills/cyberaudit/USAGE-GUIDE.md +107 -0
  13. package/skills/cyberaudit/mobile/MOBILE-CHECKLIST.md +245 -0
  14. package/skills/cyberaudit/mobile/MOBILE-PHILOSOPHY.md +352 -0
  15. package/skills/cyberaudit/mobile/MOBILE-REMEDIATION-LIBRARY.md +468 -0
  16. package/skills/cyberaudit/mobile/MOBILE-THREAT-MODELS.md +279 -0
  17. package/skills/cyberaudit/mobile/frameworks/EXPO.md +247 -0
  18. package/skills/cyberaudit/mobile/frameworks/FLUTTER.md +338 -0
  19. package/skills/cyberaudit/mobile/frameworks/IONIC.md +248 -0
  20. package/skills/cyberaudit/mobile/frameworks/REACT-NATIVE.md +479 -0
  21. package/skills/cyberaudit/mobile/vulnerabilities/AUTH-MOBILE.md +160 -0
  22. package/skills/cyberaudit/mobile/vulnerabilities/BINARY-ANALYSIS.md +193 -0
  23. package/skills/cyberaudit/mobile/vulnerabilities/CRYPTO-MOBILE.md +192 -0
  24. package/skills/cyberaudit/mobile/vulnerabilities/IPC-DEEPLINKS.md +231 -0
  25. package/skills/cyberaudit/mobile/vulnerabilities/NETWORK-MOBILE.md +165 -0
  26. package/skills/cyberaudit/mobile/vulnerabilities/PERMISSIONS.md +180 -0
  27. package/skills/cyberaudit/mobile/vulnerabilities/RUNTIME-MOBILE.md +214 -0
  28. package/skills/cyberaudit/mobile/vulnerabilities/STORAGE.md +197 -0
  29. package/skills/cyberaudit/reports/EXECUTIVE-SUMMARY-TEMPLATE.md +188 -0
  30. package/skills/cyberaudit/reports/REPORT-TEMPLATE-MOBILE.md +410 -0
  31. package/skills/cyberaudit/reports/REPORT-TEMPLATE-WEB.md +222 -0
  32. package/skills/cyberaudit/shared/COMPLIANCE.md +307 -0
  33. package/skills/cyberaudit/shared/CVSS-GUIDE.md +175 -0
  34. package/skills/cyberaudit/shared/OWASP-MAPPER.md +130 -0
  35. package/skills/cyberaudit/shared/SEVERITY-SCORING.md +102 -0
  36. package/skills/cyberaudit/shared/THREAT-MODELING.md +112 -0
  37. package/skills/cyberaudit/web/WEB-CHECKLIST.md +222 -0
  38. package/skills/cyberaudit/web/WEB-PHILOSOPHY.md +308 -0
  39. package/skills/cyberaudit/web/WEB-REMEDIATION-LIBRARY.md +665 -0
  40. package/skills/cyberaudit/web/WEB-THREAT-MODELS.md +460 -0
  41. package/skills/cyberaudit/web/frameworks/ANGULAR.md +169 -0
  42. package/skills/cyberaudit/web/frameworks/EXPRESS.md +185 -0
  43. package/skills/cyberaudit/web/frameworks/LARAVEL.md +371 -0
  44. package/skills/cyberaudit/web/frameworks/NESTJS.md +337 -0
  45. package/skills/cyberaudit/web/frameworks/NEXTJS.md +352 -0
  46. package/skills/cyberaudit/web/frameworks/REACT.md +346 -0
  47. package/skills/cyberaudit/web/frameworks/VUE.md +205 -0
  48. package/skills/cyberaudit/web/vulnerabilities/AUTH-AUTHZ.md +117 -0
  49. package/skills/cyberaudit/web/vulnerabilities/BUSINESS-LOGIC.md +603 -0
  50. package/skills/cyberaudit/web/vulnerabilities/CORS.md +117 -0
  51. package/skills/cyberaudit/web/vulnerabilities/CSRF.md +131 -0
  52. package/skills/cyberaudit/web/vulnerabilities/DESERIALIZATION.md +96 -0
  53. package/skills/cyberaudit/web/vulnerabilities/HEADERS.md +105 -0
  54. package/skills/cyberaudit/web/vulnerabilities/IDOR-BOLA.md +153 -0
  55. package/skills/cyberaudit/web/vulnerabilities/INJECTION.md +165 -0
  56. package/skills/cyberaudit/web/vulnerabilities/SECRETS.md +119 -0
  57. package/skills/cyberaudit/web/vulnerabilities/SSRF.md +124 -0
  58. package/skills/cyberaudit/web/vulnerabilities/SUPPLY-CHAIN.md +142 -0
  59. package/skills/cyberaudit/web/vulnerabilities/XSS.md +133 -0
  60. package/skills/cyberaudit/web/vulnerabilities/XXE.md +94 -0
@@ -0,0 +1,185 @@
1
+ # 🚂 EXPRESS — SECURITY AUDIT GUIDE
2
+
3
+ ═══════════════════════════════════════════════════════════════
4
+ EXPRESS THREAT MODEL
5
+ ═══════════════════════════════════════════════════════════════
6
+
7
+ EXPRESS IS MINIMALIST.
8
+ What is a strength is also a danger.
9
+ No default protection.
10
+ Everything must be explicitly configured.
11
+ An Express audit = verify that everything was added manually.
12
+
13
+ SPECIFIC EXPRESS RISKS:
14
+ → No automatic input validation
15
+ → No built-in auth
16
+ → No CSRF protection by default
17
+ → Middleware in wrong order = bypass
18
+ → next() called after error = dangerous continuation
19
+
20
+ ═══════════════════════════════════════════════════════════════
21
+ VULNERABLE EXPRESS PATTERNS
22
+ ═══════════════════════════════════════════════════════════════
23
+
24
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
25
+ MIDDLEWARE ORDER
26
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
27
+
28
+ CRITICAL PATTERN — Auth middleware after routes
29
+ DETECT:
30
+ app.get('/admin/users', getUsers) // Route before middleware!
31
+ app.use(authMiddleware) // Too late!
32
+
33
+ FIX:
34
+ // Order matters: middleware first, routes next
35
+ app.use(helmet())
36
+ app.use(cors(corsOptions))
37
+ app.use(express.json({ limit: '10mb' }))
38
+ app.use(rateLimiter)
39
+ app.use(authMiddleware) // Auth BEFORE protected routes
40
+
41
+ // Public routes
42
+ app.post('/api/auth/login', loginHandler)
43
+ app.post('/api/auth/register', registerHandler)
44
+
45
+ // Protected routes (after auth middleware)
46
+ app.use('/api/admin', requireAdmin)
47
+ app.get('/api/admin/users', getUsers)
48
+
49
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
50
+ NEXT() AFTER AN ERROR
51
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
52
+
53
+ HIGH PATTERN — Continuation after auth error
54
+ DETECT:
55
+ const authMiddleware = (req, res, next) => {
56
+ const token = req.headers.authorization?.split(' ')[1]
57
+ if (!token) {
58
+ res.status(401).json({ error: 'No token' })
59
+ next() // ← CRITICAL BUG: continues despite the error!
60
+ }
61
+ // ...
62
+ }
63
+
64
+ FIX:
65
+ const authMiddleware = (req, res, next) => {
66
+ const token = req.headers.authorization?.split(' ')[1]
67
+
68
+ if (!token) {
69
+ return res.status(401).json({ error: 'Unauthorized' })
70
+ // return → do not call next()
71
+ }
72
+
73
+ try {
74
+ const payload = jwt.verify(token, process.env.JWT_SECRET, {
75
+ algorithms: ['HS256']
76
+ })
77
+ req.user = payload
78
+ next() // Called only if auth succeeds
79
+ } catch (error) {
80
+ return res.status(401).json({ error: 'Invalid token' })
81
+ // return → do not call next()
82
+ }
83
+ }
84
+
85
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
86
+ COMPLETE SECURE CONFIGURATION
87
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
88
+
89
+ SECURE EXPRESS APP
90
+ import express from 'express'
91
+ import helmet from 'helmet'
92
+ import cors from 'cors'
93
+ import rateLimit from 'express-rate-limit'
94
+ import mongoSanitize from 'express-mongo-sanitize'
95
+ import hpp from 'hpp'
96
+
97
+ const app = express()
98
+
99
+ // 1. Security headers
100
+ app.use(helmet({
101
+ contentSecurityPolicy: {
102
+ directives: {
103
+ defaultSrc: ["'self'"],
104
+ scriptSrc: ["'self'"],
105
+ styleSrc: ["'self'"],
106
+ imgSrc: ["'self'", 'data:'],
107
+ }
108
+ },
109
+ hsts: { maxAge: 31536000, includeSubDomains: true, preload: true }
110
+ }))
111
+
112
+ // 2. Remove X-Powered-By
113
+ app.disable('x-powered-by')
114
+
115
+ // 3. Restrictive CORS
116
+ app.use(cors({
117
+ origin: ['https://yourapp.com'],
118
+ credentials: true,
119
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
120
+ }))
121
+
122
+ // 4. Body parsing with limits
123
+ app.use(express.json({ limit: '10mb' }))
124
+ app.use(express.urlencoded({ extended: true, limit: '10mb' }))
125
+
126
+ // 5. NoSQL injection sanitization
127
+ app.use(mongoSanitize())
128
+
129
+ // 6. HPP (HTTP Parameter Pollution) protection
130
+ app.use(hpp())
131
+
132
+ // 7. Global rate limiting
133
+ app.use(rateLimit({
134
+ windowMs: 15 * 60 * 1000, // 15 minutes
135
+ max: 100,
136
+ standardHeaders: true,
137
+ legacyHeaders: false,
138
+ message: { error: 'Too many requests, try again later' }
139
+ }))
140
+
141
+ // 8. Specific rate limiting on auth
142
+ const authLimiter = rateLimit({
143
+ windowMs: 60 * 1000,
144
+ max: 5,
145
+ skipSuccessfulRequests: true,
146
+ })
147
+ app.use('/api/auth/login', authLimiter)
148
+ app.use('/api/auth/forgot-password', authLimiter)
149
+
150
+ // 9. Public routes
151
+ app.post('/api/auth/login', loginHandler)
152
+
153
+ // 10. Auth middleware for protected routes
154
+ app.use('/api', authMiddleware)
155
+
156
+ // 11. Protected routes
157
+ app.use('/api/users', userRouter)
158
+ app.use('/api/admin', adminMiddleware, adminRouter)
159
+
160
+ // 12. Global error handler (must be last)
161
+ app.use((err, req, res, next) => {
162
+ console.error(err) // Full log server-side
163
+ res.status(err.status || 500).json({
164
+ error: process.env.NODE_ENV === 'production'
165
+ ? 'An error occurred'
166
+ : err.message
167
+ })
168
+ })
169
+
170
+ ═══════════════════════════════════════════════════════════════
171
+ COMPLETE EXPRESS CHECKLIST
172
+ ═══════════════════════════════════════════════════════════════
173
+
174
+ □ Helmet configured first?
175
+ □ X-Powered-By disabled?
176
+ □ CORS with origin whitelist?
177
+ □ Body size limited?
178
+ □ Global + auth rate limiting?
179
+ □ Middleware in correct order?
180
+ □ next() never called after res.json() on error?
181
+ □ Global error handler last?
182
+ □ No error details exposed in prod?
183
+ □ mongoSanitize() if MongoDB used?
184
+ □ hpp() to prevent parameter pollution?
185
+ □ Input validation (joi, zod, express-validator)?
@@ -0,0 +1,371 @@
1
+ # 🐘 LARAVEL — SECURITY AUDIT GUIDE
2
+ # Comprehensive audit guide for Laravel applications
3
+
4
+ ═══════════════════════════════════════════════════════════════
5
+ COMPLETE LARAVEL THREAT MODEL
6
+ ═══════════════════════════════════════════════════════════════
7
+
8
+ LARAVEL ATTACK SURFACE
9
+ ──────────────────────────
10
+
11
+ LAYER 1 — ROUTES & MIDDLEWARE
12
+ Risks: Routes without auth, bypassed middleware,
13
+ rate limiting absent, CSRF disabled
14
+
15
+ LAYER 2 — CONTROLLERS & REQUESTS
16
+ Risks: Insufficient validation, mass assignment,
17
+ injection via request()->all()
18
+
19
+ LAYER 3 — ELOQUENT & DATABASE
20
+ Risks: Raw queries, whereRaw injection,
21
+ N+1 not critical but revealing
22
+
23
+ LAYER 4 — BLADE TEMPLATES
24
+ Risks: {!! !!} unsanitized, XSS via output
25
+
26
+ LAYER 5 — FILE SYSTEM
27
+ Risks: Upload path traversal, public storage
28
+ of sensitive files, MIME bypass
29
+
30
+ LAYER 6 — AUTHENTICATION
31
+ Risks: Auth bypass, mass assignment on User,
32
+ poorly implemented remember_me
33
+
34
+ LAYER 7 — CONFIGURATION
35
+ Risks: APP_DEBUG=true in prod, exposed .env,
36
+ weak encryption keys
37
+
38
+ LAYER 8 — DESERIALIZATION
39
+ Risks: unserialize() with user input,
40
+ Laravel gadget chains
41
+
42
+ ═══════════════════════════════════════════════════════════════
43
+ VULNERABLE LARAVEL PATTERNS
44
+ ═══════════════════════════════════════════════════════════════
45
+
46
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
47
+ SQL INJECTION
48
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
49
+
50
+ CRITICAL PATTERN 1 — DB::select with interpolation
51
+ DETECT:
52
+ DB::select("SELECT * FROM users WHERE id = $id")
53
+ DB::select("SELECT * FROM users WHERE email = '{$email}'")
54
+ DB::statement("DELETE FROM logs WHERE date < $date")
55
+
56
+ FIX:
57
+ DB::select("SELECT * FROM users WHERE id = ?", [$id])
58
+ DB::select("SELECT * FROM users WHERE email = ?", [$email])
59
+ // OR better with Eloquent
60
+ User::where('id', $id)->first()
61
+ User::where('email', $email)->first()
62
+
63
+ CRITICAL PATTERN 2 — whereRaw with direct variable
64
+ DETECT:
65
+ Model::whereRaw("name = '$name'")->get()
66
+ Model::whereRaw("status = " . $status)->get()
67
+ Model::whereRaw($request->filter)->get()
68
+
69
+ FIX:
70
+ Model::whereRaw("name = ?", [$name])->get()
71
+ Model::whereRaw("status = ?", [$status])->get()
72
+ // Validate allowed filters first
73
+ $allowedFilters = ['active', 'inactive', 'pending'];
74
+ if (!in_array($request->filter, $allowedFilters)) {
75
+ abort(400);
76
+ }
77
+
78
+ CRITICAL PATTERN 3 — orderByRaw with user input
79
+ DETECT:
80
+ Model::orderByRaw($request->sort)->get()
81
+ Model::orderByRaw($request->column . ' ' . $request->direction)
82
+
83
+ FIX:
84
+ $allowedColumns = ['name', 'email', 'created_at', 'updated_at'];
85
+ $allowedDirections = ['asc', 'desc'];
86
+
87
+ $column = in_array($request->sort, $allowedColumns)
88
+ ? $request->sort : 'created_at';
89
+ $direction = in_array($request->direction, $allowedDirections)
90
+ ? $request->direction : 'desc';
91
+
92
+ Model::orderBy($column, $direction)->get()
93
+
94
+ HIGH PATTERN 4 — havingRaw and groupByRaw
95
+ DETECT:
96
+ ->havingRaw($request->having)
97
+ ->groupByRaw($request->group)
98
+
99
+ FIX:
100
+ // Whitelist of allowed expressions
101
+ $allowedHaving = ['COUNT(*) > 5', 'SUM(amount) > 1000'];
102
+ // Never pass user input directly
103
+
104
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
105
+ MASS ASSIGNMENT
106
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
107
+
108
+ CRITICAL PATTERN 5 — create() with request()->all()
109
+ DETECT:
110
+ User::create($request->all())
111
+ Post::create($request->input())
112
+ $model->fill($request->all())
113
+ $model->update($request->all())
114
+
115
+ FIX:
116
+ // Option A: strict $fillable
117
+ // In the Model:
118
+ protected $fillable = ['name', 'email', 'bio'];
119
+ // NEVER: protected $guarded = []; // everything allowed
120
+
121
+ // Option B: validated() with FormRequest
122
+ User::create($request->validated())
123
+
124
+ // Option C: manual selection
125
+ User::create([
126
+ 'name' => $request->name,
127
+ 'email' => $request->email,
128
+ ])
129
+
130
+ // VERIFY these fields are NOT in $fillable:
131
+ // role, is_admin, is_verified, email_verified_at,
132
+ // balance, credits, stripe_id
133
+
134
+ CRITICAL PATTERN 6 — update() without whitelist
135
+ DETECT:
136
+ $user->update($request->all())
137
+ $user->update($data) // if $data comes from input
138
+
139
+ FIX:
140
+ $user->update($request->only(['name', 'bio', 'avatar']))
141
+ // OR
142
+ $user->update($request->validated())
143
+
144
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
145
+ BLADE XSS
146
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
147
+
148
+ HIGH PATTERN 7 — Unescaped output
149
+ DETECT:
150
+ {!! $userContent !!}
151
+ {!! $comment->body !!}
152
+ {!! $user->bio !!}
153
+ <?php echo $input; ?>
154
+
155
+ FIX:
156
+ // For plain text: always {{ }}
157
+ {{ $userContent }}
158
+
159
+ // For trusted HTML (admin only):
160
+ // Use HTMLPurifier or Sterilize
161
+ {!! clean($userContent) !!}
162
+
163
+ // Install: composer require mews/purifier
164
+ // Config: config/purifier.php
165
+
166
+ MEDIUM PATTERN 8 — href with unvalidated variable
167
+ DETECT:
168
+ <a href="{{ $user->website }}">
169
+ <a href="{!! $url !!}">
170
+ <script src="{{ $cdnUrl }}">
171
+
172
+ FIX:
173
+ // Validate it is indeed an HTTP/HTTPS URL
174
+ @php
175
+ $safeUrl = filter_var($user->website, FILTER_VALIDATE_URL)
176
+ && in_array(parse_url($user->website, PHP_URL_SCHEME), ['http', 'https'])
177
+ ? $user->website : '#';
178
+ @endphp
179
+ <a href="{{ $safeUrl }}">
180
+
181
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
182
+ IDOR AND AUTHORIZATION
183
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
184
+
185
+ CRITICAL PATTERN 9 — Access without ownership check
186
+ DETECT:
187
+ public function show($id) {
188
+ $order = Order::find($id); // No ownership check!
189
+ return $order;
190
+ }
191
+
192
+ public function update($id, Request $request) {
193
+ $post = Post::findOrFail($id); // Vulnerable
194
+ $post->update($request->validated());
195
+ }
196
+
197
+ FIX:
198
+ // Option A: where() with user_id
199
+ public function show($id) {
200
+ $order = Order::where('id', $id)
201
+ ->where('user_id', auth()->id())
202
+ ->firstOrFail();
203
+ return $order;
204
+ }
205
+
206
+ // Option B: Route Model Binding with Policy
207
+ public function update(Post $post, UpdatePostRequest $request) {
208
+ $this->authorize('update', $post); // Laravel Policy
209
+ $post->update($request->validated());
210
+ }
211
+
212
+ // Option C: Policy in the controller
213
+ public function destroy(Order $order) {
214
+ if ($order->user_id !== auth()->id()) {
215
+ abort(403, 'Unauthorized action.');
216
+ }
217
+ $order->delete();
218
+ }
219
+
220
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
221
+ FILE UPLOAD
222
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
223
+
224
+ CRITICAL PATTERN 10 — Upload without MIME validation
225
+ DETECT:
226
+ $file = $request->file('avatar');
227
+ $file->store('uploads'); // No validation!
228
+
229
+ $extension = $request->file('doc')->getClientOriginalExtension();
230
+ // getClientOriginalExtension() is spoofable!
231
+
232
+ FIX:
233
+ use Illuminate\Support\Facades\Storage;
234
+
235
+ public function uploadAvatar(Request $request) {
236
+ $request->validate([
237
+ 'avatar' => [
238
+ 'required',
239
+ 'file',
240
+ 'max:2048', // 2MB max
241
+ 'mimes:jpeg,png,gif,webp', // Extension whitelist
242
+ // Real MIME verification (not just extension)
243
+ function ($attribute, $value, $fail) {
244
+ $mimeType = $value->getMimeType();
245
+ $allowedMimes = ['image/jpeg', 'image/png',
246
+ 'image/gif', 'image/webp'];
247
+ if (!in_array($mimeType, $allowedMimes)) {
248
+ $fail('File type not allowed.');
249
+ }
250
+ },
251
+ ],
252
+ ]);
253
+
254
+ // Generate a random name (never use the original name)
255
+ $filename = Str::random(40) . '.' .
256
+ $request->file('avatar')->extension();
257
+
258
+ // Store OUTSIDE the public folder if possible
259
+ $path = $request->file('avatar')
260
+ ->storeAs('avatars', $filename, 'private');
261
+
262
+ // Serve via a controlled route
263
+ // GET /avatar/{filename} → check rights → return the file
264
+ }
265
+
266
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
267
+ CRITICAL CONFIGURATION
268
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
269
+
270
+ CRITICAL PATTERN 11 — APP_DEBUG in production
271
+ DETECT in .env or config/app.php:
272
+ APP_DEBUG=true
273
+ 'debug' => true
274
+ 'debug' => env('APP_DEBUG', true) // dangerous default
275
+
276
+ FIX:
277
+ // .env production
278
+ APP_DEBUG=false
279
+
280
+ // config/app.php
281
+ 'debug' => (bool) env('APP_DEBUG', false),
282
+
283
+ // Startup verification possible:
284
+ // AppServiceProvider::boot()
285
+ if (app()->isProduction() && config('app.debug')) {
286
+ throw new \RuntimeException(
287
+ 'DEBUG MODE IS ENABLED IN PRODUCTION!'
288
+ );
289
+ }
290
+
291
+ CRITICAL PATTERN 12 — Weak or default application key
292
+ DETECT in .env:
293
+ APP_KEY= (empty)
294
+ APP_KEY=base64:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
295
+ APP_KEY=SomeEasyToGuessString
296
+
297
+ FIX:
298
+ // Generate a real key
299
+ php artisan key:generate
300
+
301
+ // Verify length (must be 32 bytes in base64)
302
+ // Generated key starts with: base64:
303
+ // and is exactly 44 characters after the prefix
304
+
305
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
306
+ DESERIALIZATION
307
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
308
+
309
+ CRITICAL PATTERN 13 — unserialize() with user input
310
+ DETECT:
311
+ unserialize($request->input('data'))
312
+ unserialize(base64_decode($token))
313
+ unserialize(Cookie::get('cart'))
314
+
315
+ FIX:
316
+ // NEVER unserialize() user data
317
+ // Use JSON instead
318
+ $data = json_decode($request->input('data'), true);
319
+
320
+ // For sensitive cookies: Laravel encryption
321
+ // (enabled by default via EncryptCookies middleware)
322
+
323
+ // If serialize() is necessary for internal cache:
324
+ // Ensure the data NEVER comes from the user
325
+
326
+ ═══════════════════════════════════════════════════════════════
327
+ COMPLETE LARAVEL CHECKLIST
328
+ ═══════════════════════════════════════════════════════════════
329
+
330
+ ROUTES & MIDDLEWARE
331
+ □ All sensitive routes protected by auth middleware?
332
+ □ CSRF token present on all POST forms?
333
+ □ CSRF disabled only on webhooks with signature validation?
334
+ □ Rate limiting configured on login/register/reset-password?
335
+ □ API throttle configured?
336
+ □ Laravel debug routes disabled in prod?
337
+
338
+ ELOQUENT MODELS
339
+ □ $fillable defined on ALL models?
340
+ □ $guarded = [] absent?
341
+ □ Sensitive fields in $hidden? (password, remember_token)
342
+ □ Sensitive fields in $casts? (password → hashed)
343
+ □ N+1 relations not exploitable for IDOR?
344
+
345
+ CONTROLLERS
346
+ □ FormRequest used for validation?
347
+ □ authorize() called in FormRequests?
348
+ □ Ownership verified before every object access?
349
+ □ Response does not return unnecessary sensitive data?
350
+
351
+ AUTHENTICATION
352
+ □ Password hashing: Hash::make() used?
353
+ □ Comparison: Hash::check() used?
354
+ □ Remember me: limited duration?
355
+ □ Sessions invalidated on logout?
356
+ □ Email verification enabled?
357
+ □ Sanctum/Passport configured correctly?
358
+
359
+ CONFIGURATION
360
+ □ APP_DEBUG=false in production?
361
+ □ APP_ENV=production in production?
362
+ □ APP_KEY randomly generated?
363
+ □ .env in .gitignore?
364
+ □ config:cache used in prod?
365
+ □ Logs do not contain sensitive data?
366
+ □ Exceptions handler does not reveal infrastructure?
367
+
368
+ DEPENDENCIES
369
+ □ composer audit executed?
370
+ □ Packages up to date?
371
+ □ composer.lock committed?