Is Telegram Video Downloader - TG Downloader safe?
Telegram Video Downloader is medium risk. On the free tier, Telegram Video Downloader fetches a remote config from gmplus.io on session start. freeUseCount sets your free-download limit; activeRateExtensions/setDiscountExtensions toggle promo UI, server-side and changeable anytime.
Who publishes itadtargetinghello - 3 other listings from the same operator, 1 of them carrying a finding
adtargetinghello - 3 other listings from the same operator, 1 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
3 other listings published from this account, 17k+ users between them. 1 of them carries a finding.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Free-tier download limits and promos controlled by a remote config server
On the free tier, Telegram Video Downloader fetches a remote config from gmplus.io on session start. freeUseCount sets your free-download limit; activeRateExtensions/setDiscountExtensions toggle promo UI, server-side and changeable anytime.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Dynamic sandbox
You use the extension while on the free plan.
The fetch only happens for free-tier sessions; paid plans skip it.
The extension asks gmplus.io how many free downloads to allow you and whether to show promotional pricing.
The server's answer directly overwrites the extension's local free-use counter and discount flags.
JSON body containing a config array; the entry with id "244" carries params.freeUseCount, params.activeRateExtensions, and params.setDiscountExtensions, each keyed by the extension's internal identifier.
- Content-Type
- application/x-www-form-urlencoded
extension_id=35&language=enRemote config fetch and free-tier limit override
async function fetchRemoteConfig(lang) { if (cachedLang === lang) return cachedResult || pendingRequest || {}; cachedLang = lang; pendingRequest = null; return (cachedResult = (async () => { const body = new URLSearchParams(); body.append("extension_id", "35"); body.append("language", lang); const res = await fetch("https://gmplus.io/user/api-chrome-extension/get-remote-config", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body }); return await res.json(); })().then(json => cachedResult = json || {}));}async function applyFreeTierConfig(state = {}, lang) { if (state[LAST_FETCH_KEY] === lang) return state; const next = { ...state, [LAST_FETCH_KEY]: lang }; const config = await fetchRemoteConfig(lang); const entry = (config?.data?.config || []).find(e => String(e?.id) === "244")?.params; if (!entry) return next; if (entry.freeUseCount !== undefined) next.freeUseCount = toNumber(entry.freeUseCount, next.freeUseCount ?? 3); next.hasActiveRate = Boolean(entry.activeRateExtensions?.[EXTENSION_KEY]); next.hasDiscountCode = Boolean(entry.setDiscountExtensions?.[EXTENSION_KEY]); return next;}- Free download countfreeUseCount: 3
How many downloads you're allowed to make before being asked to upgrade, set by the server, not the extension's shipped code.
- Active rate flagactiveRateExtensions.main_ioiepomamdncfjkigofklhciigbonnlk: true
Whether promotional pricing UI is shown to you, decided per extension ID by the server.
- Discount code flagsetDiscountExtensions.main_ioiepomamdncfjkigofklhciigbonnlk: false
Whether a discount code prompt is shown to you, also server-controlled.
- gmplus.io
Returns the config entry that sets this extension's free-use limits and promotional UI flags on every free-tier session.