Install
$ agentstack add skill-kalshamsi-claude-security-skills-mobile-security ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →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-revieworbandit-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-auditskill already covers the request at a cryptographic level - When auditing container security or infrastructure (use
docker-scout-scanneroriac-scanner) - When the user asks about server-side API security, REST endpoints, or backend code — you MUST decline and recommend
api-security-testerorsecurity-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
- 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.jsonwithreact-native,*.tsx/*.jsx - Flutter:
pubspec.yamlwithflutter,*.dart
- 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
- Run the 10 OWASP Mobile Top 10:2024 checks against each identified file (see Checks section below).
- 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
- Deduplicate and sort findings by severity: Critical > High > Medium > Low.
- Generate the findings report using the Findings Format below.
- 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 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 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]
}
}
// 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:
// 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
}
}
// 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:
// 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
}
// 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:
// 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
// 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 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 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:
// 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
}
}
// 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 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 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
}
// 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:
// 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)
}
}
}
// 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 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 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!))
}
}
// React Native -- cleartext traffic
fetch('http://api.example.com/login', {
method: 'POST',
body: JSON.stringify({ username, password }),
});
SAFE:
// 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.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.