Back to Feed
ToolsMar 28, 2026

I Decompiled the White House's New App

White House Android app contains cookie/paywall bypass injector, GPS tracking every 4.5 minutes, and external

Summary

Security researcher decompiled the official White House Android app and discovered multiple concerning features: a JavaScript injector that strips GDPR/cookie consent dialogs and paywalls from third-party websites, location tracking infrastructure capable of capturing GPS coordinates every 4.5 minutes via OneSignal, and hardcoded loading of JavaScript from an external GitHub Pages domain. While location tracking requires explicit permission grant and JS-layer activation, the full infrastructure is compiled into the APK and ready to be enabled.

Full text

The White House released an app on the App Store and Google Play. They posted a blog about it. "Unparalleled access to the Trump Administration."It took a few minutes to pull the APKs with ADB, and threw them into JADX.Here is everything I found.What Is This App?It's a React Native app built with Expo (SDK 54), running on the Hermes JavaScript engine. The backend is WordPress with a custom REST API. The app was built by an entity called "forty-five-press" according to the Expo config.The actual app logic is compiled into a 5.5 MB Hermes bytecode bundle. The native Java side is just a thin wrapper.javaCopyVersion 47.0.1. Build 20. Hermes enabled. New Architecture enabled. Nothing weird here. Let's keep going.Expo ConfigjsonCopyTwo things stand out here. First, there's a plugin called withNoLocation. Second, there's a plugin called withStripPermissions. Remember these. They become relevant very soon.OTA updates are disabled. The Expo update infrastructure is compiled in but dormant.What the App Actually DoesI extracted every string from the Hermes bytecode bundle and filtered for URLs and API endpoints. The app's content comes from a WordPress REST API at whitehouse.gov with a custom whitehouse/v1 namespace.Here are the endpoints:EndpointWhat It Serves/wp-json/whitehouse/v1/homeHome screen/wp-json/whitehouse/v1/news/articlesNews articles/wp-json/whitehouse/v1/wire"The Wire" news feed/wp-json/whitehouse/v1/liveLive streams/wp-json/whitehouse/v1/galleriesPhoto galleries/wp-json/whitehouse/v1/issuesPolicy issues/wp-json/whitehouse/v1/prioritiesPriorities/wp-json/whitehouse/v1/achievementsAchievements/wp-json/whitehouse/v1/affordabilityDrug pricing/wp-json/whitehouse/v1/media-bias"Media Bias" section/wp-json/whitehouse/v1/social/xX/Twitter feed proxyOther hardcoded strings from the bundle: "THE TRUMP EFFECT", "Greatest President Ever!" (lol), "Text President Trump", "Send a text message to President Trump at 45470", "Visit TrumpRx.gov", "Visit TrumpAccounts.gov".There's also a direct link to https://www.ice.gov/webform/ice-tip-form. The ICE tip reporting form. In a news app.It's a content portal. News, live streams, galleries, policy pages, social media embeds, and promotional material for administration initiatives. All powered by WordPress.Now let's look at what else it does.Consent/Paywall Bypass InjectorThe app has a WebView for opening external links. Every time a page loads in this WebView, the app injects a JavaScript snippet. I found it in the Hermes bytecode string table:javascriptCopyRead that carefully. It hides:Cookie bannersGDPR consent dialogsOneTrust popupsPrivacy bannersLogin wallsSignup wallsUpsell promptsPaywall elementsCMP (Consent Management Platform) boxesIt forces body { overflow: auto !important } to re-enable scrolling on pages where consent dialogs lock the scroll. Then it sets up a MutationObserver to continuously nuke any consent elements that get dynamically added.An official United States government app is injecting CSS and JavaScript into third-party websites to strip away their cookie consent dialogs, GDPR banners, login gates, and paywalls.The native side confirms this is the injectedJavaScript prop on the React Native WebView:javaCopyjavaCopyEvery page load in the in-app browser triggers this. It wraps the injection in an IIFE and runs it via Android's evaluateJavascript().Location Tracking InfrastructureRemember withNoLocation from the Expo config? The plugin that's supposed to strip location? Yeah. The OneSignal SDK's native location tracking code is fully compiled into the APK.javaCopy270,000 milliseconds is 4.5 minutes. 570,000 is 9.5 minutes.To be clear about what activates this: the tracking doesn't start silently. There are three gates. The LocationManager checks all of them before the fused location API ever fires.javaCopyFirst, the _isShared flag. It's read from SharedPreferences on init and defaults to false. The JavaScript layer can flip it on with setLocationShared(true). The Hermes string table confirms both setLocationShared and isLocationShared are referenced in the app's JS bundle, so the app has the ability to toggle this.Second, the user has to grant the Android runtime location permission. The location permissions aren't declared in the AndroidManifest but requested at runtime. The Google Play Store listing confirms the app asks for "access precise location only in the foreground" and "access approximate location only in the foreground."Third, the start() method only proceeds if the device actually has a location provider (GMS or HMS).If all three gates pass, here's what runs. The fused location API requests GPS at the intervals defined above:javaCopyThis gets called on both onFocus() and onUnfocused(), dynamically switching between the 4.5-minute foreground interval and the 9.5-minute background interval.When a location update comes in, it feeds into the LocationCapturer:javaCopyLatitude, longitude, accuracy, timestamp, whether the app was in the foreground or background, and whether it was fine (GPS) or coarse (network). All of it gets written into OneSignal's PropertiesModel, which syncs to their backend.The data goes here:javaCopyThere's also a background service that keeps capturing location even when the app isn't active:javaCopySo the tracking isn't unconditionally active. But the entire pipeline including permission strings, interval constants, fused location requests, capture logic, background scheduling, and the sync to OneSignal's API, all of them are fully compiled in and one setLocationShared(true) call away from activating. The withNoLocation Expo plugin clearly did not strip any of this. Whether the JS layer currently calls setLocationShared(true) is something I can't determine from the native side alone, since the Hermes bytecode is compiled and the actual call site is buried in the 5.5 MB bundle. What I can say is that the infrastructure is there, ready to go, and the JS API to enable it is referenced in the bundle.OneSignal User ProfilingOneSignal is doing a lot more than push notifications in this app. From the Hermes string table:addTag - tag users for segmentationaddSms - associate phone numbers with user profilesaddAliases - cross-device user identificationaddOutcomeWithValue / addUniqueOutcome - track user actions and conversionsOneSignal-notificationClicked - notification tap trackingOneSignal-inAppMessageClicked / WillDisplay / DidDisplay / WillDismiss / DidDismiss - full in-app message lifecycle trackingOneSignal-permissionChanged / subscriptionChanged / userStateChanged - state change trackingsetLocationShared / isLocationShared - location togglesetPrivacyConsentRequired / setPrivacyConsentGiven - consent gatingThe local database tracks every notification received and whether it was opened or dismissed:javaCopyYour location, your notification interactions, your in-app message clicks, your phone number if you provide it, your tags, your state changes. All going to OneSignal's servers.Supply Chain: Loading JS From Some Guy's GitHub PagesThe app embeds YouTube videos using the react-native-youtube-iframe library. This library loads its player HTML from: CopyThat's a personal GitHub Pages site. If the lonelycpp GitHub account gets compromised, whoever controls it can serve arbitrary HTML and JavaScript to every user of this app, executing inside the WebView context.This is a government app loading code from a random person's GitHub Pages.Supply Chain: Elfsight Widget PlatformThe app loads third-party JavaScript from Elfsight to embed social media feeds: CopyElfsight is a commercial SaaS widget company. Their JavaScript runs inside the app's WebView with no sandboxing. Whatever tracking Elfsight does, it does it here too. Their code can change at any time. The Elfsight widget ID 4a00611b-befa-466e-bab2-6e824a0a98a9 is hardcoded in an HTML embed.Supply Chain: Everything ElseMailchimp at whitehouse.us10.list-manage.com/subscribe/post-json handles email signups. User emails go to Mail

Indicators of Compromise

  • domain — whitehouse.gov
  • domain — ice.gov
  • url — https://www.ice.gov/webform/ice-tip-form