Security Alert: Confirmed Malware
MyGate Network Node
ID: hajiimgolngmlbglaoheacnejbnnmoco
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- Mygate networkView Profile
- Privacy
- Privacy Policy
- MX records exist
- No
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- Yes
- Mailbox exists
- No
This app allows users to share their network bandwidth with others and earn points as rewards.
This app allows users to share their network bandwidth with others and earn points as rewards. By connecting to the app, users contribute their unused internet resources to a decentralized network. In return, they receive points that can later be swapped for tokens or other benefits within the platform.
The content script immediately reads the entire Redux Persist store (`persist:root`) from localStorage on the MyGate web app and transmits the complete serialized application state to the background service worker. The `persist:root` key is the standard Redux Persist storage key and typically contains all Redux slices including authentication state, user profile data, and session information. Exfiltrating the entire app state rather than requesting only what is needed violates the principle of least privilege and exposes more user data than necessary.
(() => { const e = localStorage.getItem("persist:root"); e ? chrome.runtime.sendMessage({ type: "FROM_CONTENT", data: e }) : chrome.runtime.sendMessage({ type: "FROM_REMOVE_TOKEN" })})();The background script receives the full serialized Redux state dumped from localStorage, parses it, extracts the authentication bearer token from the `auth` slice, and persists it to `chrome.storage.local`. This token is then silently reused across all extension API calls and WebSocket connections — the user is never explicitly asked to grant the extension access to their session credentials. Storing a live auth token in chrome.storage makes it accessible to the extension indefinitely without re-authentication.
chrome.runtime.onMessage.addListener((n, e, t) => { var s; if (n.type === "FROM_CONTENT") { const i = JSON.parse(n.data), r = (s = JSON.parse(i == null ? void 0 : i.auth)) == null ? void 0 : s.token; r && chrome.storage.local.set({ token: r }) } n.type === "FROM_REMOVE_TOKEN" && chrome.storage.local.remove("token")});Immediately on install/startup the background service worker establishes a persistent Socket.IO connection to `api.mygate.network` authenticated with the harvested bearer token, registering the browser as a `nodeId`-identified network proxy node. A `setInterval` forces a token refresh and reconnection every 10 minutes, keeping the connection alive continuously without explicit per-session user consent. The server can push arbitrary `message` events to this node, and the extension description confirms traffic is relayed through the user's network connection — turning the user's browser into a bandwidth-sharing proxy relay.
let b = null;const fe = async () => { try { const n = await j(), e = await pe("device_id"); if (!n) { console.error("Token not found"); return } b && (console.log("Disconnecting existing socket..."), b.disconnect()), b = C("https://api.mygate.network", { auth: { token: `Bearer ${n}` }, query: { nodeId: e }, reconnection: !0, transports: ["websocket", "polling"] }), b.on("connect", () => { console.log("Socket.IO connected") }), b.on("message", t => { console.log("Message from server:", t) }), b.on("disconnect", () => { console.warn("Socket.IO disconnected") }), b.on("connect_error", t => { console.error("Connection error:", t) }) } catch (n) { console.error("Failed to connect WebSocket:", n) }};fe();const le = async () => { try { await j() ? (console.log("Connecting WebSocket..."), fe()) : console.error("No token found") } catch (n) { console.error("Failed to refresh token:", n) }};le();setInterval(() => { console.log("Refreshing token and reconnecting WebSocket..."), le()}, 10 * 60 * 1e3);The popup UI's Axios instance silently reads the token from `chrome.storage.local` on every request and injects it as a Bearer authorization header to `https://api.mygate.network/api/front`. On a 401 response it removes `accessToken` from localStorage and redirects to `/admin`, which is unusual behavior for an extension popup and could interfere with the user's authenticated session on the host site. The combination with the token-harvesting content script means the extension can autonomously make credentialed API calls on behalf of the user without further interaction.
Ui.interceptors.request.use(async function(e) { const { headers: t } = e; try { const n = await Pc(); n && t && (t.Authorization = `Bearer ${n}`) } catch (n) { console.error("Error fetching token from Chrome storage:", n); return } return e}, async function(e) { return Promise.reject(e)});Ui.interceptors.response.use(function(e) { return e}, function(e) { var t; return ((t = e.response) == null ? void 0 : t.status) === 401 && (localStorage.removeItem("accessToken"), window.location.href = "/admin"), Promise.reject(e)});By severity
Versions scanned
Showing 2 of 18 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 1.0.19 | 5 |
| 1.0.0 | 4 |
Files with findings
3 distinct paths — top paths by unique finding count:
- background.js5
- content.js2
- main.js2
URLs
View the external URLs this extension communicates with to understand its network activity and data interactions.
Gain full insight into all external connections.
Upgrade for full visibility.
Gain full insight into all external connections.
Upgrade for full visibility.
Code Diff
Compare extension code between any two versions.
No comparable text files found between these versions.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.