Build signing is configured
Why it matters
Code signing is the cryptographic mechanism that proves your binary was built by you and hasn't been tampered with in transit. Without a valid signing configuration, app stores refuse to accept the binary — there is no workaround or exception. For Android, releasing with only the debug keystore (the default development key) means you cannot update your app once published, because Google Play requires all updates to be signed with the same key. A lost or overwritten keystore permanently orphans your published app, blocking all future updates for every existing user. CWE-798 (hardcoded credentials) applies when keystore passwords appear in committed source — exposing your signing key allows anyone to publish malicious updates impersonating your app.
Severity rationale
Critical because unsigned builds are rejected outright by both stores, and a lost Android keystore permanently blocks updates for every existing install.
Remediation
For Expo projects, use EAS Build which manages credentials automatically. For bare React Native Android, generate a release keystore and reference it via environment variables — never commit the keystore file or its password.
// android/app/build.gradle
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE_PATH") ?: "../release.keystore")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEYSTORE_ALIAS")
keyPassword System.getenv("KEYSTORE_KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
Store the keystore file and all four environment variables in your CI secret store (GitHub Actions secrets, EAS secrets, etc.). Back up the keystore in a separate secure location — it cannot be recovered if lost.
Detection
- ID:
build-signing-configured - Severity:
critical - What to look for: For iOS, look for signing configuration in
eas.jsonunderbuild.ios.productionor in Xcode project settings (team ID, provisioning profile, certificate). For Android, checkandroid/app/build.gradlefor asigningConfigsblock oreas.jsonforandroid.production.withoutCredentials: false. Count all signing configuration references found across build files. Verify signing keys/certificates are referenced (not necessarily examining the actual keys themselves, just the configuration). - Pass criteria: Signing configuration exists and is properly referenced for at least 1 target platform. For iOS: Xcode project has signing team ID set, or eas.json has Apple credentials configured. For Android: signingConfigs block exists in build.gradle with keystore reference, or EAS Build credentials configured. No more than 0 signing credentials should be hardcoded in source files.
- Fail criteria: No signing configuration found, signing config is incomplete (references a keystore that doesn't exist), or signing credentials appear to be hardcoded in source code (security risk). Do NOT pass when only debug signing is configured and no release/production signing exists.
- Skip (N/A) when: Never — signing is required for any app store submission.
- Detail on fail: Specify the issue. Example:
"No iOS signing configuration found in Xcode project — Team ID not set"or"Android signingConfigs references keystore at path that doesn't exist: ./keystore.jks" - Remediation: App stores require apps to be digitally signed with a certificate/key. Configure signing:
- For Expo (EAS Build): Use EAS to manage credentials:
eas build --platform ios --auto-submit # EAS handles signing eas build --platform android # EAS handles signing - For React Native iOS:
- In Xcode: Select your project, select your target, go to Signing & Capabilities
- Set Team ID (Apple Developer Team)
- Xcode automatically manages certificates and provisioning profiles
- For React Native Android:
- Create a keystore (one-time):
keytool -genkey -v -keystore my-release.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias my-key-alias - In
android/app/build.gradle, add signingConfigs:signingConfigs { release { storeFile file("../my-release.keystore") storePassword System.getenv("KEYSTORE_PASSWORD") keyAlias System.getenv("KEYSTORE_ALIAS") keyPassword System.getenv("KEYSTORE_KEY_PASSWORD") } }
- Create a keystore (one-time):
- For Expo (EAS Build): Use EAS to manage credentials:
External references
- cwe · CWE-798 — Use of Hard-coded Credentials
- external · apple-code-signing — Apple Developer — Code Signing
- external · android-sign-app — Android Developer — Sign your app
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-store-readiness·automated