{"id":"54336879-b4cf-4465-9c37-f37ae8311f1c","shortId":"7ytL77","kind":"skill","title":"security","tagline":"27 Android skills for AI agents (Claude Code, Codex, Cursor). Fixes Supabase auth, Hilt errors, design inconsistency, kapt→ksp, missing UiState states. Reduced my token bills 5×. FitGenZ AI shipped in 18 days.","description":"# Android Security\r\n\r\n## Rule 1: Never store secrets in source code or BuildConfig\r\n\r\n```kotlin\r\n// ❌ Never — committed to git, visible in APK\r\nconst val API_KEY = \"sk-1234567890abcdef\"\r\nbuildConfigField(\"String\", \"API_KEY\", \"\\\"sk-1234567890abcdef\\\"\")\r\n\r\n// ✅ Use local.properties (gitignored) + build script injection\r\n// local.properties (never commit this file)\r\n// API_KEY=sk-1234567890abcdef\r\n\r\n// build.gradle.kts\r\nval apiKey = gradleLocalProperties(rootDir, providers).getProperty(\"API_KEY\") ?: \"\"\r\nbuildConfigField(\"String\", \"API_KEY\", \"\\\"$apiKey\\\"\")\r\n\r\n// ✅ Better: use server-side proxy — never expose API keys in app at all\r\n// Client → Your backend → Third-party API\r\n```\r\n\r\n## Rule 2: Encrypted storage for sensitive data\r\n\r\n```kotlin\r\n// ✅ EncryptedSharedPreferences for tokens, session data\r\nclass SecureStorageImpl @Inject constructor(\r\n    @ApplicationContext context: Context\r\n) : SecureStorage {\r\n    private val masterKey = MasterKey.Builder(context)\r\n        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)\r\n        .build()\r\n\r\n    private val encryptedPrefs = EncryptedSharedPreferences.create(\r\n        context,\r\n        \"secure_prefs\",\r\n        masterKey,\r\n        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,\r\n        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM\r\n    )\r\n\r\n    override fun saveToken(token: String) {\r\n        encryptedPrefs.edit().putString(\"auth_token\", token).apply()\r\n    }\r\n\r\n    override fun getToken(): String? = encryptedPrefs.getString(\"auth_token\", null)\r\n\r\n    override fun clearAll() = encryptedPrefs.edit().clear().apply()\r\n}\r\n```\r\n\r\n## Rule 3: Network Security Config\r\n\r\n```xml\r\n<!-- res/xml/network_security_config.xml -->\r\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<network-security-config>\r\n    <!-- Block all cleartext traffic in production -->\r\n    <base-config cleartextTrafficPermitted=\"false\">\r\n        <trust-anchors>\r\n            <certificates src=\"system\" />\r\n        </trust-anchors>\r\n    </base-config>\r\n\r\n    <!-- Allow cleartext only for debug -->\r\n    <debug-overrides>\r\n        <trust-anchors>\r\n            <certificates src=\"system\" />\r\n            <certificates src=\"user\" />  <!-- allow Charles/mitmproxy in debug -->\r\n        </trust-anchors>\r\n    </debug-overrides>\r\n</network-security-config>\r\n```\r\n\r\n```xml\r\n<!-- AndroidManifest.xml -->\r\n<application\r\n    android:networkSecurityConfig=\"@xml/network_security_config\"\r\n    android:usesCleartextTraffic=\"false\">\r\n```\r\n\r\n## Rule 4: Certificate pinning\r\n\r\n```kotlin\r\n// ✅ OkHttp certificate pinning for high-security apps\r\nval certificatePinner = CertificatePinner.Builder()\r\n    .add(\"api.myapp.com\", \"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\")  // leaf\r\n    .add(\"api.myapp.com\", \"sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=\")  // backup\r\n    .build()\r\n\r\nOkHttpClient.Builder()\r\n    .certificatePinner(certificatePinner)\r\n    .build()\r\n```\r\n\r\n## Rule 5: Prevent screenshots and screen recording\r\n\r\n```kotlin\r\n// ✅ Prevent screenshots on sensitive screens (banking, passwords)\r\n@Composable\r\nfun SecureScreen(content: @Composable () -> Unit) {\r\n    val activity = LocalContext.current as? Activity\r\n    DisposableEffect(Unit) {\r\n        activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE)\r\n        onDispose {\r\n            activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)\r\n        }\r\n    }\r\n    content()\r\n}\r\n```\r\n\r\n## Rule 6: Backup rules — exclude sensitive files\r\n\r\n```xml\r\n<!-- res/xml/backup_rules.xml -->\r\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<full-backup-content>\r\n    <exclude domain=\"sharedpref\" path=\"secure_prefs.xml\" />\r\n    <exclude domain=\"database\" path=\"app_database\" />\r\n    <exclude domain=\"file\" path=\".\" />\r\n</full-backup-content>\r\n\r\n<!-- AndroidManifest.xml -->\r\n<application\r\n    android:allowBackup=\"false\"\r\n    android:dataExtractionRules=\"@xml/backup_rules\">\r\n```\r\n\r\n## Common Mistakes\r\n\r\n❌ Storing tokens in plain SharedPreferences — use EncryptedSharedPreferences\r\n❌ API keys in BuildConfig — visible by decompiling APK\r\n❌ `android:allowBackup=\"true\"` without backup rules — sensitive DB backed up to Google\r\n❌ `android:usesCleartextTraffic=\"true\"` in production — all traffic unencrypted\r\n❌ Logging tokens or PII in debug — `Log.d(\"token\", userToken)` visible in logcat\r\n❌ No root detection for banking/payment apps — use Play Integrity API","tags":["security","android","agent","skills","piyushverma0","agent-skills","ai-agent","antigravity","claude-code","codex","cursor","gemini-cli"],"capabilities":["skill","source-piyushverma0","skill-security","topic-agent-skills","topic-ai-agent","topic-android","topic-antigravity","topic-claude-code","topic-codex","topic-cursor","topic-gemini-cli","topic-hilt","topic-jetpack-compose","topic-kotlin","topic-material3"],"categories":["android-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/piyushverma0/android-agent-skills/security","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add piyushverma0/android-agent-skills","source_repo":"https://github.com/piyushverma0/android-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.454","qualityRationale":"deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 8 github stars · SKILL.md body (4,383 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:09:10.913Z","embedding":null,"createdAt":"2026-05-18T13:14:50.778Z","updatedAt":"2026-05-18T19:09:10.913Z","lastSeenAt":"2026-05-18T19:09:10.913Z","tsv":"'1':38 '1234567890abcdef':61,68,84 '18':33 '2':121 '27':2 '3':191 '4':198 '5':28,227 '6':267 'activ':248,251,254,260 'add':213,217 'addflag':256 'aes256':148,160,163 'agent':7 'ai':6,30 'allowbackup':292 'android':3,35,291,303 'api':57,64,80,92,96,107,119,283,332 'api.myapp.com':214,218 'apikey':87,98 'apk':54,290 'app':110,209,328 'appli':175,189 'applicationcontext':137 'auth':14,172,181 'back':299 'backend':115 'backup':220,268,295 'bank':239 'banking/payment':327 'better':99 'bill':27 'build':72,150,221,225 'build.gradle.kts':85 'buildconfig':46,286 'buildconfigfield':62,94 'certif':199,203 'certificatepinn':211,223,224 'certificatepinner.builder':212 'class':133 'claud':8 'clear':188 'clearal':186 'clearflag':262 'client':113 'code':9,44 'codex':10 'commit':49,77 'common':274 'compos':241,245 'config':194 'const':55 'constructor':136 'content':244,265 'context':138,139,145,155 'cursor':11 'data':126,132 'day':34 'db':298 'debug':316 'decompil':289 'design':17 'detect':325 'disposableeffect':252 'encrypt':122 'encryptedpref':153 'encryptedprefs.edit':170,187 'encryptedprefs.getstring':180 'encryptedsharedprefer':128,282 'encryptedsharedpreferences.create':154 'encryptedsharedpreferences.prefkeyencryptionscheme':159 'encryptedsharedpreferences.prefvalueencryptionscheme':162 'error':16 'exclud':270 'expos':106 'file':79,272 'fitgenz':29 'fix':12 'fun':166,177,185,242 'gcm':149,164 'getproperti':91 'gettoken':178 'git':51 'gitignor':71 'googl':302 'gradlelocalproperti':88 'high':207 'high-secur':206 'hilt':15 'inconsist':18 'inject':74,135 'integr':331 'kapt':19 'key':58,65,81,93,97,108,284 'kotlin':47,127,201,233 'ksp':20 'leaf':216 'local.properties':70,75 'localcontext.current':249 'log':311 'log.d':317 'logcat':322 'masterkey':143,158 'masterkey.builder':144 'masterkey.keyscheme':147 'miss':21 'mistak':275 'network':192 'never':39,48,76,105 'null':183 'okhttp':202 'okhttpclient.builder':222 'ondispos':259 'overrid':165,176,184 'parti':118 'password':240 'pii':314 'pin':200,204 'plain':279 'play':330 'pref':157 'prevent':228,234 'privat':141,151 'product':307 'provid':90 'proxi':104 'putstr':171 'record':232 'reduc':24 'root':324 'rootdir':89 'rule':37,120,190,197,226,266,269,296 'savetoken':167 'screen':231,238 'screenshot':229,235 'script':73 'secret':41 'secur':1,36,156,193,208,258,264 'securescreen':243 'securestorag':140 'securestorageimpl':134 'sensit':125,237,271,297 'server':102 'server-sid':101 'session':131 'setkeyschem':146 'sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa':215 'sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb':219 'sharedprefer':280 'ship':31 'side':103 'siv':161 'sk':60,67,83 'sk-1234567890abcdef':59,66,82 'skill':4 'skill-security' 'sourc':43 'source-piyushverma0' 'state':23 'storag':123 'store':40,276 'string':63,95,169,179 'supabas':13 'third':117 'third-parti':116 'token':26,130,168,173,174,182,277,312,318 'topic-agent-skills' 'topic-ai-agent' 'topic-android' 'topic-antigravity' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-gemini-cli' 'topic-hilt' 'topic-jetpack-compose' 'topic-kotlin' 'topic-material3' 'traffic':309 'true':293,305 'uistat':22 'unencrypt':310 'unit':246,253 'use':69,100,281,329 'usertoken':319 'usescleartexttraff':304 'val':56,86,142,152,210,247 'visibl':52,287,320 'window':255,261 'windowmanager.layoutparams.flag':257,263 'without':294 'xml':195,196,273","prices":[{"id":"d889b9e3-7550-4cc2-9137-2f0a48c4ae4a","listingId":"54336879-b4cf-4465-9c37-f37ae8311f1c","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"piyushverma0","category":"android-agent-skills","install_from":"skills.sh"},"createdAt":"2026-05-18T13:14:50.778Z"}],"sources":[{"listingId":"54336879-b4cf-4465-9c37-f37ae8311f1c","source":"github","sourceId":"piyushverma0/android-agent-skills/security","sourceUrl":"https://github.com/piyushverma0/android-agent-skills/tree/main/skills/security","isPrimary":false,"firstSeenAt":"2026-05-18T13:14:50.778Z","lastSeenAt":"2026-05-18T19:09:10.913Z"}],"details":{"listingId":"54336879-b4cf-4465-9c37-f37ae8311f1c","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"piyushverma0","slug":"security","github":{"repo":"piyushverma0/android-agent-skills","stars":8,"topics":["agent-skills","ai-agent","android","antigravity","claude-code","codex","cursor","gemini-cli","hilt","jetpack-compose","kotlin","material3","open-source","skills","supabase"],"license":"mit","html_url":"https://github.com/piyushverma0/android-agent-skills","pushed_at":"2026-04-27T09:15:31Z","description":"27 Android skills for AI agents (Claude Code, Codex, Cursor). Fixes Supabase auth, Hilt errors, design inconsistency, kapt→ksp, missing UiState states. Reduced my token bills 5×. FitGenZ AI shipped in 18 days.","skill_md_sha":"194626a3d848ba43ba0314a1c04b0ad157290a55","skill_md_path":"skills/security/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/piyushverma0/android-agent-skills/tree/main/skills/security"},"layout":"multi","source":"github","category":"android-agent-skills","frontmatter":{},"skills_sh_url":"https://skills.sh/piyushverma0/android-agent-skills/security"},"updatedAt":"2026-05-18T19:09:10.913Z"}}