2026-05-29

Traeger Left the Keys to trgr.link in the Android App

androidsecretsbitlysupply-chaindisclosure

I have a Traeger grill and use the app like everyone else. At some point I got curious about what the Android build was doing under the hood. I decompiled the APK, grepped for API keys and bearer tokens, and found a production Bitly credential sitting in plain text. I did not call Traeger's Bitly account or poke at anyone else's links. Everything below comes from the app binary and from what that kind of token is allowed to do on Bitly's side.

I disclosed this to Traeger on May 3, 2026. I am publishing this now without waiting around. Traeger says the hardcoded token has been removed from the app and the Bitly key has been rotated. I have not pulled a new build to verify that myself. This writeup is a record of what was in version 3.16.0 and why it mattered.

How I even started looking

Same workflow as other Android stuff I look at. Pull the APK, open it in JADX, search for strings like Bearer, api-ssl.bitly.com, and common header names. No MITM, no proxy on my phone, no hitting Bitly with the extracted token.

Traeger uses Bitly for the branded short domain trgr.link. Recipe sharing and URL expansion in the app went through Bitly's v4 API. The client built OkHttp requests with an Authorization header and a hardcoded token value.

What was in the APK (v3.16.0)

The token showed up in two utility classes that handle shortening and expanding URLs (com.traegergrills.app.util.t and com.traegergrills.app.util.l). Same 40-character bearer string in both places. No obfuscation, no runtime fetch from a secrets backend. There is even a Timber log line in the production build that prints the first part of the token, so you could spot it in logcat without decompiling.

Shorten URL (decompiled)

Request requestBuild = new Request.Builder()
    .url("https://api-ssl.bitly.com/v4/bitlinks")
    .post(...)
    .addHeader("Authorization",
               "Bearer cf9d7b41...[REDACTED]")
    .addHeader("Content-Type", "application/json")
    .build();

// Timber log line left in the release build
aVar2.a("Using token: "
       + Dd.o.U0(10, "cf9d7b41...[REDACTED]")
       + "...", new Object[0]);

Anyone who downloaded that APK from the Play Store or a mirror could extract the same string in under a minute. Bitly personal access tokens do not expire by default, so any APK copy from that era would keep working until Traeger revoked the key in the Bitly dashboard.

What a token like this can do (I did not run these)

I am not going to reproduce calls against Traeger's Bitly account here. That is their infrastructure, not mine. But this is not a read-only app key for shortening one URL at a time. Bitly personal access tokens for a group typically grant full account access. Someone with the embedded credential could, in principle:

  • List every short link under Traeger's Bitly group, including destinations and metadata.
  • Read click analytics for those links (useful if you wanted to know which product setup guides get scanned the most).
  • Create new trgr.linkURLs that look official because they are on Traeger's branded domain.
  • Change where an existing short link points with a single PATCH request. The printed QR code on the box does not change. Only the redirect on Bitly's servers changes.
  • Archive or disable links, which breaks whatever still points at them.

The app only needs shorten-and-expand for recipe shares and deep links. The token in the APK is scoped like an admin key for the whole account.

Why that matters for grill buyers

Traeger prints QR codes on assembly guides and quick-start cards for lines like Timberline, Ironwood, Woodridge, and Flatrock. Those codes resolve to trgr.link URLs that bounce you to setup content on traeger.com. If an attacker had write access to the Bitly account, they could redirect any of those short links to a phishing page. The victim still scanned a code on official Traeger paperwork and still lands on a Traeger-branded domain first. The QR sticker on the grill does not update when someone changes the redirect server-side.

Separately, when you share a recipe from the app it asks Bitly to mint a new trgr.link URL and you text that to a friend. With account-wide write access, freshly created share links could be retargeted before the recipient taps them. The link looks like it came from the real Traeger app because it did.

Link inventories on marketing accounts also tend to accumulate junk from internal testing. If engineers ever stuck API keys or feature-flag query params into destination URLs, anyone who could list links would get those secrets for free. I am not claiming I pulled Traeger's inventory. It is a predictable second-order problem when the list-everything key ships in the consumer app.

What an attacker could do

  1. Install or download com.traegergrills.app and decompile it.
  2. Copy the Bitly bearer token from the utility classes.
  3. Use Bitly's API to enumerate, create, or rewrite links on trgr.link.
  4. Redirect physical-product QR targets or recent recipe-share URLs to a malicious page.
  5. Keep doing it until Traeger revokes the token and ships an app without it.

Disclosure timeline

2026-05-03: Found the token during static analysis of APK v3.16.0. Sent a full report to Traeger's security contact.

Why I am posting this now

The credential should never have been in a consumer app. I am putting this out so there is a public record of what v3.16.0 contained and what that class of Bitly token can do. Traeger says they removed the token and rotated the key. I have not decompiled a current Play Store build to confirm that.

If you own a Traeger, you did nothing wrong. Update the app if you are on an old install. For anyone building something similar: do not put Bitly admin tokens in mobile apps. Proxy shortening through your backend and scope any replacement key to the minimum it needs.

Status: Disclosed to Traeger 2026-05-03. Vendor reports token removed and key rotated. Not independently verified.