# Mobile Security

> Use when auditing an Android or iOS application for security issues, reviewing React Native or Flutter code, checking mobile authentication or insecure data storage, or covering the OWASP Mobile Top 10:2024.

- **Type:** Skill
- **Install:** `agentstack add skill-kalshamsi-claude-security-skills-mobile-security`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [kalshamsi](https://agentstack.voostack.com/s/kalshamsi)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [kalshamsi](https://github.com/kalshamsi)
- **Source:** https://github.com/kalshamsi/claude-security-skills/tree/main/skills/mobile-security

## Install

```sh
agentstack add skill-kalshamsi-claude-security-skills-mobile-security
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Mobile Security Audit

This skill performs static code analysis for mobile application security vulnerabilities across Android (Java/Kotlin), iOS (Swift/Objective-C), React Native (JavaScript/TypeScript), and Flutter (Dart) projects. It identifies vulnerabilities mapped to all 10 OWASP Mobile Top 10:2024 categories, providing CWE references and concrete UNSAFE/SAFE code pairs for remediation.

## When to Use

- When the user asks to "audit mobile security", "review mobile app code", or "check for mobile vulnerabilities"
- When the user mentions "OWASP Mobile Top 10", "mobile pentest", or "mobile app security review"
- When scanning Android projects (Kotlin/Java with `AndroidManifest.xml`, `build.gradle`)
- When scanning iOS projects (Swift/Objective-C with `Info.plist`, `.xcodeproj`)
- When reviewing React Native or Flutter projects for mobile-specific security issues
- When a pull request modifies authentication, data storage, network communication, or cryptographic code in a mobile app
- When the user asks about "insecure data storage", "certificate pinning", "root/jailbreak detection", or "WebView security"

## When NOT to Use

- When the user is asking about server-side/backend security (use `security-review` or `bandit-sast`)
- When the user wants runtime dynamic analysis of a running mobile app (use a DAST tool)
- When reviewing general web application code unrelated to mobile platforms
- When the `crypto-audit` skill already covers the request at a cryptographic level
- When auditing container security or infrastructure (use `docker-scout-scanner` or `iac-scanner`)
- When the user asks about **server-side API security, REST endpoints, or backend code** — you **MUST** decline and recommend `api-security-tester` or `security-review`
- When the user asks about **OWASP Web Top 10 issues** (SQL injection, XSS, CSRF) — you **MUST** decline, explain that this skill covers OWASP Mobile Top 10:2024 only, and recommend `security-review`

## Prerequisites

### Tool Installed (Preferred)

No external tool required. This skill uses code analysis only.

All checks are performed through pattern matching and code inspection -- no CLI tool needs to be installed, configured, or invoked.

### Tool Not Installed (Fallback)

This skill is always available as a pure analysis skill. There is no fallback mode because there is no external tool dependency. All checks run directly through code analysis.

## Workflow

1. **Detect project platform** -- Inspect project files to determine which mobile platforms are in use:
   - Android: `AndroidManifest.xml`, `build.gradle`, `*.kt`, `*.java`
   - iOS: `Info.plist`, `*.xcodeproj`, `*.swift`, `*.m`, `*.h`
   - React Native: `package.json` with `react-native`, `*.tsx`/`*.jsx`
   - Flutter: `pubspec.yaml` with `flutter`, `*.dart`
2. **Identify security-relevant files** -- Search for files that handle:
   - Authentication and credential management
   - Data storage (SharedPreferences, UserDefaults, Keychain, SQLite)
   - Network communication (HTTP clients, WebSocket, certificate pinning)
   - WebView configurations
   - Cryptographic operations
   - Intent/deep-link handling
   - Logging and debugging
   - Binary protections and code obfuscation configuration
3. **Run the 10 OWASP Mobile Top 10:2024 checks** against each identified file (see Checks section below).
4. **For each finding:**
   a. Determine severity (Critical / High / Medium / Low) using the Reference Tables
   b. Map to the relevant CWE identifier
   c. Map to the relevant OWASP Mobile Top 10:2024 category
   d. Record file path and line number
   e. Generate the UNSAFE pattern found and the corresponding SAFE fix
   f. Draft a remediation recommendation
5. **Deduplicate and sort** findings by severity: Critical > High > Medium > Low.
6. **Generate the findings report** using the Findings Format below.
7. **Summarize** -- State total findings, breakdown by severity, and top 3 remediation priorities.

## Checks

### Check 1: Improper Credential Usage (M1)

**CWE-798** (Use of Hard-coded Credentials) | **M1** - Improper Credential Usage | Severity: **Critical**

**WHY:** Hardcoded API keys, passwords, and tokens in mobile app source code are trivially extractable through reverse engineering. Unlike server-side code, mobile binaries are distributed to end users, making any embedded secret effectively public. Attackers routinely decompile APKs and IPAs to harvest credentials.

**UNSAFE:**

```kotlin
// Kotlin Android -- hardcoded API key in source
class ApiClient {
    companion object {
        private const val API_KEY = "sk-live-a1b2c3d4e5f6g7h8i9j0"
        private const val API_SECRET = "super_secret_key_12345"
    }

    fun makeRequest() {
        val connection = URL("https://api.example.com").openConnection()
        connection.setRequestProperty("Authorization", "Bearer $API_KEY")
    }
}
```

```swift
// Swift iOS -- hardcoded credentials
class NetworkManager {
    let apiKey = "HARDCODED_GOOGLE_API_KEY_EXAMPLE"
    let secretToken = "HARDCODED_TOKEN_DO_NOT_COMMIT"

    func authenticate() {
        let headers = ["X-API-Key": apiKey]
    }
}
```

```dart
// Flutter -- hardcoded keys in Dart source
class Config {
  static const String apiKey = 'HARDCODED_API_KEY_DO_NOT_DO_THIS';
  static const String dbPassword = 'production_password_123';
}
```

**SAFE:**

```kotlin
// Load credentials from secure sources at runtime
class ApiClient(private val context: Context) {
    private fun getApiKey(): String {
        // Option 1: BuildConfig from local.properties (not committed to VCS)
        return BuildConfig.API_KEY
        // Option 2: Android Keystore for sensitive credentials
        // Option 3: Fetch from server after authentication
    }
}
```

```swift
// Use Keychain or server-side token exchange
class NetworkManager {
    func getApiKey() -> String? {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "apiKey",
            kSecReturnData as String: true
        ]
        var result: AnyObject?
        SecItemCopyMatching(query as CFDictionary, &result)
        return (result as? Data).flatMap { String(data: $0, encoding: .utf8) }
    }
}
```

---

### Check 2: Inadequate Supply Chain Security (M2)

**CWE-829** (Inclusion of Functionality from Untrusted Control Sphere) | **M2** - Inadequate Supply Chain Security | Severity: **High**

**WHY:** Mobile apps depend on third-party SDKs, libraries, and build tools. Compromised or outdated dependencies can introduce malware, data exfiltration, or known vulnerabilities into the app. Supply chain attacks targeting mobile SDKs (e.g., ad networks, analytics) have been documented in production apps on both app stores.

**UNSAFE:**

```kotlin
// build.gradle.kts -- no dependency verification, wildcard versions
dependencies {
    implementation("com.unknown.sdk:analytics:+")  // Wildcard version
    implementation("com.github.random-user:crypto-lib:1.0")  // Unvetted source
    implementation("com.squareup.okhttp3:okhttp:3.12.0")  // Known vulnerable version
}
```

```dart
// pubspec.yaml -- unvetted dependencies, no version pinning
dependencies:
  flutter:
    sdk: flutter
  sketchy_analytics: any
  http: ^0.13.0
  untrusted_crypto:
    git:
      url: https://github.com/random-user/untrusted_crypto.git
```

**SAFE:**

```kotlin
// build.gradle.kts -- pinned versions, verified sources, dependency verification
dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.12.0")  // Pinned, patched version
    implementation("com.google.android.gms:play-services-auth:21.0.0")  // Verified publisher
}

// Enable Gradle dependency verification
// In gradle/verification-metadata.xml -- enforce checksums
```

```dart
// pubspec.yaml -- pinned versions, trusted sources only
dependencies:
  flutter:
    sdk: flutter
  http: 1.2.0  // Exact version pin
  dio: 5.4.0   // Well-maintained, audited library
```

---

### Check 3: Insecure Authentication/Authorization (M3)

**CWE-287** (Improper Authentication) | **M3** - Insecure Authentication/Authorization | Severity: **Critical**

**WHY:** Mobile apps often implement client-side authentication checks that can be bypassed by an attacker with a debugger or modified binary. Storing session tokens insecurely, failing to validate tokens server-side, or using biometric authentication without a server-side fallback leaves the app vulnerable to unauthorized access.

**UNSAFE:**

```kotlin
// Kotlin Android -- client-side only auth check
class AuthManager(private val context: Context) {
    fun isAuthenticated(): Boolean {
        // Client-side check only -- trivially bypassed
        val prefs = context.getSharedPreferences("auth", Context.MODE_PRIVATE)
        return prefs.getBoolean("is_logged_in", false)
    }

    fun login(username: String, password: String) {
        // Storing credentials in plain SharedPreferences
        val prefs = context.getSharedPreferences("auth", Context.MODE_PRIVATE)
        prefs.edit().putString("username", username).apply()
        prefs.edit().putString("password", password).apply()
        prefs.edit().putBoolean("is_logged_in", true).apply()
    }
}
```

```swift
// Swift iOS -- biometric auth without server-side validation
func authenticateUser() {
    let context = LAContext()
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
                           localizedReason: "Authenticate") { success, _ in
        if success {
            // No server-side token validation -- bypass with Frida
            self.grantAccess()
        }
    }
}
```

**SAFE:**

```kotlin
// Server-validated auth with secure token storage
class AuthManager(private val context: Context) {
    private val encryptedPrefs = EncryptedSharedPreferences.create(
        "secure_auth",
        MasterKey.Builder(context).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build(),
        context,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )

    suspend fun isAuthenticated(): Boolean {
        val token = encryptedPrefs.getString("access_token", null) ?: return false
        // Always validate token server-side
        return apiService.validateToken(token).isValid
    }
}
```

```swift
// Biometric auth backed by Keychain and server validation
func authenticateUser() {
    let context = LAContext()
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
                           localizedReason: "Authenticate") { success, _ in
        if success {
            // Retrieve Keychain-stored token and validate with server
            guard let token = KeychainHelper.getToken("access_token") else { return }
            self.apiService.validateToken(token) { isValid in
                if isValid { self.grantAccess() }
            }
        }
    }
}
```

---

### Check 4: Insufficient Input/Output Validation (M4)

**CWE-79** (Improper Neutralization of Input During Web Page Generation) | **M4** - Insufficient Input/Output Validation | Severity: **High**

**WHY:** Mobile apps that use WebViews, deep links, or inter-process communication (Intents, URL schemes) without proper input validation are vulnerable to injection attacks. Malicious input through deep links can trigger XSS in WebViews, SQL injection in local databases, or path traversal in file operations.

**UNSAFE:**

```kotlin
// Kotlin Android -- WebView with JavaScript injection via Intent
class WebViewActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val webView = WebView(this)
        webView.settings.javaScriptEnabled = true
        webView.settings.allowFileAccess = true
        webView.settings.allowUniversalAccessFromFileURLs = true

        // Loading URL directly from intent without validation
        val url = intent.getStringExtra("url") ?: ""
        webView.loadUrl(url)  // Arbitrary URL loading -- XSS, phishing
    }
}
```

```swift
// Swift iOS -- unvalidated deep link handling
func application(_ app: UIApplication, open url: URL,
                 options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
    // No validation of URL scheme or parameters
    let webView = WKWebView()
    webView.load(URLRequest(url: url))  // Arbitrary URL loading
    return true
}
```

```dart
// Flutter -- SQL injection in local database
Future getUser(String username) async {
  final db = await database;
  // String interpolation in SQL -- injection vulnerability
  final result = await db.rawQuery(
    "SELECT * FROM users WHERE username = '$username'"
  );
  return result.isNotEmpty ? User.fromMap(result.first) : null;
}
```

**SAFE:**

```kotlin
// Validate and sanitize all external input
class WebViewActivity : AppCompatActivity() {
    private val allowedHosts = setOf("app.example.com", "cdn.example.com")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val webView = WebView(this)
        webView.settings.javaScriptEnabled = true
        webView.settings.allowFileAccess = false
        webView.settings.allowUniversalAccessFromFileURLs = false

        val url = intent.getStringExtra("url") ?: return
        val uri = Uri.parse(url)
        if (uri.scheme == "https" && uri.host in allowedHosts) {
            webView.loadUrl(url)
        }
    }
}
```

```dart
// Use parameterized queries
Future getUser(String username) async {
  final db = await database;
  final result = await db.query(
    'users',
    where: 'username = ?',
    whereArgs: [username],
  );
  return result.isNotEmpty ? User.fromMap(result.first) : null;
}
```

---

### Check 5: Insecure Communication (M5)

**CWE-295** (Improper Certificate Validation) | **M5** - Insecure Communication | Severity: **Critical**

**WHY:** Mobile apps frequently communicate over untrusted networks (public Wi-Fi, cellular). Without certificate pinning and proper TLS configuration, attackers can perform man-in-the-middle attacks to intercept credentials, session tokens, and sensitive data. Disabling certificate validation or ATS is a common developer shortcut that destroys transport security.

**UNSAFE:**

```kotlin
// Kotlin Android -- trust all certificates
val trustAllCerts = arrayOf(object : X509TrustManager {
    override fun checkClientTrusted(chain: Array, authType: String) {}
    override fun checkServerTrusted(chain: Array, authType: String) {}
    override fun getAcceptedIssuers(): Array = arrayOf()
})

val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, SecureRandom())
OkHttpClient.Builder().sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
```

```swift
// Swift iOS -- disabling ATS entirely in Info.plist
// NSAppTransportSecurity
// 
//     NSAllowsArbitraryLoads
//     
// 

// Swift -- disabling server trust evaluation
class InsecureDelegate: NSObject, URLSessionDelegate {
    func urlSession(_ session: URLSession,
                    didReceive challenge: URLAuthenticationChallenge,
                    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // Accept any certificate
        completionHandler(.useCredential,
                          URLCredential(trust: challenge.protectionSpace.serverTrust!))
    }
}
```

```typescript
// React Native -- cleartext traffic
fetch('http://api.example.com/login', {
  method: 'POST',
  body: JSON.stringify({ username, password }),
});
```

**SAFE:**

```kotlin
// Kotlin Android -- certificate pinning with OkHttp
val certificatePinner = CertificatePinner.Builder()
    .add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
    .add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")  // Backup pin
    .build()

val client = OkHttpClient.Builder()

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kalshamsi](https://github.com/kalshamsi)
- **Source:** [kalshamsi/claude-security-skills](https://github.com/kalshamsi/claude-security-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-kalshamsi-claude-security-skills-mobile-security
- Seller: https://agentstack.voostack.com/s/kalshamsi
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
