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,346 @@
1
+ # ⚛️ REACT — SECURITY AUDIT GUIDE
2
+ # Comprehensive audit guide for React applications
3
+
4
+ ═══════════════════════════════════════════════════════════════
5
+ REACT THREAT MODEL
6
+ ═══════════════════════════════════════════════════════════════
7
+
8
+ FUNDAMENTAL REMINDER:
9
+ React is a FRONTEND framework.
10
+ Backend security is still essential.
11
+ React cannot secure data server-side.
12
+ A React audit = audit of the client-side surface.
13
+
14
+ REACT ATTACK SURFACE
15
+ ────────────────────────
16
+
17
+ LAYER 1 — JSX RENDERING
18
+ Risks: XSS via dangerouslySetInnerHTML, innerHTML
19
+
20
+ LAYER 2 — STATE MANAGEMENT
21
+ Risks: Sensitive data in Redux/Context exposed
22
+ State logs in production
23
+
24
+ LAYER 3 — API COMMUNICATION
25
+ Risks: Tokens in localStorage, secrets in code,
26
+ Client-side CORS (false security)
27
+
28
+ LAYER 4 — CLIENT ROUTING
29
+ Risks: Bypassable route guards, unvalidated redirect
30
+
31
+ LAYER 5 — NPM DEPENDENCIES
32
+ Risks: CVEs, supply chain, malicious scripts
33
+
34
+ LAYER 6 — BUILD AND DEPLOYMENT
35
+ Risks: Exposed source maps, env vars in bundle
36
+
37
+ ═══════════════════════════════════════════════════════════════
38
+ VULNERABLE REACT PATTERNS
39
+ ═══════════════════════════════════════════════════════════════
40
+
41
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
42
+ XSS VIA DANGEROUS RENDERING
43
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
44
+
45
+ CRITICAL PATTERN — Unsanitized dangerouslySetInnerHTML
46
+ DETECT:
47
+ <div dangerouslySetInnerHTML={{ __html: userContent }} />
48
+ <div dangerouslySetInnerHTML={{ __html: comment.body }} />
49
+ <div dangerouslySetInnerHTML={{ __html: product.description }} />
50
+
51
+ FIX:
52
+ import DOMPurify from 'dompurify'
53
+
54
+ const SafeHTML = ({ content }: { content: string }) => {
55
+ const sanitized = DOMPurify.sanitize(content, {
56
+ ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li'],
57
+ ALLOWED_ATTR: [], // No href, onclick, etc. attributes
58
+ FORBID_TAGS: ['script', 'style', 'iframe', 'object'],
59
+ FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover'],
60
+ })
61
+
62
+ return <div dangerouslySetInnerHTML={{ __html: sanitized }} />
63
+ }
64
+
65
+ // Even better: use react-markdown for markdown content
66
+ import ReactMarkdown from 'react-markdown'
67
+ import remarkGfm from 'remark-gfm'
68
+
69
+ const SafeMarkdown = ({ content }: { content: string }) => (
70
+ <ReactMarkdown
71
+ remarkPlugins={[remarkGfm]}
72
+ components={{
73
+ // Disable dangerous elements
74
+ script: () => null,
75
+ iframe: () => null,
76
+ // Secure links
77
+ a: ({ href, children }) => {
78
+ const isExternal = href?.startsWith('http')
79
+ return (
80
+ <a
81
+ href={href}
82
+ target={isExternal ? '_blank' : undefined}
83
+ rel={isExternal ? 'noopener noreferrer' : undefined}
84
+ >
85
+ {children}
86
+ </a>
87
+ )
88
+ }
89
+ }}
90
+ >
91
+ {content}
92
+ </ReactMarkdown>
93
+ )
94
+
95
+ CRITICAL PATTERN — eval() and new Function()
96
+ DETECT:
97
+ eval(userInput)
98
+ eval(`return ${expression}`)
99
+ new Function('x', userCode)()
100
+ setTimeout(userString, 100) // setTimeout with string!
101
+ setInterval(userString, 100) // setInterval with string!
102
+
103
+ FIX:
104
+ // Never evaluate user code
105
+ // Replace with static mappings
106
+
107
+ // ❌ Instead of:
108
+ const result = eval(userExpression)
109
+
110
+ // ✅ Use a secure evaluation library
111
+ // or a functional approach:
112
+ const SAFE_OPERATIONS: Record<string, (a: number, b: number) => number> = {
113
+ add: (a, b) => a + b,
114
+ subtract: (a, b) => a - b,
115
+ multiply: (a, b) => a * b,
116
+ divide: (a, b) => b !== 0 ? a / b : 0,
117
+ }
118
+
119
+ const result = SAFE_OPERATIONS[operation]?.(numA, numB) ?? 0
120
+
121
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
122
+ CLIENT-SIDE TOKEN STORAGE
123
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
124
+
125
+ HIGH PATTERN — Tokens in localStorage
126
+ DETECT:
127
+ localStorage.setItem('token', accessToken)
128
+ localStorage.setItem('auth', JSON.stringify(authData))
129
+ localStorage.getItem('token')
130
+ sessionStorage.setItem('jwt', token)
131
+
132
+ UNDERSTAND:
133
+ localStorage = accessible via JavaScript
134
+ XSS → token theft → session hijacking
135
+ No automatic expiration
136
+ Shared across all tabs
137
+
138
+ FIX:
139
+ // OPTION A — HttpOnly Cookies (recommended)
140
+ // Token is managed server-side, not accessible via JS
141
+ // Login via API that sets the cookie
142
+
143
+ // React side: no token management at all
144
+ const login = async (credentials) => {
145
+ await fetch('/api/auth/login', {
146
+ method: 'POST',
147
+ credentials: 'include', // Sends and receives cookies
148
+ headers: { 'Content-Type': 'application/json' },
149
+ body: JSON.stringify(credentials),
150
+ })
151
+ // HttpOnly cookie is automatically set by the server
152
+ // React does not have access to the token
153
+ }
154
+
155
+ // OPTION B — Memory only (if cookies impossible)
156
+ // Token in React memory, never in storage
157
+ // Lost on reload → use a refresh token in cookie
158
+
159
+ let inMemoryToken: string | null = null
160
+
161
+ export const authService = {
162
+ setToken: (token: string) => { inMemoryToken = token },
163
+ getToken: () => inMemoryToken,
164
+ clearToken: () => { inMemoryToken = null },
165
+ }
166
+
167
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
168
+ SECRETS IN THE BUNDLE
169
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
170
+
171
+ CRITICAL PATTERN — Env vars in the bundle
172
+ DETECT:
173
+ // Everything starting with REACT_APP_ is in the bundle
174
+ const apiKey = process.env.REACT_APP_SECRET_KEY
175
+ const dbUrl = process.env.REACT_APP_DATABASE_URL
176
+
177
+ UNDERSTAND:
178
+ REACT_APP_* = injected into the JavaScript bundle
179
+ anyone can see these values via DevTools
180
+ or by downloading the .js file of the app
181
+
182
+ FIX:
183
+ // Client-side variables (OK if truly public):
184
+ REACT_APP_API_URL=https://api.yourapp.com ✅
185
+ REACT_APP_ANALYTICS_ID=G-XXXXXXXXXX ✅
186
+ REACT_APP_STRIPE_PUBLIC_KEY=pk_live_... ✅
187
+
188
+ // Secrets: NEVER in REACT_APP_
189
+ // They must be on the server
190
+ DATABASE_URL=... ← Server only
191
+ STRIPE_SECRET=... ← Server only
192
+ JWT_SECRET=... ← Server only
193
+
194
+ // If you need a server value on the client:
195
+ // Create an API endpoint that returns the value
196
+ // after auth verification
197
+
198
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
199
+ CLIENT ROUTE GUARDS
200
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
201
+
202
+ HIGH PATTERN — Client-side only protection
203
+ DETECT:
204
+ // Purely client-side protection = bypassable
205
+ const PrivateRoute = ({ children }) => {
206
+ const token = localStorage.getItem('token')
207
+ return token ? children : <Navigate to="/login" />
208
+ }
209
+ // An attacker can set token in localStorage
210
+ // and access all "protected" components
211
+
212
+ FIX:
213
+ // React routes = UX only
214
+ // Real protection = server
215
+
216
+ // React side: verify via the server
217
+ const PrivateRoute = ({ children }) => {
218
+ const [isAuth, setIsAuth] = useState<boolean | null>(null)
219
+
220
+ useEffect(() => {
221
+ // Server-side verification, not localStorage
222
+ fetch('/api/auth/me', { credentials: 'include' })
223
+ .then(res => setIsAuth(res.ok))
224
+ .catch(() => setIsAuth(false))
225
+ }, [])
226
+
227
+ if (isAuth === null) return <LoadingSpinner />
228
+ if (!isAuth) return <Navigate to="/login" replace />
229
+ return children
230
+ }
231
+
232
+ // AND server-side: each API route verifies auth
233
+ // independently of React routing
234
+
235
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
236
+ REACT ROUTER OPEN REDIRECT
237
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
238
+
239
+ MEDIUM PATTERN — Redirect with unvalidated URL parameter
240
+ DETECT:
241
+ const redirectTo = new URLSearchParams(location.search).get('next')
242
+ navigate(redirectTo || '/dashboard')
243
+
244
+ const { returnUrl } = queryParams
245
+ window.location.href = returnUrl // CRITICAL: domain exit possible
246
+
247
+ FIX:
248
+ function getSafeRedirect(redirectParam: string | null): string {
249
+ if (!redirectParam) return '/dashboard'
250
+
251
+ // Only allow relative paths from our app
252
+ // A relative path starts with / but not //
253
+ if (
254
+ redirectParam.startsWith('/') &&
255
+ !redirectParam.startsWith('//') &&
256
+ !redirectParam.startsWith('/\\')
257
+ ) {
258
+ // Verify the path is in our whitelist
259
+ const allowedPaths = ['/dashboard', '/profile',
260
+ '/orders', '/settings']
261
+ const isAllowed = allowedPaths.some(
262
+ path => redirectParam.startsWith(path)
263
+ )
264
+ return isAllowed ? redirectParam : '/dashboard'
265
+ }
266
+
267
+ return '/dashboard'
268
+ }
269
+
270
+ // Usage
271
+ const redirect = getSafeRedirect(searchParams.get('next'))
272
+ navigate(redirect)
273
+
274
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
275
+ SOURCE MAPS IN PRODUCTION
276
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
277
+
278
+ MEDIUM PATTERN — Exposed source maps
279
+ DETECT:
280
+ // In package.json or .env:
281
+ GENERATE_SOURCEMAP=true (CRA default in prod)
282
+ // .js.map files publicly accessible
283
+
284
+ IMPACT:
285
+ → Reconstruction of original source code
286
+ → Business logic exposed
287
+ → Internal file paths visible
288
+ → Original comments and variable names readable
289
+
290
+ FIX:
291
+ // Create React App
292
+ GENERATE_SOURCEMAP=false (in .env.production)
293
+
294
+ // Vite — vite.config.ts
295
+ export default defineConfig({
296
+ build: {
297
+ sourcemap: false, // In production
298
+ // OR send source maps to Sentry only:
299
+ sourcemap: true, // Generate
300
+ // And configure Sentry to upload them then remove
301
+ }
302
+ })
303
+
304
+ // Webpack
305
+ module.exports = {
306
+ devtool: process.env.NODE_ENV === 'production'
307
+ ? false // No source maps in prod
308
+ : 'source-map', // Source maps in dev
309
+ }
310
+
311
+ ═══════════════════════════════════════════════════════════════
312
+ COMPLETE REACT CHECKLIST
313
+ ═══════════════════════════════════════════════════════════════
314
+
315
+ XSS AND RENDERING
316
+ □ dangerouslySetInnerHTML with DOMPurify if used?
317
+ □ eval() / new Function() absent?
318
+ □ Direct innerHTML absent?
319
+ □ External links with rel="noopener noreferrer"?
320
+ □ CSP configured on the deployment server?
321
+
322
+ TOKEN MANAGEMENT
323
+ □ Tokens in HttpOnly cookies (not localStorage)?
324
+ □ No token in sessionStorage if XSS risky?
325
+ □ Memory-only as acceptable alternative?
326
+
327
+ VARIABLES AND SECRETS
328
+ □ No secrets in REACT_APP_?
329
+ □ GENERATE_SOURCEMAP=false in production?
330
+ □ .env.production in .gitignore?
331
+
332
+ ROUTING
333
+ □ Systematic server-side protection (not just React)?
334
+ □ Redirects validated with whitelist?
335
+ □ URL parameters sanitized before use?
336
+
337
+ DEPENDENCIES
338
+ □ npm audit clean?
339
+ □ Dependencies up to date?
340
+ □ Lock file committed?
341
+ □ Unused dependencies removed?
342
+
343
+ API COMMUNICATION
344
+ □ credentials: 'include' if HttpOnly cookies?
345
+ □ HTTPS only?
346
+ □ Error handling does not reveal internal details?
@@ -0,0 +1,205 @@
1
+ # 💚 VUE.JS — SECURITY AUDIT GUIDE
2
+
3
+ ═══════════════════════════════════════════════════════════════
4
+ VUE.JS THREAT MODEL
5
+ ═══════════════════════════════════════════════════════════════
6
+
7
+ VUE AUTO-ESCAPE:
8
+ Vue automatically escapes data in templates.
9
+ {{ userInput }} is safe by default.
10
+ XSS risks come from exceptions to this rule.
11
+
12
+ VUE ATTACK SURFACE
13
+ ──────────────────────
14
+ LAYER 1 — TEMPLATES (v-html, :href)
15
+ Risks: XSS via v-html, javascript: in href
16
+
17
+ LAYER 2 — DYNAMIC COMPONENTS
18
+ Risks: <component :is="userInput"> → XSS / injection
19
+
20
+ LAYER 3 — SSR (Nuxt.js)
21
+ Risks: Hydration mismatch, server-side injection
22
+
23
+ LAYER 4 — PINIA / VUEX
24
+ Risks: State exposure, persisted sensitive data
25
+
26
+ LAYER 5 — VUE ROUTER
27
+ Risks: Bypassable route guards, navigation guards
28
+
29
+ ═══════════════════════════════════════════════════════════════
30
+ VULNERABLE VUE PATTERNS
31
+ ═══════════════════════════════════════════════════════════════
32
+
33
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
34
+ XSS VIA v-html
35
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
36
+
37
+ HIGH PATTERN — v-html with user content
38
+ DETECT:
39
+ <div v-html="userComment"></div>
40
+ <div v-html="product.description"></div>
41
+ <span v-html="formattedContent"></span>
42
+
43
+ FIX:
44
+ // Install DOMPurify
45
+ // npm install dompurify @types/dompurify
46
+
47
+ // Custom Vue directive
48
+ // directives/safe-html.ts
49
+ import DOMPurify from 'dompurify'
50
+ import type { Directive } from 'vue'
51
+
52
+ export const safeHtml: Directive = {
53
+ mounted(el, binding) {
54
+ el.innerHTML = DOMPurify.sanitize(binding.value, {
55
+ ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li'],
56
+ ALLOWED_ATTR: [],
57
+ })
58
+ },
59
+ updated(el, binding) {
60
+ el.innerHTML = DOMPurify.sanitize(binding.value, {
61
+ ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li'],
62
+ ALLOWED_ATTR: [],
63
+ })
64
+ }
65
+ }
66
+
67
+ // Global registration
68
+ // main.ts
69
+ app.directive('safe-html', safeHtml)
70
+
71
+ // Usage in templates
72
+ <div v-safe-html="userComment"></div>
73
+
74
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
75
+ UNCONTROLLED DYNAMIC COMPONENTS
76
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
77
+
78
+ HIGH PATTERN — :is with user value
79
+ DETECT:
80
+ <component :is="userInput" />
81
+ <component :is="route.params.componentName" />
82
+
83
+ FIX:
84
+ // Whitelist of allowed components
85
+ import CardComponent from './Card.vue'
86
+ import ListComponent from './List.vue'
87
+ import TableComponent from './Table.vue'
88
+
89
+ const ALLOWED_COMPONENTS = {
90
+ card: CardComponent,
91
+ list: ListComponent,
92
+ table: TableComponent,
93
+ } as const
94
+
95
+ const safeComponent = computed(() => {
96
+ return ALLOWED_COMPONENTS[userInput] || CardComponent
97
+ })
98
+
99
+ <component :is="safeComponent" />
100
+
101
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
102
+ VUE ROUTER — NAVIGATION GUARDS
103
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
104
+
105
+ HIGH PATTERN — Guard based on local state alone
106
+ DETECT:
107
+ router.beforeEach((to, from, next) => {
108
+ const authStore = useAuthStore()
109
+ // Based solely on Pinia state
110
+ // No server verification
111
+ if (to.meta.requiresAuth && !authStore.isLoggedIn) {
112
+ next('/login')
113
+ } else {
114
+ next()
115
+ }
116
+ })
117
+
118
+ FIX:
119
+ router.beforeEach(async (to, from, next) => {
120
+ if (!to.meta.requiresAuth) return next()
121
+
122
+ try {
123
+ // Server-side verification
124
+ const response = await fetch('/api/auth/verify', {
125
+ credentials: 'include'
126
+ })
127
+
128
+ if (!response.ok) {
129
+ return next({
130
+ path: '/login',
131
+ query: { redirect: to.fullPath }
132
+ })
133
+ }
134
+
135
+ const { user } = await response.json()
136
+
137
+ // Role check if necessary
138
+ if (to.meta.requiredRole && user.role !== to.meta.requiredRole) {
139
+ return next('/unauthorized')
140
+ }
141
+
142
+ next()
143
+ } catch {
144
+ next('/login')
145
+ }
146
+ })
147
+
148
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
149
+ NUXT.JS — SSR SPECIFIC
150
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
151
+
152
+ HIGH PATTERN — useRoute() with unvalidated params in SSR
153
+ DETECT:
154
+ // pages/user/[id].vue
155
+ const route = useRoute()
156
+ const { data } = await useFetch(`/api/user/${route.params.id}`)
157
+ // route.params.id unvalidated = possible SSRF or injection
158
+
159
+ FIX:
160
+ const route = useRoute()
161
+ const userId = route.params.id
162
+
163
+ // Validate the ID format
164
+ if (!/^[0-9a-f-]{36}$/.test(userId as string)) {
165
+ throw createError({ statusCode: 400, message: 'Invalid ID' })
166
+ }
167
+
168
+ const { data } = await useFetch(`/api/user/${userId}`, {
169
+ // Security headers passed if needed
170
+ })
171
+
172
+ MEDIUM PATTERN — Secrets in nuxt.config.ts on the public side
173
+ DETECT:
174
+ // nuxt.config.ts
175
+ runtimeConfig: {
176
+ public: {
177
+ apiSecret: process.env.API_SECRET, // EXPOSED TO CLIENT!
178
+ }
179
+ }
180
+
181
+ FIX:
182
+ runtimeConfig: {
183
+ // Server-side only (private)
184
+ apiSecret: process.env.API_SECRET,
185
+ databaseUrl: process.env.DATABASE_URL,
186
+
187
+ // Client-side (public) — only if truly public
188
+ public: {
189
+ apiUrl: process.env.NUXT_PUBLIC_API_URL,
190
+ appName: 'MyApp',
191
+ }
192
+ }
193
+
194
+ ═══════════════════════════════════════════════════════════════
195
+ COMPLETE VUE.JS CHECKLIST
196
+ ═══════════════════════════════════════════════════════════════
197
+
198
+ □ v-html with sanitization (DOMPurify)?
199
+ □ Dynamic components with whitelist?
200
+ □ Navigation guards with server verification?
201
+ □ Tokens in HttpOnly cookies (not localStorage)?
202
+ □ Nuxt: secrets in private runtimeConfig?
203
+ □ Nuxt: useRoute() params validated server-side?
204
+ □ Source maps disabled in production?
205
+ □ npm audit clean?
@@ -0,0 +1,117 @@
1
+ # 🔐 AUTH & AUTHZ — VULNERABILITY GUIDE
2
+
3
+ ═══════════════════════════════════════════════════════════════
4
+ AUTHENTICATION VS AUTHORIZATION
5
+ ═══════════════════════════════════════════════════════════════
6
+
7
+ AUTHENTICATION = "Who are you?"
8
+ Verify a user's identity.
9
+ Mechanisms : Password, MFA, Biometrics, SSO, OAuth
10
+
11
+ AUTHORIZATION = "Do you have permission?"
12
+ Verify if the authenticated user can perform this action.
13
+ Mechanisms : RBAC, ABAC, ACL, Policy-based
14
+
15
+ BOTH CAN BE COMPROMISED INDEPENDENTLY.
16
+ Strong Auth + Weak Authz = IDOR, privilege escalation
17
+ Weak Auth + Strong Authz = account takeover then escalation
18
+
19
+ OWASP : A07:2021 (Auth) + A01:2021 (Authz)
20
+
21
+ ═══════════════════════════════════════════════════════════════
22
+ AUTHENTICATION FLAWS
23
+ ═══════════════════════════════════════════════════════════════
24
+
25
+ BRUTE FORCE
26
+ Detect : No rate limiting on /login
27
+ Impact : Account compromise with weak passwords
28
+ Fix : Rate limiting + lockout + CAPTCHA + increasing delay
29
+
30
+ CREDENTIAL STUFFING
31
+ Detect : Same accounts as on other services
32
+ Impact : Mass compromise if passwords reused
33
+ Fix : Mandatory MFA + credential stuffing detection
34
+ (HaveIBeenPwned API, delays, device fingerprinting)
35
+
36
+ PASSWORD RESET HIJACKING
37
+ Detect :
38
+ - Predictable token (timestamp, MD5 hash of email)
39
+ - No token expiration
40
+ - Reusable token
41
+ - Message revealing if email exists
42
+ Impact : Full account takeover
43
+ Fix :
44
+ const resetToken = crypto.randomBytes(32).toString('hex')
45
+ const hashedToken = crypto
46
+ .createHash('sha256')
47
+ .update(resetToken)
48
+ .digest('hex')
49
+
50
+ await db.passwordReset.create({
51
+ data: {
52
+ userId: user.id,
53
+ token: hashedToken, // Store hash, send raw
54
+ expiresAt: new Date(Date.now() + 15 * 60 * 1000), // 15min
55
+ used: false,
56
+ }
57
+ })
58
+
59
+ SESSION FIXATION
60
+ Detect : Session ID not regenerated after login
61
+ Impact : Attacker forces a known session ID, then user logs in
62
+ Fix : req.session.regenerate() after every authentication
63
+
64
+ JWT VULNERABILITIES
65
+ Detect :
66
+ - "none" algorithm accepted
67
+ - jwt.decode() instead of jwt.verify()
68
+ - Short or predictable secret
69
+ - No expiration
70
+ - Algorithm confusion (RS256 → HS256 with public key)
71
+ Impact : Forged token = identity theft
72
+ Fix : See REM-003 in remediation library
73
+
74
+ ═══════════════════════════════════════════════════════════════
75
+ AUTHORIZATION FLAWS
76
+ ═══════════════════════════════════════════════════════════════
77
+
78
+ IDOR (Insecure Direct Object Reference)
79
+ See : web/vulnerabilities/IDOR-BOLA.md
80
+
81
+ BFLA (Broken Function Level Authorization)
82
+ Detect :
83
+ - Admin endpoints accessible without role check
84
+ - Destructive actions without verification
85
+ - Unrestricted HTTP methods (DELETE without auth)
86
+ Impact : Access to admin functions by a normal user
87
+ Fix :
88
+ // Role verification on EVERY admin endpoint
89
+ @Get('admin/users')
90
+ @Roles('ADMIN', 'SUPER_ADMIN')
91
+ async getUsers() { ... }
92
+
93
+ // Do not rely on the URL starting with /admin
94
+ // Verify role explicitly even under /admin
95
+
96
+ PRIVILEGE ESCALATION
97
+ Detect :
98
+ - "role" field accepted in user updates
99
+ - is_admin parameter in body
100
+ - JWT with modifiable role on client side
101
+ Impact : Normal user becomes admin
102
+ Fix :
103
+ // Never update role from user input
104
+ // Except through an explicitly protected admin endpoint
105
+
106
+ // ❌ DANGEROUS :
107
+ await user.update(req.body) // req.body may contain role: "admin"
108
+
109
+ // ✅ SECURE :
110
+ await user.update({
111
+ name: req.body.name,
112
+ email: req.body.email,
113
+ // role → never from req.body
114
+ })
115
+
116
+ MASS ASSIGNMENT
117
+ See : web/frameworks/LARAVEL.md (Pattern 5 and 6)