--- description: "Security standards for {{PROJECT_NAME}} — ALWAYS APPLIED on every file write" alwaysApply: true --- # Security Standards — {{PROJECT_NAME}} > **Pillar 5**: Security is an always-on rule, not just a reactive agent. > These rules apply to EVERY file write, regardless of feature or context. ## Credential & secret management - **NEVER** hardcode API keys, tokens, or secrets in source code - **NEVER** commit `.env` files — use `.gitignore` and document required vars in `.env.example` - API keys belong in: flavored `--dart-define` build args, or a secrets manager (e.g. AWS Secrets) - Use `flutter_secure_storage` for tokens/credentials — **NEVER** `SharedPreferences` for sensitive data - Obfuscation: enable `--obfuscate --split-debug-info=build/debug-symbols/` for release builds ## Authentication & sessions - JWT/session tokens: stored in `flutter_secure_storage`, never in `SharedPreferences` or local DB - Implement token refresh with retry logic — never let a 401 show a raw error to the user - Certificate pinning: required for production builds on {{AUTH}} — use `dio_pinning_interceptor` - Biometric re-auth: require for any transaction > defined threshold ## Data & privacy - **NEVER** log PII (names, emails, phone numbers, addresses) to console or crash reporters - Sanitize all user inputs before sending to backend - Use `SensitiveWidget` wrapper to exclude screens from screenshots / app switcher thumbnails - Comply with platform privacy requirements: iOS `NSPrivacyAccessedAPITypes`, Android permissions ## Network security - All API calls use HTTPS — no http:// in production - Validate SSL certificates — never bypass with `badCertificateCallback: (_,_,_) => true` - Add a timeout to every HTTP call: `connectTimeout: Duration(seconds: 10)` - Rate-limit sensitive endpoints: auth, OTP, password reset ## Dependency security - Run `dart pub outdated` monthly — flag packages with known CVEs - Never use a package with <100 pub points without explicit tech lead approval - Pin critical security packages to exact versions in `pubspec.yaml` ## Secure coding patterns ```dart // ✅ Correct: secure token storage final storage = FlutterSecureStorage(); await storage.write(key: 'access_token', value: token); // ❌ Wrong: SharedPreferences for sensitive data final prefs = await SharedPreferences.getInstance(); prefs.setString('access_token', token); // NEVER do this // ✅ Correct: PII-safe logging logger.info('User authenticated: userId=${user.id}'); // ok — id, not email logger.debug('Payment processed: orderId=$orderId'); // ok — no card data // ❌ Wrong: PII in logs logger.info('Login: email=${user.email}, phone=${user.phone}'); // NEVER // ✅ Correct: --dart-define for secrets (build arg, not in code) // flutter build apk --dart-define=API_KEY=$API_KEY const apiKey = String.fromEnvironment('API_KEY'); // acceptable // ✅ Correct: certificate pinning with Dio (dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient = () { final client = HttpClient(); client.badCertificateCallback = (cert, host, port) => false; // strict return client; }; ``` ## Deep linking & intent security - Validate all incoming deep link parameters — never trust raw URL params - Use `app_links` package for verified deep link handling - Restrict URL schemes to known patterns — reject unknown schemes - For OAuth callbacks: validate `state` parameter to prevent CSRF ## Storage security - Encrypt locally cached sensitive data using `hive` with `HiveAesCipher` - Clear sensitive data from memory after use (set to null, trigger GC) - Do NOT cache auth tokens in network layer (no `dio_cache_interceptor` for auth endpoints) - Use `SecureRandom` for nonce/token generation — never `Random()` ## Code obfuscation & binary protection ```yaml # android/app/build.gradle — release config buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } ``` ```bash # Flutter release build with obfuscation flutter build apk --release --obfuscate --split-debug-info=build/debug-symbols/ flutter build ipa --release --obfuscate --split-debug-info=build/debug-symbols/ ``` ## Release checklist Before every production release, verify: - [ ] No hardcoded secrets (`grep -r "api_key\|secret\|password\|token" lib/`) - [ ] Debug flags disabled (`kDebugMode` guards on all debug-only paths) - [ ] Obfuscation enabled in release build config - [ ] Certificate pinning active and tested on both platforms - [ ] Crash reporter PII filters configured (Sentry `beforeSend`, Firebase `setConsentType`) - [ ] `flutter_secure_storage` used for all tokens — no `SharedPreferences` for sensitive keys - [ ] Network calls all HTTPS — scan for `http://` in lib/ - [ ] Dependencies audited: `dart pub outdated --json | jq '.packages[] | select(.isDiscontinued)'` - [ ] Deep link parameters validated - [ ] App transport security / network security config reviewed