원클릭으로
mobile-security
Android security patterns for secure storage, network security, input validation, and authentication.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Android security patterns for secure storage, network security, input validation, and authentication.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Core Android development patterns for Kotlin, including coroutines, lifecycle management, and functional programming idioms.
Apple Combine framework for reactive programming. Publishers, subscribers, operators, and error handling.
Pattern extraction and skill generation for mobile development sessions. Automatically learns from your coding patterns.
Instinct-based learning system with confidence scoring for mobile patterns. Automatically extracts and evolves patterns.
Core Data for iOS persistence. Data models, fetch requests, background contexts, and SwiftData migration.
Kotlin Coroutines and Flow patterns for structured concurrency, error handling, and async operations.
| name | mobile-security |
| description | Android security patterns for secure storage, network security, input validation, and authentication. |
Security best practices for Android.
// Create encrypted preferences
private fun createSecurePrefs(context: Context): SharedPreferences {
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
return EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}
// Usage
class TokenStorage(context: Context) {
private val prefs = createSecurePrefs(context)
var accessToken: String?
get() = prefs.getString("access_token", null)
set(value) = prefs.edit().putString("access_token", value).apply()
fun clear() = prefs.edit().clear().apply()
}
// Generate key in Keystore
fun generateSecretKey(alias: String) {
val keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
)
keyGenerator.init(
KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
.setUserAuthenticationParameters(300, KeyProperties.AUTH_BIOMETRIC_STRONG)
.build()
)
keyGenerator.generateKey()
}
<!-- res/xml/network_security_config.xml -->
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system"/>
</trust-anchors>
</base-config>
<!-- Debug only -->
<debug-overrides>
<trust-anchors>
<certificates src="user"/>
</trust-anchors>
</debug-overrides>
<!-- Certificate pinning -->
<domain-config>
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2025-12-31">
<pin digest="SHA-256">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</pin>
<pin digest="SHA-256">BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=</pin>
</pin-set>
</domain-config>
</network-security-config>
val client = HttpClient(OkHttp) {
engine {
config {
certificatePinner(
CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAA...")
.add("api.example.com", "sha256/BBBB...") // Backup
.build()
)
}
}
}
// ❌ NEVER log sensitive data
Log.d("Auth", "Token: $token")
// ✅ Release-safe logging with Timber
class ReleaseTree : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (priority >= Log.WARN) {
// Send to crash reporting
Crashlytics.log(priority, tag, message)
}
}
}
// In Application
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
} else {
Timber.plant(ReleaseTree())
}
// Validate before use
fun validateEmail(email: String): Result<String> {
return when {
email.isBlank() -> Result.failure(ValidationError.Empty)
!Patterns.EMAIL_ADDRESS.matcher(email).matches() ->
Result.failure(ValidationError.InvalidFormat)
email.length > 254 -> Result.failure(ValidationError.TooLong)
else -> Result.success(email)
}
}
// SQL injection prevention - use parameterized queries
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUser(userId: String): User?
val biometricPrompt = BiometricPrompt(
activity,
executor,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
val cipher = result.cryptoObject?.cipher
// Use cipher to decrypt sensitive data
}
}
)
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Authenticate")
.setNegativeButtonText("Cancel")
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
.build()
biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
# R8 rules for security
-keepattributes SourceFile,LineNumberTable # For crash reports only
# Obfuscate sensitive classes
-repackageclasses 'a'
-allowaccessmodification
# Remove logging
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}
Remember: Security is not optional. Build it in from the start.