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.
- package/README.md +77 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +241 -0
- package/dist/mcp-server.d.ts +2 -0
- package/dist/mcp-server.js +126 -0
- package/package.json +58 -0
- package/skills/cyberaudit/AGENT-BOOT.md +122 -0
- package/skills/cyberaudit/COMMANDS.md +1125 -0
- package/skills/cyberaudit/INSTALL.md +311 -0
- package/skills/cyberaudit/MASTER.md +194 -0
- package/skills/cyberaudit/README.md +154 -0
- package/skills/cyberaudit/USAGE-GUIDE.md +107 -0
- package/skills/cyberaudit/mobile/MOBILE-CHECKLIST.md +245 -0
- package/skills/cyberaudit/mobile/MOBILE-PHILOSOPHY.md +352 -0
- package/skills/cyberaudit/mobile/MOBILE-REMEDIATION-LIBRARY.md +468 -0
- package/skills/cyberaudit/mobile/MOBILE-THREAT-MODELS.md +279 -0
- package/skills/cyberaudit/mobile/frameworks/EXPO.md +247 -0
- package/skills/cyberaudit/mobile/frameworks/FLUTTER.md +338 -0
- package/skills/cyberaudit/mobile/frameworks/IONIC.md +248 -0
- package/skills/cyberaudit/mobile/frameworks/REACT-NATIVE.md +479 -0
- package/skills/cyberaudit/mobile/vulnerabilities/AUTH-MOBILE.md +160 -0
- package/skills/cyberaudit/mobile/vulnerabilities/BINARY-ANALYSIS.md +193 -0
- package/skills/cyberaudit/mobile/vulnerabilities/CRYPTO-MOBILE.md +192 -0
- package/skills/cyberaudit/mobile/vulnerabilities/IPC-DEEPLINKS.md +231 -0
- package/skills/cyberaudit/mobile/vulnerabilities/NETWORK-MOBILE.md +165 -0
- package/skills/cyberaudit/mobile/vulnerabilities/PERMISSIONS.md +180 -0
- package/skills/cyberaudit/mobile/vulnerabilities/RUNTIME-MOBILE.md +214 -0
- package/skills/cyberaudit/mobile/vulnerabilities/STORAGE.md +197 -0
- package/skills/cyberaudit/reports/EXECUTIVE-SUMMARY-TEMPLATE.md +188 -0
- package/skills/cyberaudit/reports/REPORT-TEMPLATE-MOBILE.md +410 -0
- package/skills/cyberaudit/reports/REPORT-TEMPLATE-WEB.md +222 -0
- package/skills/cyberaudit/shared/COMPLIANCE.md +307 -0
- package/skills/cyberaudit/shared/CVSS-GUIDE.md +175 -0
- package/skills/cyberaudit/shared/OWASP-MAPPER.md +130 -0
- package/skills/cyberaudit/shared/SEVERITY-SCORING.md +102 -0
- package/skills/cyberaudit/shared/THREAT-MODELING.md +112 -0
- package/skills/cyberaudit/web/WEB-CHECKLIST.md +222 -0
- package/skills/cyberaudit/web/WEB-PHILOSOPHY.md +308 -0
- package/skills/cyberaudit/web/WEB-REMEDIATION-LIBRARY.md +665 -0
- package/skills/cyberaudit/web/WEB-THREAT-MODELS.md +460 -0
- package/skills/cyberaudit/web/frameworks/ANGULAR.md +169 -0
- package/skills/cyberaudit/web/frameworks/EXPRESS.md +185 -0
- package/skills/cyberaudit/web/frameworks/LARAVEL.md +371 -0
- package/skills/cyberaudit/web/frameworks/NESTJS.md +337 -0
- package/skills/cyberaudit/web/frameworks/NEXTJS.md +352 -0
- package/skills/cyberaudit/web/frameworks/REACT.md +346 -0
- package/skills/cyberaudit/web/frameworks/VUE.md +205 -0
- package/skills/cyberaudit/web/vulnerabilities/AUTH-AUTHZ.md +117 -0
- package/skills/cyberaudit/web/vulnerabilities/BUSINESS-LOGIC.md +603 -0
- package/skills/cyberaudit/web/vulnerabilities/CORS.md +117 -0
- package/skills/cyberaudit/web/vulnerabilities/CSRF.md +131 -0
- package/skills/cyberaudit/web/vulnerabilities/DESERIALIZATION.md +96 -0
- package/skills/cyberaudit/web/vulnerabilities/HEADERS.md +105 -0
- package/skills/cyberaudit/web/vulnerabilities/IDOR-BOLA.md +153 -0
- package/skills/cyberaudit/web/vulnerabilities/INJECTION.md +165 -0
- package/skills/cyberaudit/web/vulnerabilities/SECRETS.md +119 -0
- package/skills/cyberaudit/web/vulnerabilities/SSRF.md +124 -0
- package/skills/cyberaudit/web/vulnerabilities/SUPPLY-CHAIN.md +142 -0
- package/skills/cyberaudit/web/vulnerabilities/XSS.md +133 -0
- package/skills/cyberaudit/web/vulnerabilities/XXE.md +94 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# 🎯 MOBILE THREAT MODELS — CYBERAUDIT SKILL
|
|
2
|
+
# Comprehensive threat models for mobile applications
|
|
3
|
+
|
|
4
|
+
═══════════════════════════════════════════════════════════════
|
|
5
|
+
STRIDE APPLIED TO MOBILE
|
|
6
|
+
═══════════════════════════════════════════════════════════════
|
|
7
|
+
|
|
8
|
+
S — SPOOFING
|
|
9
|
+
Specific mobile threats:
|
|
10
|
+
→ Fake app on third-party stores (APK sideloading)
|
|
11
|
+
→ Certificate spoofed via compromised CA (without pinning)
|
|
12
|
+
→ Deep link hijacking (another app intercepts the link)
|
|
13
|
+
→ Intent spoofing (Android: implicit intents intercepted)
|
|
14
|
+
→ Biometrics bypassed via Frida hook
|
|
15
|
+
|
|
16
|
+
Controls:
|
|
17
|
+
→ Mandatory certificate pinning
|
|
18
|
+
→ Explicit intents for internal communication
|
|
19
|
+
→ App signature verification
|
|
20
|
+
→ Biometrics linked to a cryptographic key
|
|
21
|
+
|
|
22
|
+
T — TAMPERING
|
|
23
|
+
Specific mobile threats:
|
|
24
|
+
→ Binary modification APK/IPA (repackaging)
|
|
25
|
+
→ Hooking via Frida to modify behavior
|
|
26
|
+
→ Man-in-the-Middle on network traffic
|
|
27
|
+
→ Modification of SharedPreferences/plist files
|
|
28
|
+
→ Code injection via WebView bridge
|
|
29
|
+
|
|
30
|
+
Controls:
|
|
31
|
+
→ Binary integrity verification
|
|
32
|
+
→ Anti-hooking / anti-Frida
|
|
33
|
+
→ Certificate pinning
|
|
34
|
+
→ Secure storage with integrity
|
|
35
|
+
|
|
36
|
+
R — REPUDIATION
|
|
37
|
+
Specific mobile threats:
|
|
38
|
+
→ Sensitive actions without audit trail server-side
|
|
39
|
+
→ Transactions without cryptographic proof
|
|
40
|
+
→ Insufficient logs for forensic after incident
|
|
41
|
+
|
|
42
|
+
Controls:
|
|
43
|
+
→ Server-side logging of all sensitive actions
|
|
44
|
+
→ Signature of critical transactions
|
|
45
|
+
→ Server timestamps (not client)
|
|
46
|
+
|
|
47
|
+
I — INFORMATION DISCLOSURE
|
|
48
|
+
Specific mobile threats:
|
|
49
|
+
→ AsyncStorage/SharedPreferences read on rooted device
|
|
50
|
+
→ Unencrypted ADB backup
|
|
51
|
+
→ Screenshots in app switcher
|
|
52
|
+
→ Logs accessible via ADB logcat
|
|
53
|
+
→ Binary strings extracted from APK/IPA
|
|
54
|
+
→ Memory dumps on rooted device
|
|
55
|
+
→ Unencrypted traffic intercepted
|
|
56
|
+
→ Data in clipboard
|
|
57
|
+
→ Sensitive data in crash reports
|
|
58
|
+
|
|
59
|
+
Controls:
|
|
60
|
+
→ Mandatory Keychain/Keystore
|
|
61
|
+
→ allowBackup=false or backup rules
|
|
62
|
+
→ Screenshot protection
|
|
63
|
+
→ Conditional logs in dev only
|
|
64
|
+
→ Secrets outside binary
|
|
65
|
+
→ Memory protection for sensitive data
|
|
66
|
+
|
|
67
|
+
D — DENIAL OF SERVICE
|
|
68
|
+
Specific mobile threats:
|
|
69
|
+
→ Battery drain via excessive network requests
|
|
70
|
+
→ Storage exhaustion via uploads
|
|
71
|
+
→ CPU exhaustion via unlimited cryptographic operations
|
|
72
|
+
→ App crash via malformed deep link
|
|
73
|
+
→ Crash via malformed JSON payload in WebView bridge
|
|
74
|
+
|
|
75
|
+
Controls:
|
|
76
|
+
→ Timeout on all network requests
|
|
77
|
+
→ Input validation before heavy processing
|
|
78
|
+
→ Server-side rate limiting
|
|
79
|
+
→ Exception handling on deep links
|
|
80
|
+
|
|
81
|
+
E — ELEVATION OF PRIVILEGE
|
|
82
|
+
Specific mobile threats:
|
|
83
|
+
→ Root access exploited to read other apps' data
|
|
84
|
+
→ Exported Content Provider giving access to internal data
|
|
85
|
+
→ Exported Activity allowing access to admin functions
|
|
86
|
+
→ Privilege escalation via WebView → JavaScript Bridge → Native
|
|
87
|
+
|
|
88
|
+
Controls:
|
|
89
|
+
→ Components not exported by default
|
|
90
|
+
→ Permissions on exported components
|
|
91
|
+
→ Minimal WebView bridge
|
|
92
|
+
|
|
93
|
+
═══════════════════════════════════════════════════════════════
|
|
94
|
+
MOBILE ATTACK TREES
|
|
95
|
+
═══════════════════════════════════════════════════════════════
|
|
96
|
+
|
|
97
|
+
TREE 1 — AUTH TOKEN COMPROMISE
|
|
98
|
+
────────────────────────
|
|
99
|
+
|
|
100
|
+
OBJECTIVE: Steal the authentication token
|
|
101
|
+
│
|
|
102
|
+
├── VECTOR A: Extraction from storage
|
|
103
|
+
│ ├── A1: Rooted device → read AsyncStorage directly
|
|
104
|
+
│ │ Prerequisite: root, physical access
|
|
105
|
+
│ │ Ease: EASY if AsyncStorage
|
|
106
|
+
│ │
|
|
107
|
+
│ ├── A2: Unencrypted ADB backup
|
|
108
|
+
│ │ Prerequisite: ADB enabled OR cloud backup
|
|
109
|
+
│ │ Ease: EASY if allowBackup=true
|
|
110
|
+
│ │
|
|
111
|
+
│ └── A3: Memory dump (app in foreground)
|
|
112
|
+
│ Prerequisite: root + tools
|
|
113
|
+
│ Ease: MEDIUM
|
|
114
|
+
│
|
|
115
|
+
├── VECTOR B: Network interception
|
|
116
|
+
│ ├── B1: MitM on public WiFi (without pinning)
|
|
117
|
+
│ │ Prerequisite: same network
|
|
118
|
+
│ │ Ease: EASY with mitmproxy
|
|
119
|
+
│ │
|
|
120
|
+
│ └── B2: Malicious CA installed (without pinning)
|
|
121
|
+
│ Prerequisite: physical access to device
|
|
122
|
+
│ Ease: MEDIUM
|
|
123
|
+
│
|
|
124
|
+
└── VECTOR C: Binary extraction
|
|
125
|
+
├── C1: Token hardcoded in JS bundle
|
|
126
|
+
│ Prerequisite: APK downloaded
|
|
127
|
+
│ Ease: VERY EASY
|
|
128
|
+
│
|
|
129
|
+
└── C2: Dev endpoint exposed in prod
|
|
130
|
+
Prerequisite: knowledge of endpoint
|
|
131
|
+
Ease: EASY
|
|
132
|
+
|
|
133
|
+
TREE 2 — MOBILE ACCOUNT TAKEOVER
|
|
134
|
+
────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
OBJECTIVE: Take control of an account
|
|
137
|
+
│
|
|
138
|
+
├── VECTOR A: Session theft (see tree 1)
|
|
139
|
+
│
|
|
140
|
+
├── VECTOR B: Biometrics bypass
|
|
141
|
+
│ ├── B1: Frida hook on verification method
|
|
142
|
+
│ │ Prerequisite: root + Frida
|
|
143
|
+
│ │ Ease: EASY if client-side only check
|
|
144
|
+
│ │
|
|
145
|
+
│ └── B2: Biometrics = just a boolean flag
|
|
146
|
+
│ Prerequisite: root or decompilation
|
|
147
|
+
│ Ease: EASY if poorly implemented
|
|
148
|
+
│
|
|
149
|
+
├── VECTOR C: Malicious deep link
|
|
150
|
+
│ └── C1: Forged link that triggers an auth action
|
|
151
|
+
│ Prerequisite: unvalidated deep link
|
|
152
|
+
│ Ease: EASY
|
|
153
|
+
│
|
|
154
|
+
└── VECTOR D: Mobile API exploitation
|
|
155
|
+
└── D1: IDOR on mobile endpoint (predictable IDs)
|
|
156
|
+
Prerequisite: valid account
|
|
157
|
+
Ease: MEDIUM
|
|
158
|
+
|
|
159
|
+
TREE 3 — LOCAL DATA EXFILTRATION
|
|
160
|
+
──────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
OBJECTIVE: Read another user's data
|
|
163
|
+
│
|
|
164
|
+
├── VECTOR A: Physical access + root
|
|
165
|
+
│ └── A1: Direct read of unencrypted storage
|
|
166
|
+
│ Ease: VERY EASY if unencrypted
|
|
167
|
+
│
|
|
168
|
+
├── VECTOR B: Backup extraction
|
|
169
|
+
│ ├── B1: ADB backup (Android)
|
|
170
|
+
│ └── B2: iTunes/iCloud backup (iOS)
|
|
171
|
+
│ Ease: EASY if not excluded
|
|
172
|
+
│
|
|
173
|
+
└── VECTOR C: Malware / malicious app
|
|
174
|
+
└── C1: Intent sniffing (Android)
|
|
175
|
+
Unprotected Content Provider
|
|
176
|
+
Ease: MEDIUM
|
|
177
|
+
|
|
178
|
+
═══════════════════════════════════════════════════════════════
|
|
179
|
+
THREAT MODELS BY MOBILE APP TYPE
|
|
180
|
+
═══════════════════════════════════════════════════════════════
|
|
181
|
+
|
|
182
|
+
BANKING / FINTECH APP
|
|
183
|
+
──────────────────────
|
|
184
|
+
Priority 1: Token theft → fraudulent transactions
|
|
185
|
+
Priority 2: MitM → amount manipulation
|
|
186
|
+
Priority 3: Root/jailbreak → protection bypass
|
|
187
|
+
Priority 4: Repackaging → fake app for phishing
|
|
188
|
+
Priority 5: Screen recording during transactions
|
|
189
|
+
|
|
190
|
+
Mandatory controls:
|
|
191
|
+
→ Certificate pinning with backup pin
|
|
192
|
+
→ Root/Jailbreak detection
|
|
193
|
+
→ Keystore with StrongBox (Android)
|
|
194
|
+
→ Biometrics linked to cryptographic key
|
|
195
|
+
→ Transaction signing server-side
|
|
196
|
+
→ Business code obfuscation
|
|
197
|
+
→ Anti-Frida/anti-debug
|
|
198
|
+
|
|
199
|
+
HEALTH APP
|
|
200
|
+
──────────────────────
|
|
201
|
+
Priority 1: Access to other patients' medical data
|
|
202
|
+
Priority 2: Cleartext data in backups
|
|
203
|
+
Priority 3: Logs containing health data
|
|
204
|
+
Priority 4: Data in crash reports
|
|
205
|
+
Priority 5: Access without re-authentication
|
|
206
|
+
|
|
207
|
+
Mandatory controls:
|
|
208
|
+
→ Encryption of entire local database
|
|
209
|
+
→ Backup exclusion
|
|
210
|
+
→ Crash report filtering
|
|
211
|
+
→ Re-auth for access to sensitive data
|
|
212
|
+
→ HIPAA compliance
|
|
213
|
+
|
|
214
|
+
E-COMMERCE APP
|
|
215
|
+
──────────────────────
|
|
216
|
+
Priority 1: Card data theft (if stored)
|
|
217
|
+
Priority 2: Account takeover → fraudulent purchase
|
|
218
|
+
Priority 3: Client-side price manipulation
|
|
219
|
+
Priority 4: Coupon/promo abuse via race condition
|
|
220
|
+
Priority 5: Personal data (GDPR)
|
|
221
|
+
|
|
222
|
+
Mandatory controls:
|
|
223
|
+
→ NEVER store card data locally
|
|
224
|
+
→ Use payment SDK (Stripe, etc.)
|
|
225
|
+
→ Server-side price validation only
|
|
226
|
+
→ Rate limiting on purchases
|
|
227
|
+
|
|
228
|
+
GENERAL PUBLIC APP
|
|
229
|
+
──────────────────────
|
|
230
|
+
Priority 1: Exposed personal data
|
|
231
|
+
Priority 2: Account takeover
|
|
232
|
+
Priority 3: Abusive permissions
|
|
233
|
+
Priority 4: Overly invasive analytics
|
|
234
|
+
Priority 5: Unvalidated deep links
|
|
235
|
+
|
|
236
|
+
═══════════════════════════════════════════════════════════════
|
|
237
|
+
MOBILE KILL CHAINS
|
|
238
|
+
═══════════════════════════════════════════════════════════════
|
|
239
|
+
|
|
240
|
+
MOBILE KILL CHAIN 1 — TOKEN THEFT VIA BACKUP
|
|
241
|
+
1. Application with allowBackup="true" (Android default)
|
|
242
|
+
2. Attacker with temporary physical access to device
|
|
243
|
+
3. adb backup -apk com.yourapp ./backup.ab
|
|
244
|
+
4. Extraction: android-backup-extractor + tar
|
|
245
|
+
5. Reading: /data/data/com.yourapp/
|
|
246
|
+
shared_prefs/asyncstorage.xml
|
|
247
|
+
6. Cleartext token → account access
|
|
248
|
+
|
|
249
|
+
MOBILE KILL CHAIN 2 — MITM VIA PROXY
|
|
250
|
+
1. Application without certificate pinning
|
|
251
|
+
2. Attacker on same WiFi network
|
|
252
|
+
3. Install mitmproxy + CA on device (if user allows)
|
|
253
|
+
4. Intercept all API calls
|
|
254
|
+
5. Steal Bearer token from headers
|
|
255
|
+
6. Replay token → account access
|
|
256
|
+
|
|
257
|
+
MOBILE KILL CHAIN 3 — BINARY SECRET EXTRACTION
|
|
258
|
+
1. Download APK (from device or third-party stores)
|
|
259
|
+
2. apktool d app.apk (decompilation)
|
|
260
|
+
3. grep -r "API_KEY\|secret\|password\|token" ./
|
|
261
|
+
4. Secrets found in cleartext in index.android.bundle
|
|
262
|
+
5. Use secrets to access infrastructure
|
|
263
|
+
|
|
264
|
+
MOBILE KILL CHAIN 4 — DEEP LINK INJECTION
|
|
265
|
+
1. Application with poorly validated deep link
|
|
266
|
+
myapp://transfer?amount=100&to=victim
|
|
267
|
+
2. Attacker creates link:
|
|
268
|
+
myapp://transfer?amount=9999&to=attacker
|
|
269
|
+
3. Victim clicks link (SMS, email, QR code)
|
|
270
|
+
4. App opens and executes transfer without validation
|
|
271
|
+
5. Money transferred to attacker's account
|
|
272
|
+
|
|
273
|
+
MOBILE KILL CHAIN 5 — FRIDA RUNTIME MANIPULATION
|
|
274
|
+
1. Rooted device with Frida installed
|
|
275
|
+
2. Attack on biometric verification:
|
|
276
|
+
frida -U -n com.yourapp -s bypass_biometric.js
|
|
277
|
+
3. Hook on verification method → always returns true
|
|
278
|
+
4. Access to biometric-protected features
|
|
279
|
+
5. Data extraction or execution of sensitive actions
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# 🚀 EXPO — SECURITY AUDIT GUIDE
|
|
2
|
+
# Comprehensive audit guide for Expo / Expo Router applications
|
|
3
|
+
|
|
4
|
+
═══════════════════════════════════════════════════════════════
|
|
5
|
+
EXPO — TWO MODES, TWO RISK MODELS
|
|
6
|
+
═══════════════════════════════════════════════════════════════
|
|
7
|
+
|
|
8
|
+
EXPO MANAGED WORKFLOW
|
|
9
|
+
──────────────────────
|
|
10
|
+
→ Expo handles native for you
|
|
11
|
+
→ Advantage: simplicity
|
|
12
|
+
→ Security risk: limited native modules
|
|
13
|
+
|
|
14
|
+
IMPLICATIONS:
|
|
15
|
+
→ Keychain/Keystore via expo-secure-store only
|
|
16
|
+
→ Certificate pinning difficult in managed
|
|
17
|
+
→ No custom native modules
|
|
18
|
+
→ Expo Go = additional attack surface in dev
|
|
19
|
+
|
|
20
|
+
EXPO BARE WORKFLOW
|
|
21
|
+
──────────────────────
|
|
22
|
+
→ Full access to native code
|
|
23
|
+
→ Same security model as pure React Native
|
|
24
|
+
→ All React Native fixes apply
|
|
25
|
+
|
|
26
|
+
EXPO GO (DEVELOPMENT ONLY)
|
|
27
|
+
────────────────────────────────────
|
|
28
|
+
⚠️ EXPO GO MUST NEVER BE USED IN PRODUCTION
|
|
29
|
+
→ Expo Go can load any app via QR code
|
|
30
|
+
→ App secrets can be exposed
|
|
31
|
+
→ No certificate pinning possible in Expo Go
|
|
32
|
+
|
|
33
|
+
OTA UPDATES (EXPO UPDATES)
|
|
34
|
+
────────────────────────────
|
|
35
|
+
→ Expo allows Over-The-Air updates of the JS bundle
|
|
36
|
+
→ CRITICAL RISK: if the OTA channel is compromised,
|
|
37
|
+
malicious code can be deployed to all devices
|
|
38
|
+
→ Verify: separate channels (dev/staging/prod)
|
|
39
|
+
→ Verify: update signing configured
|
|
40
|
+
|
|
41
|
+
═══════════════════════════════════════════════════════════════
|
|
42
|
+
VULNERABLE EXPO PATTERNS
|
|
43
|
+
═══════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
46
|
+
EXPO SECURE STORE — CORRECT USAGE
|
|
47
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
48
|
+
|
|
49
|
+
CRITICAL PATTERN 1 — AsyncStorage instead of SecureStore
|
|
50
|
+
DETECT:
|
|
51
|
+
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
52
|
+
await AsyncStorage.setItem('token', authToken)
|
|
53
|
+
|
|
54
|
+
FIX:
|
|
55
|
+
import * as SecureStore from 'expo-secure-store'
|
|
56
|
+
|
|
57
|
+
// expo-secure-store uses:
|
|
58
|
+
// iOS → Keychain Services
|
|
59
|
+
// Android → EncryptedSharedPreferences (API 23+)
|
|
60
|
+
|
|
61
|
+
const TOKEN_KEY = 'auth_token'
|
|
62
|
+
|
|
63
|
+
// Store
|
|
64
|
+
await SecureStore.setItemAsync(TOKEN_KEY, token, {
|
|
65
|
+
keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
|
|
66
|
+
// WHEN_UNLOCKED_THIS_DEVICE_ONLY:
|
|
67
|
+
// - Device must be unlocked to read
|
|
68
|
+
// - Not in iCloud backups
|
|
69
|
+
// - Bound to physical device
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// Read
|
|
73
|
+
const token = await SecureStore.getItemAsync(TOKEN_KEY)
|
|
74
|
+
|
|
75
|
+
// Delete
|
|
76
|
+
await SecureStore.deleteItemAsync(TOKEN_KEY)
|
|
77
|
+
|
|
78
|
+
// ⚠️ LIMITATION: expo-secure-store has a size limit
|
|
79
|
+
// Store only tokens, not large objects
|
|
80
|
+
// For larger data:
|
|
81
|
+
// Encrypt with a key stored in SecureStore
|
|
82
|
+
// then store encrypted data in AsyncStorage
|
|
83
|
+
|
|
84
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
85
|
+
EXPO ENVIRONMENT VARIABLES
|
|
86
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
87
|
+
|
|
88
|
+
CRITICAL PATTERN 2 — Secrets in app.config.js / app.json
|
|
89
|
+
DETECT:
|
|
90
|
+
// app.config.js
|
|
91
|
+
export default {
|
|
92
|
+
extra: {
|
|
93
|
+
apiKey: 'sk-abc123...', // CRITICAL: in the bundle!
|
|
94
|
+
dbPassword: 'secret',
|
|
95
|
+
stripeKey: 'sk_live_...',
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// app.json
|
|
100
|
+
{
|
|
101
|
+
"expo": {
|
|
102
|
+
"extra": {
|
|
103
|
+
"apiKey": "sk-abc123..." // CRITICAL
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
UNDERSTAND:
|
|
109
|
+
expo.extra is embedded in the app's JS bundle.
|
|
110
|
+
Accessible via Constants.expoConfig.extra
|
|
111
|
+
= visible in decompiled bundle
|
|
112
|
+
= visible in Expo Go
|
|
113
|
+
|
|
114
|
+
FIX:
|
|
115
|
+
// app.config.js — Read from CI/CD environment
|
|
116
|
+
export default {
|
|
117
|
+
extra: {
|
|
118
|
+
// ✅ Public key (not secret)
|
|
119
|
+
apiUrl: process.env.EXPO_PUBLIC_API_URL,
|
|
120
|
+
// EXPO_PUBLIC_ variables are injected into the bundle
|
|
121
|
+
// Use ONLY for public values
|
|
122
|
+
|
|
123
|
+
// ❌ Do NOT put here:
|
|
124
|
+
// apiSecret, dbPassword, privateKey, etc.
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Real secret keys stay server-side.
|
|
129
|
+
// The mobile app should NOT have secrets.
|
|
130
|
+
// It authenticates against a backend
|
|
131
|
+
// which has access to the secrets.
|
|
132
|
+
|
|
133
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
134
|
+
EXPO UPDATES — OTA SECURITY
|
|
135
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
136
|
+
|
|
137
|
+
HIGH PATTERN 3 — Poorly configured OTA channels
|
|
138
|
+
DETECT in app.config.js:
|
|
139
|
+
updates: {
|
|
140
|
+
url: 'https://u.expo.dev/...',
|
|
141
|
+
// No channel configuration
|
|
142
|
+
// No signature verification
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
FIX:
|
|
146
|
+
// app.config.js
|
|
147
|
+
updates: {
|
|
148
|
+
url: 'https://u.expo.dev/YOUR-PROJECT-ID',
|
|
149
|
+
enabled: true,
|
|
150
|
+
checkAutomatically: 'ON_LOAD',
|
|
151
|
+
fallbackToCacheTimeout: 0,
|
|
152
|
+
codeSigningCertificate: './code-signing/certificate.pem',
|
|
153
|
+
codeSigningMetadata: {
|
|
154
|
+
keyid: 'main',
|
|
155
|
+
alg: 'rsa-v1_5-sha256',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
runtimeVersion: {
|
|
159
|
+
policy: 'appVersion',
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
// EAS Update: separate channels
|
|
163
|
+
// eas.json
|
|
164
|
+
// {
|
|
165
|
+
// "build": {
|
|
166
|
+
// "production": {
|
|
167
|
+
// "channel": "production"
|
|
168
|
+
// },
|
|
169
|
+
// "staging": {
|
|
170
|
+
// "channel": "staging"
|
|
171
|
+
// }
|
|
172
|
+
// }
|
|
173
|
+
// }
|
|
174
|
+
|
|
175
|
+
// Deploy to prod only after staging validation
|
|
176
|
+
|
|
177
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
178
|
+
EXPO DEEP LINKS
|
|
179
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
180
|
+
|
|
181
|
+
HIGH PATTERN 4 — Expo Router without validation
|
|
182
|
+
DETECT:
|
|
183
|
+
// app/(tabs)/order/[id].tsx
|
|
184
|
+
// ID comes directly from URL without validation
|
|
185
|
+
|
|
186
|
+
export default function OrderScreen() {
|
|
187
|
+
const { id } = useLocalSearchParams()
|
|
188
|
+
// id used directly without validation
|
|
189
|
+
const order = await fetchOrder(id) // IDOR possible!
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
FIX:
|
|
193
|
+
// app/(tabs)/order/[id].tsx
|
|
194
|
+
import { useLocalSearchParams, useRouter } from 'expo-router'
|
|
195
|
+
|
|
196
|
+
export default function OrderScreen() {
|
|
197
|
+
const { id } = useLocalSearchParams<{ id: string }>()
|
|
198
|
+
const router = useRouter()
|
|
199
|
+
|
|
200
|
+
// 1. Validate format
|
|
201
|
+
const orderId = parseInt(id ?? '', 10)
|
|
202
|
+
if (isNaN(orderId) || orderId <= 0) {
|
|
203
|
+
router.replace('/not-found')
|
|
204
|
+
return null
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 2. Ownership check is done server-side
|
|
208
|
+
// The server verifies the order belongs
|
|
209
|
+
// to the authenticated user
|
|
210
|
+
const { data, error } = useQuery({
|
|
211
|
+
queryKey: ['order', orderId],
|
|
212
|
+
queryFn: () => orderApi.getById(orderId),
|
|
213
|
+
// If 403 → server refused → error handled
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// ...
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
═══════════════════════════════════════════════════════════════
|
|
220
|
+
COMPLETE EXPO CHECKLIST
|
|
221
|
+
═══════════════════════════════════════════════════════════════
|
|
222
|
+
|
|
223
|
+
STORAGE
|
|
224
|
+
□ expo-secure-store for all tokens and secrets ?
|
|
225
|
+
□ AsyncStorage only for non-sensitive data ?
|
|
226
|
+
□ No secrets in expo.extra (app.config.js) ?
|
|
227
|
+
|
|
228
|
+
OTA UPDATES
|
|
229
|
+
□ Code signing configured for OTA updates ?
|
|
230
|
+
□ Separate channels: dev / staging / production ?
|
|
231
|
+
□ runtime version policy configured ?
|
|
232
|
+
□ Expo Go forbidden in production ?
|
|
233
|
+
|
|
234
|
+
DEEP LINKS / EXPO ROUTER
|
|
235
|
+
□ URL parameters validated in each screen ?
|
|
236
|
+
□ Auth checked before data access ?
|
|
237
|
+
□ Universal Links configured (not URL scheme only) ?
|
|
238
|
+
|
|
239
|
+
ENVIRONMENT VARIABLES
|
|
240
|
+
□ EXPO_PUBLIC_ only for non-secret values ?
|
|
241
|
+
□ Secrets managed server-side only ?
|
|
242
|
+
□ .env in .gitignore ?
|
|
243
|
+
|
|
244
|
+
BUILD EAS
|
|
245
|
+
□ Secrets configured in EAS Secrets (not in code) ?
|
|
246
|
+
□ Production build tested before release ?
|
|
247
|
+
□ android.allowBackup=false in app.config.js ?
|