Is UnDistracted - Hide Facebook, YouTube Feeds safe?

Medium risk

UnDistracted is medium risk. When an email is already saved, opening UnDistracted GETs a subscription lookup from undistracted-server.up.railway.app with the email in the query string. Response email, paid status, and cancellation link get written back to storage.

UnDistraced.Developerv3.6.38Chrome Web Store
45Risk
Who publishes it

UnDistraced.Developer - no other listings under this identity

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
UnDistraced.Developer

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Email subscription lookup sent to remote server

When an email is already saved, opening UnDistracted GETs a subscription lookup from undistracted-server.up.railway.app with the email in the query string.

Response email, paid status, and cancellation link get written back to storage.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You open the UnDistracted popup after an email address has been saved.

The same lookup is also called when you submit the subscription-restore form.

The extension did this

The extension sends that email address to its subscription server.

The server response is used to refresh subscription status and the cancellation link in local storage.

Fields used by the subscription lookup
  • Saved email address
    subscriber@example.com (illustrative)

    This identifies the account whose subscription status is being checked.

  • Paid status
    true

    This records whether the account is treated as having an active paid subscription.

  • Cancellation link
    https://billing.stripe.com/p/session/test_51Nk7hQ2eZvKYlo2C (illustrative)

    This can point to an account-management page tied to the subscription record.

Captured request
GEThttps://undistracted-server.up.railway.app/getSubscription?email=subscriber@example.com

The source expects JSON containing email, hasPaid, and optionally cancelLink.

The code that does this

Subscription lookup sends the email and stores the response

Readable version

Readable subscription lookup function

assets/index-DaKYjg1g.js:38082-38100
ZI = async (e, t, r, n, o, i) => {  try {    const a = await fetch(`https://undistracted-server.up.railway.app/getSubscription?email=${e.email}`);    if (!a.ok) throw new Error(`HTTP error! status: ${a.status}`);    const s = await a.json();    localStorage.setItem("email", s.email), r(s.email), localStorage.setItem("hasPaid", s.hasPaid), chrome.storage.local.set({      hasPaid: s.hasPaid    }), n(s.hasPaid), s.hasPaid ? (localStorage.setItem("cancelLink", s.cancelLink), o(s.cancelLink), i && i(!0), t && t({      title: `Subscription restored for ${s.email}`,      status: "success",      isClosable: !0    })) : (localStorage.removeItem("cancelLink"), t && t({      title: `Subscription not found for ${s.email}`,      status: "error",      isClosable: !0    }))  } catch (a) {    console.error("Error fetching subscription:", a)  }}

Readable popup-load trigger

assets/index-DaKYjg1g.js:42483-42506
b.useEffect(() => {  chrome.storage && (chrome.storage.sync.get(["facebookSettings", "youtubeSettings", "twitterSettings", "redditSettings", "netflixSettings", "linkedinSettings", "instagramSettings", "pinterestSettings", "generalSettings"], ({    facebookSettings: X = {},    youtubeSettings: Ce = {},    twitterSettings: Me = {},    redditSettings: Ve = {},    netflixSettings: pe = {},    linkedinSettings: Pe = {},    instagramSettings: ke = {},    pinterestSettings: ot = {},    generalSettings: se = {}  }) => {    n(X), i(Ce), s(Me), u(Ve), f(pe), h(Pe), m(ke), g(ot), y(se)  }), chrome.storage.onChanged.addListener((X, Ce) => {    const [Me, Ve] = Object.entries(X)[0], pe = Ve.newValue, Pe = Ve.oldValue;    Me === "generalSettings" && pe.disableFiltersTemporary.value.active !== Pe.disableFiltersTemporary.value.active ? y(pe) : Me === "generalSettings" && pe.blockDomainCategories.value && !Pe.blockDomainCategories.value && chrome.runtime.sendMessage({      action: "loadDomainsToIndexedDB"    })  })), he(), W(parseInt(localStorage.getItem("activeTab"))), k(localStorage.getItem("email")), _(localStorage.getItem("hasPaid") === "true"), V(localStorage.getItem("cancelLink")), (localStorage.getItem("email") || S) && ZI({    email: localStorage.getItem("email")  }, null, k, _, V), chrome.runtime.onMessage.addListener((X, Ce, Me) => {    X.action === "updateLoadingStatus" && (console.log(X.status, X.progress), q(X.status === "processing"), ne(X.progress))  })}, [])

Readable form-submit trigger

assets/index-DaKYjg1g.js:38138-38140
onSubmit: a(c => {  ZI(c, o, n.setEmail, n.setHasPaid, n.setCancelLink, n.setIsExploding)})
Remote destination contacted by the lookup
    • undistracted-server.up.railway.app

    Receives the saved email address as a subscription lookup key and returns account-status fields. The hostname is hosted under Railway's app domain.

Updated 30 September 2026pjjgklgkfeoeiebjogplpnibpfnffkng