CodenameOne implicit intent for sensitive communication
Description
A vulnerability was found in CodenameOne 7.0.70. It has been classified as problematic. Affected is an unknown function. The manipulation leads to use of implicit intent for sensitive communication. It is possible to launch the attack remotely. The complexity of an attack is rather high. The exploitability is told to be difficult. Upgrading to version 7.0.71 is able to address this issue. The patch is identified as dad49c9ef26a598619fc48d2697151a02987d478. It is recommended to upgrade the affected component. VDB-220470 is the identifier assigned to this vulnerability.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CodenameOne 7.0.70 uses an implicit PendingIntent, potentially allowing malicious apps to intercept or modify sensitive communication.
Analysis
CodenameOne version 7.0.70 contains a vulnerability where the framework uses an implicit PendingIntent for sensitive communication, such as push notification actions. The root cause is the use of PendingIntent.FLAG_CANCEL_CURRENT without setting FLAG_IMMUTABLE, which can allow other applications to read or modify the intent's data [1][3].
Exploitation requires an attacker to be able to run a malicious application on the same device, as the attack is performed remotely by intercepting or modifying the PendingIntent. The attack complexity is rated as high, and exploitability is considered difficult [2]. The vulnerability is classified as problematic rather than critical.
An attacker who successfully exploits this could potentially intercept sensitive information passed through the implicit intent, or redirect the intent to a malicious component, leading to data disclosure or privilege escalation. However, the specific impact depends on the application's use of the affected function.
The issue has been fixed in version 7.0.71, with the commit dad49c9ef26a598619fc48d2697151a02987d478 introducing FLAG_IMMUTABLE for Android API 23 and above, while falling back to FLAG_CANCEL_CURRENT for older versions [3][4]. Users are recommended to upgrade to the latest version. The vulnerability is tracked as VDB-220470.
- GitHub - codenameone/CodenameOne: Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.
- NVD - CVE-2022-4903
- Fixed #3583 Pending Intent vulnerability · codenameone/CodenameOne@dad49c9
- Implicit pending intent error
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.codenameone:codenameone-coreMaven | < 7.0.71 | 7.0.71 |
Affected products
3- CodenameOne/CodenameOnedescription
- Range: <= 7.0.70
Patches
1dad49c9ef26aFixed #3583 Pending Intent vulnerability
5 files changed · +54 −31
Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java+37 −9 modified@@ -775,7 +775,36 @@ private static PushActionCategory[] getInstalledPushActionCategories(Context con } return out.toArray(new PushActionCategory[out.size()]); } - + + public static PendingIntent createPendingIntent(Context ctx, int value, Intent intent) { + if (android.os.Build.VERSION.SDK_INT >= 23) { + // PendingIntent.FLAG_IMMUTABLE + return PendingIntent.getActivity(ctx, value, newIntent, 67108864); + } else { + return PendingIntent.getActivity(ctx, value, newIntent, PendingIntent.FLAG_CANCEL_CURRENT); + } + } + + public static PendingIntent getPendingIntent(Context ctx, int value, Intent intent) { + if (android.os.Build.VERSION.SDK_INT >= 23) { + // PendingIntent.FLAG_IMMUTABLE + return PendingIntent.getService(ctx, value, newIntent, 67108864); + } else { + return PendingIntent.getService(ctx, value, newIntent, PendingIntent.FLAG_CANCEL_CURRENT); + } + PendingIntent.getService + } + + public static PendingIntent getBroadcastPendingIntent(Context ctx, int value, Intent intent) { + if (android.os.Build.VERSION.SDK_INT >= 23) { + // PendingIntent.FLAG_IMMUTABLE + return PendingIntent.getBroadcast(ctx, value, newIntent, 67108864); + } else { + return PendingIntent.getBroadcast(ctx, value, newIntent, PendingIntent.FLAG_CANCEL_CURRENT); + } + PendingIntent.getService + } + /** * Adds actions to a push notification. This is called by the Push broadcast receiver probably before * Codename One is initialized @@ -811,7 +840,7 @@ public static void addActionsToNotification(PushActionsProvider provider, String for (PushAction action : category.getActions()) { Intent newIntent = (Intent)targetIntent.clone(); newIntent.putExtra("pushActionId", action.getId()); - PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode++, newIntent, PendingIntent.FLAG_CANCEL_CURRENT); + PendingIntent contentIntent = createPendingIntent(context, requestCode++, newIntent); try { int iconId = 0; try { iconId = Integer.parseInt(action.getIcon());} catch (Exception ex){} @@ -7093,7 +7122,7 @@ public Object notifyStatusBar(String tickerText, String contentTitle, Intent notificationIntent = new Intent(); notificationIntent.setComponent(activityComponentName); - PendingIntent contentIntent = PendingIntent.getActivity(getContext(), 0, notificationIntent, 0); + PendingIntent contentIntent = createPendingIntent(getContext(), 0, notificationIntent); NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext()) @@ -10416,20 +10445,19 @@ public void scheduleLocalNotification(LocalNotification notif, long firstTime, i //intent.putExtra("backgroundClass", getBackgroundLocationListener().getName()); //an ugly workaround to the putExtra bug intent.setData(Uri.parse("http://codenameone.com/a?" + getBackgroundFetchListener().getClass().getName())); - PendingIntent pendingIntent = PendingIntent.getService(context, 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = getPendingIntent(context, 0, + intent); notificationIntent.putExtra(LocalNotificationPublisher.BACKGROUND_FETCH_INTENT, pendingIntent); } else { contentIntent.setData(Uri.parse("http://codenameone.com/a?LocalNotificationID="+Uri.encode(notif.getId()))); } - PendingIntent pendingContentIntent = PendingIntent.getActivity(getContext(), 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingContentIntent = createPendingIntent(getContext(), 0, contentIntent); notificationIntent.putExtra(LocalNotificationPublisher.NOTIFICATION_INTENT, pendingContentIntent); - PendingIntent pendingIntent = PendingIntent.getBroadcast(getContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = getBroadcastPendingIntent(getContext(), 0, notificationIntent); AlarmManager alarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); if (BACKGROUND_FETCH_NOTIFICATION_ID.equals(notif.getId())) { @@ -10462,7 +10490,7 @@ public void cancelLocalNotification(String notificationId) { Intent notificationIntent = new Intent(getContext(), LocalNotificationPublisher.class); notificationIntent.setAction(getContext().getApplicationInfo().packageName + "." + notificationId); - PendingIntent pendingIntent = PendingIntent.getBroadcast(getContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = getBroadcastPendingIntent(getContext(), 0, notificationIntent); AlarmManager alarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent); }
Ports/Android/src/com/codename1/impl/android/CodenameOneActivity.java+2 −2 modified@@ -428,15 +428,15 @@ public boolean isBackground() { public void registerForPush(String key) { Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER"); registrationIntent.setPackage("com.google.android.gms"); - registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate + registrationIntent.putExtra("app", AndroidImplementation.getBroadcastPendingIntent(this, 0, new Intent())); // boilerplate registrationIntent.putExtra("sender", key); startService(registrationIntent); } public void stopReceivingPush() { Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER"); unregIntent.setPackage("com.google.android.gms"); - unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); + unregIntent.putExtra("app", AndroidImplementation.getBroadcastPendingIntent(this, 0, new Intent())); startService(unregIntent); }
Ports/Android/src/com/codename1/impl/android/PushNotificationService.java+3 −2 modified@@ -103,7 +103,8 @@ public void onDestroy() { public abstract PushCallback getPushCallbackInstance(); public abstract Class getStubClass(); - + + @Override public void push(final String value) { final PushCallback callback = getPushCallbackInstance(); @@ -116,7 +117,7 @@ public void run() { } else { NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); Intent newIntent = new Intent(this, getStubClass()); - PendingIntent contentIntent = PendingIntent.getActivity(this, 0, newIntent, PendingIntent.FLAG_CANCEL_CURRENT); + PendingIntent contentIntent = AndroidImplementation.createPendingIntent(this, 0, newIntent);
Ports/Android/src/com/codename1/location/AndroidLocationPlayServiceManager.java+10 −14 modified@@ -189,9 +189,8 @@ public void run() { if (bgListenerClass != null) { intent.setData(Uri.parse("http://codenameone.com/a?" + bgListenerClass.getName())); } - PendingIntent pendingIntent = PendingIntent.getService(context, 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = AndroidImplementation.getPendingIntent(context, 0, + intent); inMemoryBackgroundLocationListener = AndroidLocationPlayServiceManager.this; @@ -228,16 +227,15 @@ private PendingIntent createBackgroundPendingIntent(boolean forceService) { Intent intent = new Intent(context, BackgroundLocationBroadcastReceiver.class); intent.setData(Uri.parse("http://codenameone.com/a?" + bgListenerClass.getName())); intent.setAction(BackgroundLocationBroadcastReceiver.ACTION_PROCESS_UPDATES); - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = AndroidImplementation.getBroadcastPendingIntent(context, 0, intent); return pendingIntent; } else { Intent intent = new Intent(context, BackgroundLocationHandler.class); intent.setData(Uri.parse("http://codenameone.com/a?" + bgListenerClass.getName())); - PendingIntent pendingIntent = PendingIntent.getService(context, 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = AndroidImplementation.getPendingIntent(context, 0, + intent); return pendingIntent; } } @@ -290,9 +288,8 @@ public void run() { if (bgListenerClass != null) { intent.putExtra("backgroundClass", bgListenerClass.getName()); } - PendingIntent pendingIntent = PendingIntent.getService(context, 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = AndroidImplementation.getPendingIntent(context, 0, + intent); //LocationServices.FusedLocationApi.removeLocationUpdates(getmGoogleApiClient(), pendingIntent); removeLocationUpdates(context, pendingIntent); @@ -481,16 +478,15 @@ private PendingIntent createGeofencePendingIntent(Class geofenceListenerClass, c intent.setAction(BackgroundLocationBroadcastReceiver.ACTION_PROCESS_GEOFENCE_TRANSITIONS); intent.setData(Uri.parse("http://codenameone.com/a?" + geofenceListenerClass.getName())); //intent.setAction(BackgroundLocationBroadcastReceiver.ACTION_PROCESS_GEOFENCE_TRANSITIONS); - geofencePendingIntent = PendingIntent.getBroadcast(AndroidNativeUtil.getContext().getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + geofencePendingIntent = AndroidImplementation.getBroadcastPendingIntent(AndroidNativeUtil.getContext().getApplicationContext(), 0, intent); return geofencePendingIntent; } else { Intent intent = new Intent(context, GeofenceHandler.class); intent.putExtra("geofenceClass", geofenceListenerClass.getName()); intent.putExtra("geofenceID", gf.getId()); - PendingIntent pendingIntent = PendingIntent.getService(context, 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = AndroidImplementation.getPendingIntent(context, 0, + intent); return pendingIntent;
Ports/Android/src/com/codename1/media/BackgroundAudioService.java+2 −4 modified@@ -53,6 +53,7 @@ import android.text.TextUtils; +import com.codename1.impl.android.AndroidImplementation; import com.codename1.ui.Display; @@ -267,9 +268,6 @@ void showPausedNotification() { } - - - private void initMediaSession() { ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class); mMediaSessionCompat = new MediaSessionCompat(getApplicationContext(), "Tag", mediaButtonReceiver, null); @@ -279,7 +277,7 @@ private void initMediaSession() { Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setClass(this, MediaButtonReceiver.class); - PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0); + PendingIntent pendingIntent = AndroidImplementation.getBroadcastPendingIntent(this, 0, mediaButtonIntent); mMediaSessionCompat.setMediaButtonReceiver(pendingIntent); setSessionToken(mMediaSessionCompat.getSessionToken());
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/codenameone/CodenameOne/commit/dad49c9ef26a598619fc48d2697151a02987d478ghsapatchWEB
- github.com/codenameone/CodenameOne/releases/tag/7.0.71ghsapatchWEB
- github.com/advisories/GHSA-p6xq-9h8r-v544ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-4903ghsaADVISORY
- github.com/codenameone/CodenameOne/issues/3583ghsaissue-trackingWEB
- vuldb.comghsasignaturepermissions-requiredWEB
- vuldb.comghsavdb-entrytechnical-descriptionWEB
News mentions
0No linked articles in our index yet.