# Security Audit Checklist — Android TV Apps (May 2026)

Run every `find`→`grep`→fix pass below. Most take < 5 min each.

## Pass 1: Hardcoded Secrets

```bash
# API keys, tokens, OAuth client IDs
grep -rn '"[A-Za-z0-9+/=_-]{20,}"' --include="*.kt" app/src/ | grep -v test | grep -v BuildConfig
grep -rn 'ifBlank\s*\{' --include="*.kt" app/src/     # fallback values
grep -rn 'ApiKey\|apiKey\|CLIENT_ID\|clientId\|SECRET' --include="*.kt" app/src/
```

**Fix pattern:**
```kotlin
// BEFORE — hardcoded fallback
get() = BuildConfig.RD_CLIENT_ID.ifBlank { "X245A4XAIBGVM" }

// AFTER — fail loudly with clear error
get() {
    val id = BuildConfig.RD_CLIENT_ID.ifBlank { null }
    requireNotNull(id) { "RD OAuth unavailable: BuildConfig.RD_CLIENT_ID is empty" }
    return id
}
```

## Pass 2: Release-Build Logging

```bash
grep -rn 'Log\.\(d\|i\|w\|e\)(' --include="*.kt" app/src/ | grep -v test | grep -v 'BuildConfig.DEBUG'
```

**Fix pattern — standalone log:**
```kotlin
// BEFORE
android.util.Log.d("Tag", "→ $url")

// AFTER
if (BuildConfig.DEBUG) { android.util.Log.d("Tag", "→ $url") }
```

**Fix pattern — log inside expression:** The `patch` tool wraps can corrupt multiline string concatenation. Prefer `cat` verification after edits.

## Pass 3: Force-Unwrap (!!) Vectors

```bash
grep -rn '!!' --include="*.kt" app/src/main/ | grep -v test | grep -v '//'
```

**Fix patterns by context:**

| Context | Fix |
|---|---|
| `state.error!!` after `state.error != null` | `state.error ?: "Unknown error"` |
| `nextEpisode!!.title` after null check | `nextEpisode?.title ?: return` |
| `displayItem.progress!!` in calculation | `displayItem.progress ?: 0f` |
| `list.find { }!!` | `list.find { } ?: return` |
| `obj!!.field` inside `if (obj != null)` | Extract to local: `val x = obj!!` |

## Pass 4: Coroutine Scope Leaks

```bash
grep -rn 'CoroutineScope(' --include="*.kt" app/src/ | grep -v 'viewModelScope\|lifecycleScope\|supervisorScope'
```

**Fix:** `@Singleton` init blocks should use `runBlocking` for one-shot disk I/O at construction time.

## Pass 5: Network Security Config

```bash
grep -rn 'cleartextTrafficPermitted\|includeSubdomains=\"true\"' app/src/main/res/
```

**Fix:** Remove `includeSubdomains="true"` from debrid/third-party domains. Keep cleartext only on exact domains that need it for OAuth redirects.

## Pass 6: Token Storage Audit

- API keys in plain DataStore → migrate to `SecureTokenStore` (Keystore-backed AES-256/GCM)
- Trakt client secret in plain DataStore → same
- OAuth tokens (Trakt, Debrid) should already use `SecureTokenStore`

## Pass 7: Certificate Pinning

Check all `OkHttpClient.Builder()` calls for missing `certificatePinner()`:
```bash
grep -rn 'OkHttpClient.Builder()' --include="*.kt" app/src/
```

## Pass 8: Exported Components

```bash
grep -rn 'android:exported="true"' app/src/main/AndroidManifest.xml
```

## Post-Fix Verification

```bash
cd nexstream && ./gradlew :app:testDebugUnitTest :app:assembleDebug
```
