expo
expo copied to clipboard
Build-time secrets extraMavenRepos.credentials bundled into APK/AAB
Minimal reproducible example
https://github.com/MatthieuLemoine/expo-app-config-leak
Steps to reproduce
I already reached out to Expo Support through [email protected]/[email protected] who asked me to create an issue with a minimal reproduction
Summary
When using the extraMavenRepos option in expo-build-properties, credentials defined in the app config are written to both gradle.properties (which is correct) and also included in the final APK/AAB, as part of the bundled app.config.
This results in a critical security issue: Maven repository credentials are exposed to anyone who downloads the app.
How to reproduce
- Create a new Expo project:
npx create-expo-app@latest
- Install
expo-build-propertiesand configure it inapp.json:
"plugins": [
[
"expo-build-properties",
{
"android": {
"extraMavenRepos": [
{
"url": "https://example.com/maven",
"authentication": "header",
"credentials": {
"name": "x-api-key",
"value": "MY_API_KEY"
}
}
]
}
}
]
]
- Generate Android native project:
npx expo prebuild --clean --platform android
- Run a release build:
npx expo run:android --variant release
- Find the generated APK or AAB in
android/app/build/outputs/apk/releaseand inspect its contents (replace extension by .zip then unarchive). - You will find
assets/app.configincluded in the binary, with the full structure and credentials in cleartext.
Why this is a problem
- app.config is bundled for runtime needs (e.g. Expo Go or updates), but includes many build-only properties.
- The current implementation leaks secrets like:
- Maven repository credentials
- Apple team ID
- EAS project ID
- All expo-build-properties settings
This goes against secure-by-default principles and can lead to credential leaks in production apps.
Expected Behavior
- Only runtime-relevant properties should be bundled in the release build.
- Build-time data, including anything under
expo-build-properties, should be stripped automatically. - Credentials should never end up in the app binary.
Suggested Fixes
- Remove support for credentials in
extraMavenRepos, or emit a loud warning. - Redesign what parts of the app config are bundled with the final binary.
Environment
expo-env-info 1.3.3 environment info:
System:
OS: macOS 15.4.1
Shell: 5.9 - /bin/zsh
Binaries:
Node: 18.19.0 - ~/Library/Caches/fnm_multishells/39044_1746633985892/bin/node
Yarn: 1.22.21 - /opt/homebrew/bin/yarn
npm: 10.2.3 - ~/Library/Caches/fnm_multishells/39044_1746633985892/bin/npm
Watchman: 2025.03.10.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.16.2 - /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 24.1, iOS 18.1, macOS 15.1, tvOS 18.1, visionOS 2.1, watchOS 11.1
IDEs:
Android Studio: 2024.3 AI-243.22562.218.2431.13114758
Xcode: 16.1/16B40 - /usr/bin/xcodebuild
npmPackages:
expo: ~53.0.9 => 53.0.9
expo-router: ~5.0.6 => 5.0.6
react: 19.0.0 => 19.0.0
react-dom: 19.0.0 => 19.0.0
react-native: 0.79.2 => 0.79.2
react-native-web: ~0.20.0 => 0.20.0
npmGlobalPackages:
eas-cli: 16.4.0
Expo Workflow: managed
Expo Doctor Diagnostics
15/15 checks passed. No issues detected!