1. Security Assessment

Security Issues Overview

1.1 Authentication & Authorization

Status: ⚠️Warning

Findings:

  • OAuth2 token-based authentication implemented with access and refresh tokens
  • Automatic token refresh mechanism on 401 errors
  • Social login support (Facebook, Google, Apple Sign In)
  • Security concern: Access tokens and refresh tokens stored in plain text in SQLite database
  • Tokens persist across app restarts without encryption
  • No token expiration validation on client side
  • Username and UID also stored unencrypted in database

Evidence:

  • lib/rest_client.dart: OAuth2 endpoints (/app/oauth/token/mobile, /app/oauth/social/mobile)
  • lib/state_models/session_state.dart: Tokens stored directly in database as plain strings (lines 84-106)
  • lib/base_singleton.dart: Automatic token refresh on 401 errors (lines 114-151)
  • lib/db/database.dart: Moor/SQLite database used for storage
  • lib/routes/login_route.dart: Login flow stores tokens without encryption

Risk Level: Medium Risk

Recommendation:

  • Encrypt sensitive tokens before storing in database using Flutter's secure storage (e.g., flutter_secure_storage)
  • Use Android Keystore/iOS Keychain for storing sensitive credentials
  • Implement proper token revocation on logout

1.2 Data Storage & Encryption

Status: Fail

Findings:

  • Critical: Sensitive authentication data stored in plain text in SQLite database
  • Access tokens, refresh tokens, usernames, UIDs, and email addresses stored unencrypted
  • Moor/SQLite database file accessible on device without encryption
  • No encryption at rest for sensitive user data
  • Database file can be extracted from device and read directly
  • No use of platform secure storage (Android Keystore/iOS Keychain) for sensitive data

Evidence:

  • lib/state_models/session_state.dart: All sensitive data stored as plain strings in database
  • accessToken stored directly (line 88)
  • refreshToken stored directly (line 104)
  • username, uid, email stored unencrypted (lines 64, 80, 72)
  • lib/db/database.dart: Moor database implementation without encryption layer
  • No encryption libraries or secure storage packages in pubspec.yaml
  • Database file location: App's data directory (accessible on rooted/jailbroken devices)

Risk Level: High Risk

Recommendation:

  • Immediate actions:
  • Migrate sensitive data to flutter_secure_storage package
  • Use Android Keystore and iOS Keychain for credential storage
  • Encrypt database file or sensitive columns using SQLCipher
  • Remove plain text storage of tokens and credentials
  • Short-term:
  • Implement database encryption for all sensitive fields
  • Use platform-specific secure storage APIs

1.3 Network Security

Status: Fail

Findings:

  • Critical: Certificate validation can be disabled via remote configuration
  • OnlyAllowTinqOverride accepts invalid SSL certificates for specific host without proper validation
  • Certificate validation controlled by Firebase Remote Config flag override_bad_certificates
  • No certificate pinning implemented
  • Hostname validation only checks for exact match, not certificate chain validation
  • AllowAllOverride class exists (though not used in production) that accepts all certificates
  • Remote config can dynamically enable/disable certificate validation, creating security risk

Evidence:

  • lib/utils/http_overrides.dart:
  • OnlyAllowTinqOverride accepts certificates for "max.korting.tinq.nl" without proper validation (lines 15-23)
  • AllowAllOverride accepts all certificates (lines 5-12) - dangerous pattern
  • lib/main.dart and lib/main_prod.dart:
  • HttpOverrides.global = OnlyAllowTinqOverride() (line 27)
  • Remote config can override: FirebaseRemoteConfig.instance.getBool('override_bad_certificates') (lines 38-40)
  • Default sets override_bad_certificates: true (line 30)
  • No certificate pinning implementation found
  • No SSL/TLS version enforcement

Risk Level: Critical Risk

Recommendation:

  • Immediate actions:
  • Remove certificate validation override functionality
  • Remove AllowAllOverride class entirely
  • Implement proper certificate pinning using certificate_pinning or similar package
  • Remove remote config flag that controls certificate validation
  • Enforce strict SSL/TLS validation
  • Short-term:
  • Implement certificate pinning for API endpoints
  • Add SSL/TLS version checks (enforce TLS 1.2+)
  • Remove ability to disable certificate validation via remote config

1.4 Secrets & Credentials Management

Status: Fail

Findings:

  • Critical: Sensitive files including certificates, private keys, and service account credentials are stored directly in the repository
  • Android certificates and keys:
  • android-src-files/tinq4u.keystore.jks - Android signing keystore
  • android-src-files/private_key.pepk - Private key file
  • android-src-files/deployment_cert.der - Deployment certificate
  • android-src-files/upload_cert.der - Upload certificate
  • android-src-files/fastlane-serivce-account.json - Google Play service account with embedded private key
  • android-src-files/google-services.json - Firebase configuration
  • Apple certificates and keys:
  • apple-src-files/Signin-with-apple-AuthKey_63ZBT4A89B.p8 - Apple Sign In private key
  • apple-src-files/ApplePushServices.certSigningRequest - Certificate signing request
  • src-assets/AuthKey_9BWX5U9947.p8 - Additional Apple private key
  • Hardcoded path reference to sensitive file in android/fastlane/Appfile
  • No centralized secrets management system
  • Risk of credentials being exposed in version control history
  • No .gitignore entries for sensitive directories (android-src-files/, apple-src-files/, src-assets/)

Evidence:

  • android-src-files/ directory contains multiple sensitive files
  • apple-src-files/ directory contains Apple private keys
  • src-assets/AuthKey_9BWX5U9947.p8 contains private key in repository
  • android/fastlane/Appfile line 1: Hardcoded path to service account JSON
  • .gitignore does not exclude sensitive directories
  • Private keys visible in search results (PEM format)

Risk Level: Critical Risk

Recommendation:

  • Immediate actions:
  • Move all sensitive files to centralized secrets management (e.g., AWS Secrets Manager, HashiCorp Vault, or secure cloud storage)
  • Remove sensitive files from repository (after backing up to secure location)
  • Add sensitive directories to .gitignore: android-src-files/, apple-src-files/, src-assets/
  • Rotate all exposed credentials (keystores, service accounts, private keys)
  • Update android/fastlane/Appfile to reference secrets from secure location
  • Short-term:
  • Implement secrets injection in CI/CD pipeline (Codemagic secrets management)
  • Use environment variables or secure file injection for build-time secrets

1.6 Code Obfuscation & Reverse Engineering

Status: Fail

Findings:

  • Critical: Code obfuscation and minification disabled in release builds
  • minifyEnabled = false and shrinkResources = false in Android release configuration
  • ProGuard rules file exists but not used (obfuscation disabled)
  • No R8 code shrinking enabled
  • Source code, API endpoints, and business logic easily reverse-engineerable
  • No string encryption or code protection mechanisms
  • Comment in build.gradle indicates minification disabled due to crashes (technical debt)

Evidence:

  • android/app/build.gradle lines 100-106:
release {
    signingConfig signingConfigs.release
    // Turning off any type of minification to mitigate still unknown
    // crashes on certain devices.
    minifyEnabled false
    shrinkResources false
}
  • android/app/proguard-rules.pro: ProGuard rules exist but unused
  • No Flutter obfuscation flags in build commands
  • No code protection or anti-tampering measures

Risk Level: High Risk

Recommendation:

  • Immediate actions:
  • Enable code obfuscation and minification for release builds
  • Investigate and fix crashes that prevented minification
  • Enable R8 code shrinking for Android
  • Use Flutter's --obfuscate flag for release builds
  • Short-term:
  • Enable ProGuard/R8 with proper rules