{"record":{"id":"d1f8e58d2270c684","repo":"microg/GmsCore","slug":"suggested-uid","errorCode":null,"errorMessage":"suggested UID [","messagePattern":"suggested UID \\[","errorType":"validation","errorClass":"SecurityException","httpStatus":null,"severity":"error","filePath":"play-services-base/core/src/main/java/org/microg/gms/common/PackageUtils.java","lineNumber":231,"sourceCode":"            throw e;\n        }\n    }\n\n    @Nullable\n    public static String getAndCheckCallingPackage(@NonNull Context context, int suggestedCallerUid) {\n        return getAndCheckCallingPackage(context, null, suggestedCallerUid);\n    }\n\n    @Nullable\n    public static String getAndCheckCallingPackage(@NonNull Context context, @Nullable String suggestedPackageName, int suggestedCallerUid) {\n        return getAndCheckCallingPackage(context, suggestedPackageName, suggestedCallerUid, 0);\n    }\n\n    @Nullable\n    public static String getAndCheckCallingPackage(@NonNull Context context, @Nullable String suggestedPackageName, int suggestedCallerUid, int suggestedCallerPid) {\n        int callingUid = Binder.getCallingUid(), callingPid = Binder.getCallingPid();\n        if (suggestedCallerUid > 0 && suggestedCallerUid != callingUid) {\n            throw new SecurityException(\"suggested UID [\" + suggestedCallerUid + \"] and real calling UID [\" + callingUid + \"] mismatch!\");\n        }\n        if (suggestedCallerPid > 0 && suggestedCallerPid != callingPid) {\n            throw new SecurityException(\"suggested PID [\" + suggestedCallerPid + \"] and real calling PID [\" + callingPid + \"] mismatch!\");\n        }\n        return getAndCheckPackage(context, suggestedPackageName, callingUid, callingPid);\n    }\n\n    @Nullable\n    public static String getAndCheckPackage(Context context, String suggestedPackageName, int callingUid) {\n        return getAndCheckPackage(context, suggestedPackageName, callingUid, 0);\n    }\n\n    @Nullable\n    public static String getAndCheckPackage(@NonNull Context context, @Nullable String suggestedPackageName, int callingUid, int callingPid) {\n        String packageName = packageFromProcessId(context, callingPid);\n        if (packageName == null) {\n            String[] packagesForUid = context.getPackageManager().getPackagesForUid(callingUid);\n            if (packagesForUid != null && packagesForUid.length != 0) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-base/core/src/main/java/org/microg/gms/common/PackageUtils.java#L213-L249","documentation":"getAndCheckCallingPackage verifies that a caller-supplied 'suggested' caller identity matches the real Binder identity. If suggestedCallerUid > 0 and differs from Binder.getCallingUid(), it throws this SecurityException. The library does this to prevent a privileged or IPC-forwarding process from spoofing another app's identity when claiming a package name.","triggerScenarios":"An IPC endpoint (e.g. an AIDL service method receiving a Bundle) passes suggestedCallerUid from untrusted client input that does not equal Binder.getCallingUid(); forwarding a request on behalf of another process while passing that process's UID.","commonSituations":"Hand-written AIDL glue code that copies a UID/PID out of the request extras instead of leaving it 0; proxy/dispatcher apps forwarding calls to microG services; stale code written for non-Binder call paths.","solutions":["Pass suggestedCallerUid = 0 (or use the overload without uid/pid) unless you obtained the value from a trusted source for this exact transaction.","Compare against Binder.getCallingUid() yourself and log the mismatch before calling, to identify the spoofing client.","If you intentionally forward on behalf of another process, do not forward its UID; perform the package check with the real calling UID.","Fix client code to stop sending uid/pid fields in the request bundle."],"exampleFix":"// before\nString pkg = PackageUtils.getAndCheckCallingPackage(context, suggestedPkg, extra.getInt(\"uid\"), extra.getInt(\"pid\"));\n\n// after\nString pkg = PackageUtils.getAndCheckCallingPackage(context, suggestedPkg); // uid/pid taken from Binder","handlingStrategy":"validation","validationCode":"int callingUid = Binder.getCallingUid();\nif (suggestedCallerUid > 0 && suggestedCallerUid != callingUid) {\n    throw new IllegalArgumentException(\"suggestedCallerUid does not match Binder caller\");\n}","typeGuard":"boolean isTrustedSuggestedUid(int suggestedUid) {\n    return suggestedUid <= 0 || suggestedUid == Binder.getCallingUid();\n}","tryCatchPattern":"try {\n    return PackageUtils.getAndCheckCallingPackage(context, suggestedPkg, uid, pid);\n} catch (SecurityException e) {\n    Log.w(TAG, \"Caller identity mismatch (uid)\", e);\n    return null;\n}","preventionTips":["Pass 0 for suggestedCallerUid unless it comes from a trusted in-transaction source.","Never echo uid/pid from client-supplied extras back into the check.","Sample Binder identity at call time, never cache it.","Audit AIDL entry points for forwarded identity fields."],"tags":["android","binder","security","uid-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}