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,338 @@
1
+ # 🦋 FLUTTER — SECURITY AUDIT GUIDE
2
+ # Comprehensive audit guide for Flutter/Dart applications
3
+
4
+ ═══════════════════════════════════════════════════════════════
5
+ FLUTTER THREAT MODEL
6
+ ═══════════════════════════════════════════════════════════════
7
+
8
+ FLUTTER ARCHITECTURE AND SECURITY IMPLICATIONS
9
+ ──────────────────────────────────────────────
10
+
11
+ [Dart Code] → [Flutter Engine (C++)] → [Platform APIs]
12
+ ↑ ↑ ↑
13
+ Business logic Rendering Native iOS/Android
14
+ UI + State Skia/Impeller Storage, Camera...
15
+
16
+ POINTS TO WATCH:
17
+ → Dart code is compiled AOT (Ahead-of-Time)
18
+ = less readable than a JS bundle but analysable
19
+ → Dart strings can still be extracted from the binary
20
+ → Platform channels = bridge between Dart and native
21
+ = attack surface if poorly validated
22
+ → Flutter Web = additional classic web attack surface
23
+
24
+ FLUTTER ATTACK SURFACE
25
+ ──────────────────────────
26
+ LAYER 1 — LOCAL STORAGE
27
+ SharedPreferences, Hive, Isar, sqflite, path_provider
28
+
29
+ LAYER 2 — NETWORK
30
+ http, dio, chopper — no pinning by default
31
+
32
+ LAYER 3 — PLATFORM CHANNELS
33
+ MethodChannel, EventChannel — Dart/native bridge
34
+
35
+ LAYER 4 — WEBVIEW
36
+ webview_flutter — XSS surface if uncontrolled content
37
+
38
+ LAYER 5 — DART BINARY
39
+ Extractable strings, endpoints, business logic
40
+
41
+ ═══════════════════════════════════════════════════════════════
42
+ VULNERABLE FLUTTER PATTERNS
43
+ ═══════════════════════════════════════════════════════════════
44
+
45
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
46
+ UNSECURE STORAGE
47
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
48
+
49
+ CRITICAL PATTERN 1 — SharedPreferences with sensitive data
50
+ DETECT:
51
+ final prefs = await SharedPreferences.getInstance();
52
+ await prefs.setString('auth_token', token);
53
+ await prefs.setString('password', password);
54
+ await prefs.setString('user_data', jsonEncode(user));
55
+
56
+ FIX:
57
+ // pubspec.yaml
58
+ // dependencies:
59
+ // flutter_secure_storage: ^9.0.0
60
+
61
+ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
62
+
63
+ const _storage = FlutterSecureStorage(
64
+ aOptions: AndroidOptions(
65
+ encryptedSharedPreferences: true,
66
+ // Uses Android EncryptedSharedPreferences
67
+ keyCipherAlgorithm:
68
+ KeyCipherAlgorithm.RSA_ECB_OAEPwithSHA_256andMGF1Padding,
69
+ storageCipherAlgorithm:
70
+ StorageCipherAlgorithm.AES_GCM_NoPadding,
71
+ ),
72
+ iOptions: IOSOptions(
73
+ accessibility: KeychainAccessibility.first_unlock_this_device,
74
+ // first_unlock_this_device = not in iCloud backups
75
+ ),
76
+ );
77
+
78
+ // Store
79
+ await _storage.write(key: 'auth_token', value: token);
80
+
81
+ // Read
82
+ final token = await _storage.read(key: 'auth_token');
83
+
84
+ // Delete (logout)
85
+ await _storage.delete(key: 'auth_token');
86
+
87
+ // Delete all
88
+ await _storage.deleteAll();
89
+
90
+ HIGH PATTERN 2 — Hive without encryption
91
+ DETECT:
92
+ await Hive.initFlutter();
93
+ final box = await Hive.openBox('userData');
94
+ await box.put('token', authToken);
95
+ await box.put('user', user.toMap());
96
+
97
+ FIX:
98
+ import 'package:hive_flutter/hive_flutter.dart';
99
+ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
100
+
101
+ Future<Box> openEncryptedBox(String boxName) async {
102
+ const secureStorage = FlutterSecureStorage();
103
+
104
+ // Generate or retrieve encryption key
105
+ var encryptionKeyString =
106
+ await secureStorage.read(key: 'hive_key_$boxName');
107
+
108
+ late List<int> encryptionKey;
109
+
110
+ if (encryptionKeyString == null) {
111
+ // Generate a secure key
112
+ final key = Hive.generateSecureKey();
113
+ encryptionKey = key;
114
+ await secureStorage.write(
115
+ key: 'hive_key_$boxName',
116
+ value: base64UrlEncode(key),
117
+ );
118
+ } else {
119
+ encryptionKey = base64Url.decode(encryptionKeyString);
120
+ }
121
+
122
+ return Hive.openBox(
123
+ boxName,
124
+ encryptionCipher: HiveAesCipher(encryptionKey),
125
+ );
126
+ }
127
+
128
+ // Usage
129
+ final box = await openEncryptedBox('secure_user_data');
130
+ await box.put('token', token);
131
+
132
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
133
+ NETWORK — CERTIFICATE PINNING
134
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
135
+
136
+ HIGH PATTERN 3 — Dio without pinning
137
+ DETECT:
138
+ final dio = Dio();
139
+ // No pinning configuration
140
+ final response = await dio.get('/api/users');
141
+
142
+ FIX:
143
+ import 'package:dio/dio.dart';
144
+ import 'dart:io';
145
+
146
+ Dio createSecureDio() {
147
+ final dio = Dio(
148
+ BaseOptions(
149
+ baseUrl: 'https://api.yourapp.com',
150
+ connectTimeout: const Duration(seconds: 10),
151
+ receiveTimeout: const Duration(seconds: 30),
152
+ headers: {
153
+ 'Content-Type': 'application/json',
154
+ },
155
+ ),
156
+ );
157
+
158
+ // Certificate pinning via custom HttpClient
159
+ (dio.httpClientAdapter as DefaultHttpClientAdapter)
160
+ .onHttpClientCreate = (client) {
161
+
162
+ client.badCertificateCallback = (
163
+ X509Certificate cert,
164
+ String host,
165
+ int port,
166
+ ) {
167
+ // Verify SHA-256 of certificate
168
+ final expectedFingerprints = [
169
+ 'AA:BB:CC:DD:...', // Primary pin
170
+ 'EE:FF:00:11:...', // Backup pin (MANDATORY)
171
+ ];
172
+
173
+ final certFingerprint = _getCertFingerprint(cert);
174
+ return expectedFingerprints.contains(certFingerprint);
175
+ };
176
+
177
+ return client;
178
+ };
179
+
180
+ // Interceptor to add token
181
+ dio.interceptors.add(
182
+ InterceptorsWrapper(
183
+ onRequest: (options, handler) async {
184
+ final token = await _getSecureToken();
185
+ if (token != null) {
186
+ options.headers['Authorization'] = 'Bearer $token';
187
+ }
188
+ handler.next(options);
189
+ },
190
+ onError: (error, handler) {
191
+ // Do not log sensitive details
192
+ logger.error(
193
+ 'API Error: ${error.response?.statusCode}',
194
+ );
195
+ handler.next(error);
196
+ },
197
+ ),
198
+ );
199
+
200
+ return dio;
201
+ }
202
+
203
+ String _getCertFingerprint(X509Certificate cert) {
204
+ final digest = sha256.convert(cert.der);
205
+ return digest.bytes
206
+ .map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase())
207
+ .join(':');
208
+ }
209
+
210
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
211
+ HARDCODED DART SECRETS
212
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
213
+
214
+ CRITICAL PATTERN 4 — Secret constants in Dart code
215
+ DETECT:
216
+ const String apiKey = 'sk-abc123...';
217
+ const String dbPassword = 'supersecret';
218
+ static const baseUrl = 'https://internal.corp.com/api';
219
+
220
+ class Config {
221
+ static const stripeKey = 'sk_live_...'; // CRITICAL
222
+ }
223
+
224
+ UNDERSTAND:
225
+ Even compiled, Dart strings are extractable:
226
+ strings app.aot | grep -i "api\|key\|secret\|password"
227
+
228
+ FIX:
229
+ // Option A: --dart-define at build time
230
+ // flutter build apk --dart-define=API_KEY=xxx
231
+
232
+ class Config {
233
+ static const apiKey =
234
+ String.fromEnvironment('API_KEY', defaultValue: '');
235
+
236
+ // Validate at startup
237
+ static void validate() {
238
+ if (apiKey.isEmpty) {
239
+ throw Exception(
240
+ 'API_KEY must be provided via --dart-define'
241
+ );
242
+ }
243
+ }
244
+ }
245
+
246
+ // Option B: Fetch from secure backend
247
+ // on first launch (after auth)
248
+
249
+ // Option C: flutter_dotenv for development
250
+ // (NEVER real keys in prod)
251
+
252
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
253
+ LOGS IN PRODUCTION
254
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
255
+
256
+ MEDIUM PATTERN 5 — print() and debugPrint() in production
257
+ DETECT:
258
+ print('User token: $token');
259
+ debugPrint('Auth response: $response');
260
+ print(user.toJson()); // PII data
261
+
262
+ FIX:
263
+ // lib/core/logger.dart
264
+ import 'package:flutter/foundation.dart';
265
+
266
+ class AppLogger {
267
+ static void debug(String message) {
268
+ if (kDebugMode) debugPrint('[DEBUG] $message');
269
+ }
270
+
271
+ static void info(String message) {
272
+ if (kDebugMode) debugPrint('[INFO] $message');
273
+ }
274
+
275
+ static void warn(String message) {
276
+ if (kDebugMode) debugPrint('[WARN] $message');
277
+ }
278
+
279
+ static void error(
280
+ String message, [
281
+ Object? error,
282
+ StackTrace? stackTrace,
283
+ ]) {
284
+ if (kDebugMode) {
285
+ debugPrint('[ERROR] $message');
286
+ if (error != null) debugPrint(error.toString());
287
+ }
288
+
289
+ // In production: Crashlytics without sensitive data
290
+ FirebaseCrashlytics.instance.recordError(
291
+ error ?? message,
292
+ stackTrace,
293
+ reason: message,
294
+ // Do not include user data
295
+ );
296
+ }
297
+
298
+ // Intentional no-op for sensitive data
299
+ static void sensitive(String message) {}
300
+ }
301
+
302
+ ═══════════════════════════════════════════════════════════════
303
+ COMPLETE FLUTTER CHECKLIST
304
+ ═══════════════════════════════════════════════════════════════
305
+
306
+ STORAGE
307
+ □ SharedPreferences without sensitive data ?
308
+ □ flutter_secure_storage for tokens and secrets ?
309
+ □ Hive with encryption if sensitive data ?
310
+ □ sqflite with SQLCipher if sensitive data ?
311
+ □ Encryption keys in secure_storage ?
312
+
313
+ NETWORK
314
+ □ Dio with certificate pinning ?
315
+ □ Backup pin configured ?
316
+ □ Timeout configured (connect + receive) ?
317
+ □ Tokens in headers via interceptor ?
318
+ □ Error logs without sensitive data ?
319
+
320
+ CODE
321
+ □ No secret constants in Dart code ?
322
+ □ --dart-define used for sensitive configs ?
323
+ □ kDebugMode for print() ?
324
+ □ Release mode tested (flutter build --release) ?
325
+ □ ProGuard enabled for native code (Android) ?
326
+
327
+ PLATFORM
328
+ □ Secured AndroidManifest ?
329
+ □ Info.plist minimal permissions ?
330
+ □ flutter_secure_storage options configured ?
331
+ □ allowBackup=false (Android) ?
332
+ □ Keyboard cache disabled on sensitive fields ?
333
+
334
+ DEPENDENCIES
335
+ □ pub audit executed ?
336
+ □ Packages up to date ?
337
+ □ pubspec.lock committed ?
338
+ □ Firebase/analytics SDK: minimal data ?
@@ -0,0 +1,248 @@
1
+ # ⚡ IONIC / CAPACITOR — SECURITY AUDIT GUIDE
2
+ # Comprehensive audit guide for Ionic applications
3
+
4
+ ═══════════════════════════════════════════════════════════════
5
+ IONIC THREAT MODEL
6
+ ═══════════════════════════════════════════════════════════════
7
+
8
+ IONIC IS FUNDAMENTALLY DIFFERENT
9
+ ──────────────────────────────────────
10
+ Ionic = Web Application (HTML/CSS/JS) in a native WebView.
11
+
12
+ This means:
13
+ → ALL web vulnerabilities apply
14
+ → PLUS all mobile vulnerabilities apply
15
+ → XSS in a WebView = access to native APIs
16
+ → The attack surface is the LARGEST of all mobile frameworks
17
+
18
+ [HTML/CSS/JS Angular/React/Vue]
19
+
20
+ [WebView (WKWebView iOS / WebView Android)]
21
+
22
+ [Capacitor Plugins → Native APIs]
23
+
24
+ [Operating System]
25
+
26
+ XSS IN IONIC = POTENTIAL FILESYSTEM ACCESS
27
+
28
+ IONIC ATTACK SURFACE
29
+ ────────────────────────
30
+ LAYER 1 — WEB (everything web-related)
31
+ XSS, CSP, mixed content, CORS
32
+
33
+ LAYER 2 — WEBVIEW
34
+ WebView configuration, local file access
35
+
36
+ LAYER 3 — CAPACITOR PLUGINS
37
+ FileSystem, Camera, Geolocation, Storage
38
+ = native access via JavaScript calls
39
+
40
+ LAYER 4 — NETWORK
41
+ Same issues as native mobile app
42
+
43
+ LAYER 5 — STORAGE
44
+ localStorage, sessionStorage, Capacitor Storage,
45
+ Capacitor Filesystem
46
+
47
+ ═══════════════════════════════════════════════════════════════
48
+ VULNERABLE IONIC PATTERNS
49
+ ═══════════════════════════════════════════════════════════════
50
+
51
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
52
+ XSS → NATIVE ACCESS VIA CAPACITOR
53
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
54
+
55
+ CRITICAL PATTERN 1 — XSS + Capacitor = Mobile RCE
56
+ UNDERSTAND:
57
+ XSS in an Ionic app is not just cookie theft.
58
+ The attacker can call Capacitor plugins:
59
+
60
+ // From an XSS injection:
61
+ Filesystem.readFile({ path: '/etc/passwd' }) → file read
62
+ Geolocation.getCurrentPosition() → GPS tracking
63
+ Camera.getPhoto() → camera access
64
+ Capacitor.Plugins.SecureStorage.get('token') → token theft
65
+
66
+ DETECT:
67
+ // innerHTML without sanitisation
68
+ element.innerHTML = userContent
69
+
70
+ // Angular: [innerHTML] without DOMSanitizer
71
+ <div [innerHTML]="userContent"></div>
72
+
73
+ // Ionic with innerHtml without sanitisation
74
+ this.content = data.userDescription // never sanitised
75
+
76
+ FIX:
77
+ // Angular — DOMSanitizer mandatory
78
+ import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
79
+
80
+ constructor(private sanitizer: DomSanitizer) {}
81
+
82
+ getSafeHtml(content: string): SafeHtml {
83
+ // Option 1: Sanitize with Angular
84
+ return this.sanitizer.sanitize(
85
+ SecurityContext.HTML,
86
+ content
87
+ ) ?? ''
88
+
89
+ // Option 2: DOMPurify (recommended)
90
+ // npm install dompurify @types/dompurify
91
+ return DOMPurify.sanitize(content, {
92
+ ALLOWED_TAGS: ['p', 'b', 'i', 'br', 'strong', 'em'],
93
+ ALLOWED_ATTR: [],
94
+ })
95
+ }
96
+
97
+ // Template
98
+ // <div [innerHTML]="getSafeHtml(userContent)"></div>
99
+
100
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
101
+ UNSECURE IONIC STORAGE
102
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
103
+
104
+ HIGH PATTERN 2 — localStorage with sensitive data
105
+ DETECT:
106
+ localStorage.setItem('token', authToken)
107
+ localStorage.setItem('user', JSON.stringify(user))
108
+ sessionStorage.setItem('password', password)
109
+
110
+ // Capacitor Storage (old API, unencrypted)
111
+ import { Storage } from '@capacitor/storage'
112
+ await Storage.set({ key: 'token', value: token })
113
+
114
+ FIX:
115
+ // npm install @capacitor/preferences
116
+ // + encryption solution
117
+
118
+ // Option: Ionic Secure Storage (encrypted, with biometrics)
119
+ // npm install @ionic-enterprise/secure-storage
120
+ import { SecureStorage } from '@ionic-enterprise/secure-storage'
121
+
122
+ const storage = new SecureStorage()
123
+ await storage.create()
124
+
125
+ await storage.set('auth_token', token)
126
+ const token = await storage.get('auth_token')
127
+ await storage.remove('auth_token')
128
+
129
+ // Open-source alternative:
130
+ // npm install @aparajita/capacitor-secure-storage
131
+ import { SecureStorage } from
132
+ '@aparajita/capacitor-secure-storage'
133
+
134
+ await SecureStorage.set('token', value, true)
135
+ // true = requires biometrics/pin code
136
+
137
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
138
+ CONTENT SECURITY POLICY IONIC
139
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
140
+
141
+ HIGH PATTERN 3 — CSP absent or too permissive
142
+ DETECT in index.html:
143
+ <!-- No CSP at all -->
144
+
145
+ <!-- OR overly permissive CSP -->
146
+ <meta http-equiv="Content-Security-Policy"
147
+ content="default-src *">
148
+
149
+ <!-- unsafe-inline = XSS possible -->
150
+ <meta http-equiv="Content-Security-Policy"
151
+ content="default-src 'self' 'unsafe-inline'">
152
+
153
+ FIX:
154
+ <!-- index.html -->
155
+ <meta http-equiv="Content-Security-Policy" content="
156
+ default-src 'self';
157
+
158
+ script-src 'self';
159
+
160
+ style-src 'self' 'unsafe-inline';
161
+
162
+ img-src 'self' data: blob: https://cdn.yourapp.com;
163
+
164
+ connect-src 'self'
165
+ https://api.yourapp.com
166
+ wss://ws.yourapp.com;
167
+
168
+ font-src 'self';
169
+
170
+ object-src 'none';
171
+
172
+ base-uri 'self';
173
+
174
+ frame-ancestors 'none';
175
+ ">
176
+
177
+ <!-- Capacitor requires capacitor: scheme -->
178
+ <!-- On iOS: gap: scheme may be needed -->
179
+ <!-- Adapt according to specific needs -->
180
+
181
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
182
+ UNSECURE CAPACITOR PLUGINS
183
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
184
+
185
+ HIGH PATTERN 4 — Filesystem plugin without validation
186
+ DETECT:
187
+ import { Filesystem, Directory } from '@capacitor/filesystem'
188
+
189
+ // Path built with user input
190
+ const path = `documents/${userInput}/data.json`
191
+ await Filesystem.readFile({ path, directory: Directory.Data })
192
+
193
+ // Path traversal possible if userInput = "../../etc/passwd"
194
+
195
+ FIX:
196
+ import { Filesystem, Directory } from '@capacitor/filesystem'
197
+
198
+ const safeReadFile = async (filename: string) => {
199
+ // Whitelist of allowed filenames
200
+ const allowedPattern = /^[a-zA-Z0-9_-]+\.json$/
201
+
202
+ if (!allowedPattern.test(filename)) {
203
+ throw new Error('Filename not allowed')
204
+ }
205
+
206
+ // No path traversal possible
207
+ // thanks to strict pattern and Directory
208
+ return Filesystem.readFile({
209
+ path: filename,
210
+ directory: Directory.Data, // Confined to app directory
211
+ encoding: Encoding.UTF8,
212
+ })
213
+ }
214
+
215
+ ═══════════════════════════════════════════════════════════════
216
+ COMPLETE IONIC CHECKLIST
217
+ ═══════════════════════════════════════════════════════════════
218
+
219
+ XSS AND OUTPUT
220
+ □ DOMPurify used on all user HTML content ?
221
+ □ Angular DomSanitizer used for [innerHTML] ?
222
+ □ CSP configured in index.html ?
223
+ □ CSP sufficiently restrictive (no unsafe-inline on script) ?
224
+ □ No eval() or new Function() with user input ?
225
+
226
+ STORAGE
227
+ □ localStorage without sensitive data ?
228
+ □ sessionStorage without sensitive data ?
229
+ □ Capacitor Preferences without sensitive data ?
230
+ □ Ionic Secure Storage for tokens and secrets ?
231
+ ↑ Data encrypted at rest ?
232
+
233
+ NETWORK
234
+ □ HTTPS only ?
235
+ □ Certificate pinning configured ?
236
+ □ Tokens in headers (not localStorage → auto headers) ?
237
+
238
+ CAPACITOR PLUGINS
239
+ □ Minimal permissions in capacitor.config.ts ?
240
+ □ Filesystem: paths validated before use ?
241
+ □ Camera: justified and temporary access ?
242
+ □ Geolocation: justified and minimal access ?
243
+
244
+ BUILD
245
+ □ Production mode: ionic build --prod ?
246
+ □ Source maps disabled in production ?
247
+ □ Code minified and obfuscated ?
248
+ □ Capacitor sync performed before native build ?