Is Media Harvest : X (twitter) Media Downloader safe?
We analyzed Media Harvest : X (twitter) Media Downloader version 4.5.7's actual code and gave it a 78/100 trust score. This is a mostly purpose-aligned…
Bottom line
This is a mostly purpose-aligned downloader with medium privacy exposure and no established abuse.
What it can access
It can read X pages and selected personalized feeds, use X cookies for X requests, cache media, and send usage telemetry; this fits downloading but is broader than necessary. [Q1][Q2][Q3][Q6]
Security weaknesses
It automatically inspects selected X responses and stores personalized data locally, creating privacy exposure, though its messages and destinations are restricted. [Q2][Q3][Q8][Q21]
Signs of misuse
No evidence shows misuse: telemetry is aggregate, captured X data was not sent to the service, and cookies are used for X requests rather than elsewhere. [Q6][Q7][Q14]
Code findings
What access does this extension ask for, and does that access make sense for what it claims to do?
It has X/Twitter host access plus cookies, downloads, storage, notifications and unlimited local storage; access is scoped to X/Twitter domains.
Declares X/Twitter hosts and the cookies, downloads, storage, notifications, unlimitedStorage and alarms permissions. — manifest.json:1-92
Which websites can it run on, and can it read or change what appears on those pages?
It reads X page structure and selected X services response bodies to identify posts and downloadable media.
Hooks XMLHttpRequest.open in the main world and emits successful response bodies for named X timeline/tweet endpoints. — inject.js:1
Observes X post DOM nodes, adds download controls and forwards captured media responses to the background worker. — main.js:1
Can it see sensitive information you type, such as passwords, payment details, messages, or form entries?
Captured responses can include private or personalized timelines, bookmarks and likes, but the traced sink is a local tweet/media cache rather than a remote upload.
The accepted endpoint list includes HomeTimeline, Bookmarks, Likes, SearchTimeline and notifications. — main.js:1
The CaptureResponse route parses the body by response type and saves resulting tweet records through tweetResponseCache. — sw.js:1
Can it access private browser data such as cookies, signed-in sessions, browsing history, bookmarks, or downloads?
It keeps tweet/media cache, download history, settings, client identity and aggregate usage in extension storage/IndexedDB; it does not request Chrome history.
Defines local repositories for tweet cache, IndexedDB download history, settings, client registration and usage totals. — sw.js:1
Requests storage/unlimitedStorage but not history or browsingData. — manifest.json:1-92
Can it access anything else on your device, such as files, location, camera, microphone, clipboard, or installed applications?
It downloads selected media and can optionally dispatch a selected URL/filename to a separately installed Aria2 downloader extension.
The browser downloader calls chrome.downloads.download; the optional Aria2 path messages extension mpkodccbngfoacfalldjimigbofkhgjn with URL, filename and X referrer. — sw.js:1
The settings page exposes a user-controlled Aria2 integration switch. — pages.js:281
Does it send information outside your browser? If so, what information is sent, where does it go, and why?
It sends aggregate usage and client registration data to MediaHarvest and error telemetry to Sentry; captured X response bodies were not traced to those sinks.
Registers /v1/clients with initial downloadCount/trafficUsage and periodically PUTs aggregate stats to /v1/clients/{id}/stats. — sw.js:1
Initializes Sentry with a fixed ingest endpoint and clientId user context. — sw.js:1
Captured X bodies flow through the CaptureResponse router into tweetResponseCache. — sw.js:1
Does it download or run code, settings, or instructions supplied by a remote server?
No evidence of this behavior was found in the reviewed package.
Remote API commands register/sync client statistics; feature and download settings are read from local storage. — sw.js:1
Can it take actions without a clear user request, such as opening pages, redirecting searches, downloading files, or sending requests?
It automatically intercepts selected X responses, maintains a local cache and periodically evicts data; downloading requires a click or configured shortcut.
The main-world XHR hook runs from document_start on X pages. — inject.js:1
Creates a daily tweet-cache eviction alarm. — sw.js:1
Download actions originate from added buttons or the configured shortcut. — main.js:1
Can it change important browser settings, including your proxy, search engine, homepage, privacy settings, or other extensions?
No evidence of this behavior was found in the reviewed package.
Requests no proxy, browserSettings, privacy or search permission. — manifest.json:1-92
Is any important behavior difficult to inspect because the code is hidden, heavily obfuscated, dynamically generated, or supplied by third parties?
No evidence of this behavior was found in the reviewed package.
Webpack-style minified bundle with readable domain constants and event names. — sw.js:1
Minified content bundle exposes its endpoint allowlist and message schemas. — main.js:1
Does it use eval(), new Function(), or string-based timers to turn text into executable code?
No evidence of this behavior was found in the reviewed package.
Extension pages restrict scripts to self. — manifest.json:1-92
Targeted search of shipped scripts found no eval or new Function use. — sw.js:1
Does it track the websites, pages, searches, or links you visit?
No evidence of this behavior was found in the reviewed package.
Content scripts and host permissions are limited to X/Twitter domains. — manifest.json:1-92
The captured-response endpoint list includes timelines, lists, bookmarks, likes and searches. — main.js:1
Does it create a persistent ID or browser fingerprint to recognize you?
It creates a pseudonymous client UUID, syncs aggregate download/traffic statistics and associates Sentry telemetry with that client ID.
MediaHarvest client registration returns/stores a clientUUID and sync token; stats include only downloadCount and trafficUsage. — sw.js:1
Sentry is initialized with a fixed DSN, 0.3 trace sample rate and clientId user context. — sw.js:1
Does it send cookies, session details, authentication data, or page contents elsewhere?
It reads X's ct0 CSRF and gt guest-token cookies and uses them for requests back to X; no unrelated cookies or third-party credential destination was found.
Cookie repository calls chrome.cookies.get for https://x.com names ct0 and gt. — sw.js:1
Tweet solution code uses X transaction/CSRF/guest tokens to call X tweet endpoints. — sw.js:1
Does it record typing, form entries, clipboard contents, or screenshots?
No evidence of this behavior was found in the reviewed package.
Fe.handleKeyDown/handleKeyUp compares event.code to the download shortcut and excludes editable targets. — main.js:1
No desktopCapture or tabCapture permission is present. — manifest.json:1-92
Can a website or remote server send commands that make the extension take actions?
No evidence of this behavior was found in the reviewed package.
DownloadMedia, CheckDownloadHistory and CaptureResponse messages are validated against fixed schemas. — sw.js:1
The X transaction-ID provider is enabled only when sender.tab.url matches https://x.com/. — sw.js:1
Does it alter links, referral codes, advertisements, shopping carts, or search results?
No evidence of this behavior was found in the reviewed package.
DOM observers add harvester controls to X posts and optional autoRevealNsfw clicks X's reveal button. — main.js:1
Does it redirect or modify web traffic, request headers, downloads, or proxy settings?
It intercepts selected X services responses and makes authenticated requests to X for tweet details, but does not redirect or proxy unrelated traffic.
Hooks XHR only when URL paths match fixed tweet/timeline/notification endpoint patterns. — inject.js:1
Fetch solution targets X tweet APIs using X-specific tokens. — sw.js:1
Can it communicate with software on the computer or services running on localhost?
No evidence of this behavior was found in the reviewed package.
No nativeMessaging permission is declared. — manifest.json:1-92
Optional Aria2 dispatch calls chrome.runtime.sendMessage with a fixed extension ID. — sw.js:1
Does it decode, decrypt, or unpack hidden data and then execute or inject it?
No evidence of this behavior was found in the reviewed package.
Background/content scripts are packaged files and extension script-src is self. — manifest.json:1-92
Remote responses are parsed as API data/tokens, not executed as code. — sw.js:1
Can ordinary websites access privileged extension features through messaging or exposed files?
No evidence of this behavior was found in the reviewed package.
Dispatches mh:media-response with matched X response data. — inject.js:1
Converts only accepted response types into a validated CaptureResponse runtime message. — main.js:1
Background validates message schemas and restricts X transaction-ID requests by sender tab URL. — sw.js:1
Does suspicious behavior activate only for certain users, websites, dates, or remote settings?
No evidence of this behavior was found in the reviewed package.
Reads keyboardShortcut and autoRevealNsfw from local settings. — main.js:1
Options UI exposes download and Aria2 settings. — pages.js:281
Does it perform hidden resource-intensive work, such as cryptocurrency mining?
No evidence of this behavior was found in the reviewed package.
Cryptographic code belongs to AWS request signing and token handling; workload centers on API parsing and downloads. — sw.js:1
Does it change form fields or where a form sends its information?
No evidence of this behavior was found in the reviewed package.
Page edits are limited to harvester buttons, state classes and optional reveal-button clicks. — main.js:1