Security Alert: Confirmed Malware
StudyHQ (BETA)
ID: nnpkbpemkbeakdjfadfhfolbdociodln
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- http://gostudyhq.comView Profile
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
Study smart with StudyHQ flashcards - or - create your own sets with this Chrome New Tab Extension.
THIS EXTENSION IS FOR BETA TESTING. The production version can be found here - https://chrome.google.com/webstore/detail/studyhq/benhgbjbdpfalagddfmfefhfllbfllfh Get StudyHQ, customize flashcards and access practice tests, plus update your new tab page search to MyWay.com. Comes with daily content to show you news, weather and more in a new Chrome window! By installing this extension, you agree to the End User License Agreement and Privacy Policy (eula.mindspark.com/eula/) This new tab extension is a product of Ask Applications, Inc. Permissions used & reasons: "Read and change your data on a number of websites" For our product to work, we require access to the websites we own and manage. "Replace the page you see when opening a new tab" This allows us to show you our product - new tab page with free web search. "Read your browsing history" This allows us to tailor product specific content or offers towards relevant information. "Display notifications" This allows us the option to send you updates or additional product offers once you’ve already enjoyed the free product. "Manage your apps, extensions, and themes" This allows us to help you disable or remove this product and also understand whether we are able to provide the best experience. Beta Release log: 13.953 : Non user facing attribution events 13.960 : Daily Content, Mac user consistency, optimized URL structure and bug fixes. 13.966 : Optimizes the sync of this extension between Chrome profiles.
The extension hijacks the New Tab page (`chrome_url_overrides.newtab`) to redirect to a Myway/Ask-owned search portal. Combined with the broad `tabs`, `webNavigation`, and `cookies` permissions, this is classic search/new-tab hijacker behavior (Mindspark/IAC PUP family).
"chrome_url_overrides": { "newtab": "ntp1.html" }, "permissions": [ "alarms", "cookies", "storage", "tabs", "webNavigation" ], "content_scripts": [ { "all_frames": true, "js": [ "/js/logger.js", "/js/util.js", "/js/localStorageContentScript.js" ], "matches": [ "https://download.gostudyhq.com/blank.jhtml" ], "run_at": "document_end" }Content script injected on `download.gostudyhq.com/blank.jhtml` exposes a `getLocalStorage` command that reads arbitrary localStorage keys from the page and forwards them to the background service worker via a runtime port. This is a covert localStorage read/exfiltration channel used to harvest install-attribution / DLP data planted by the affiliate splash page.
var portNamePrefix = "localStorageContentScript";var channel;var commands = { getLocalStorage: function(data) { var storage = window.localStorage; var key = data && data.key; return Promise.resolve(storage.getItem(key)); }};function init() { var port = chrome.runtime.connect({ name: Util.generateGuid(portNamePrefix + "-" + chrome.runtime.id + "-") }); channel = { id: port.name, port: port, callbacks: new Map() }; port.onMessage.addListener(onConnectMessage);}Uses the privileged `chrome.cookies.getAll` API to enumerate every cookie on `.gostudyhq.com` and harvest install-attribution fields (toolbarId, partnerId, partnerSubId, coId, country, campaign, etc.). Together with the localStorage and iframe-hash fallbacks, this is a multi-layered affiliate fingerprinting / data-exfiltration pipeline.
ExtensionSetUpDLP.getDataFromCookies = function(domain) { var parseCookies = function(cookies) { var cookiesObj = cookies.reduce(function(obj, cookie) { obj[cookie.name] = cookie.value; return obj; }, {}); var toolbarData = ExtensionSetUpDLP.cleanToolbarData(cookiesObj); Logger.log("ExtensionSetUpDLP: The fetched DLP data looks like: " + JSON.stringify(toolbarData)); return toolbarData; }; return new Promise(function(resolve, reject) { chrome.cookies.getAll({ domain: domain }, function(cookies) { if (cookies.some(function(cookie) { return cookie.name === "toolbarId"; })) { resolve(parseCookies(cookies));Walks every open tab and every iframe within them via `chrome.tabs.query` + `chrome.webNavigation.getAllFrames` to scrape URL hash fragments matching affiliate patterns. This is an aggressive cross-tab scan used to pull attribution/install parameters out of pages the extension was not legitimately given access to.
ExtensionSetUpDLP.getDataFromPageIframe = function(config, defaultToolbarData) { ... return new Promise(function(resolve, reject) { chrome.tabs.query({}, function(tabs) { ... var gettingTabIframes = []; var _loop_1 = function(tab) { gettingTabIframes.push(new Promise(function(resolveGettingIframePromise) { chrome.webNavigation.getAllFrames({ tabId: tab.id }, resolveGettingIframePromise); })); }; ... return Promise.all(gettingTabIframes) .then(function(results) { for (var _i = 0, results_1 = results; _i < results_1.length; _i++) { var tabIframeDetails = results_1[_i]; ... var url = new URL(iframeDetail.url); var urlHash = url.hash; if (!urlHash || !(parentProductHashMatchRegEx.test(urlHash) || extensionDetectContentScriptMatchRegEx.test(iframeDetail.url))) continue; return resolve(getToolbarDataFromURLHash(url));Content script on *.gostudyhq.com responds to web-page postMessage queries by leaking the user's toolbarId, partnerId, partnerSubId, installDate, version, and buildDate to any same-origin script. It also plants `mindsparktb_*` cookies advertising the install — a known Mindspark/IAC tracking marker that lets affiliate sites silently fingerprint users who have the extension installed.
ExtensionDetectForPPContentScript.getMessageListener = function(state) { return function(message) { if (message.origin !== document.location.origin) return; var data = typeof message.data === "string" ? JSON.parse(message.data) : message.data; if (data.from !== ExtensionDetectForPPContentScript.fromExtension && data.status === ExtensionDetectForPPContentScript.requestStatus) { var data_1 = { toolbarId: state.toolbarData.toolbarId, partnerId: state.toolbarData.partnerId, partnerSubId: state.toolbarData.partnerSubId, installDate: state.toolbarData.installDate, toolbarVersion: state.replaceableParams.version, toolbarBuildDate: state.replaceableParams.buildDate, }; window.postMessage(JSON.stringify(ExtensionDetectForPPContentScript.getMessage(state, ExtensionDetectForPPContentScript.requestStatus, data_1)), document.location.origin); } };};ExtensionDetectForPPContentScript.setInstalledCookies = function(toolbarId) { var hourFromNow = new Date(Date.now() + (1 * 60 * 60 * 1000)) .toUTCString(); document.cookie = "mindsparktb_" + toolbarId + "=true; expires=" + hourFromNow + "; path=/"; document.cookie = "mindsparktbsupport_" + toolbarId + "=true; expires=" + hourFromNow + "; path=/";};Exposes `chrome.management.uninstallSelf` and `chrome.runtime.setUninstallURL` via the `webtooltab` runtime-message API, which is reachable from the extension's own pages and (via webTooltabAPIProxy) from web content. Web-controlled uninstall + arbitrary post-uninstall redirect URL is a privilege-escalation surface that lets the operator's web pages silently redirect users to attacker-chosen URLs upon uninstall.
var features = { management: { uninstall: function(customUninstallOptions) { var uninstall = function() { return new Promise(function(resolve, reject) { var doUninstall = function() { try { var uninstallOptions = { showConfirmDialog: !!customUninstallOptions && customUninstallOptions .showConfirmDialog || false }; ... var result = chrome.management.uninstallSelf(uninstallOptions); ... chrome.runtime.setUninstallURL(customUninstallOptions.uninstallSurveyUrl || "", function() { if (chrome.runtime.lastError) { fireUL_1(chrome.runtime.lastError); } return uninstall(); });Combined with `domainsToRedirectToNewTab` in config.json (hp.myway.com, hp.ask.com, hp.mysearch.com, hp.mywebsearch.com, hp.tb.ask.com, hsts.myway.com, hp.norton.myway.com, hp.forgebrowser.com), the handler observes navigations via `chrome.tabs.onUpdated` and forcibly rewrites the user's tab URL to the extension's own new-tab page. This is browser/search hijacking — silently overriding the user's chosen homepage on competitor/legacy hijacker domains.
OtherDomainToExtensionPageRedirect.newTabRedirectHandler = function(tabId, changeInfo) { var tabURLString = decodeURI(changeInfo.url); var tabUrlParams = UrlUtils.parseQueryString(UrlUtils.parseUrl(tabURLString) .getQueryString()) .nameValues .filter(function(param) { return "ruid" === param.name || "rd" === param.name; }); var url = PageUtils.appendParams(PageUtils.getNewTabResourceUrl(), tabUrlParams.map(function(param) { return param.name + "=" + param.value; })); chrome.tabs.update(tabId, { url: url });};Renders OS-level notifications whose title, image, icon, and click `linkUrl` come entirely from a remote, operator-controlled config (notifications-config.json). On click the extension opens that arbitrary URL in a new tab — an operator-controlled push channel that can be used to deliver arbitrary monetized/redirect content (and is well-suited to phishing or scareware delivery) at any time without an extension update.
NotificationService.handleNotificationClick = function(notificationBaseDetails) { chrome.tabs.create({ url: notificationBaseDetails.linkUrl }, function(tab) { ... });};...NotificationService.showNotification = function(notification) { return new Promise(function(resolve) { ... self.registration .showNotification(notification.notificationOptions.title, { icon: notification.notificationOptions.iconUrl, data: notificationBaseDetails, requireInteraction: true, ... image: notification.notificationOptions.imageUrl, })Hard-coded list of nine competitor/legacy hijacker homepage domains that the extension forcibly intercepts and rewrites to its own new-tab page. The new-tab URL itself carries affiliate identifiers (partnerID, toolbarID, partnerSubID, installDate). The configuration is a smoking-gun for browser-search hijacking and affiliate monetization, characteristic of the Mindspark/Ask Apps PUP family.
"newTabURL": "https://hp.myway.com/studyhq/ttab02chr/index.html?p2=${partnerID}&n=${installDateHex}&ptb=${toolbarID}&si=${partnerSubID}", "homepageURLForBabClick": "", "track": "BETA02", "coId": "BVJ", "uninstallSurveyUrl": "https://gostudyhq.dl.myway.com/uninstall.jhtml?c=<!--toolbarID-->&ptb=<!--partnerID-->", "defaultPartnerId": "^BVJ^chr999^BETA02^", ... "domainsToRedirectToNewTab": "hp.myway.com,hp.ask.com,hp.mysearch.com,hp.mywebsearch.com,hp.tb.ask.com,www1.hp.ask-tb.com,hsts.myway.com,hp.norton.myway.com,hp.forgebrowser.com"Fetches JSON configuration from operator-controlled remote endpoints (notifications-config.json, ptag service, dailyContent config) and uses the response to drive runtime behavior — notification content + click-through URLs, search parameters injected into queries, and a remote `disable` switch. Remote-controlled behavior with operator-chosen URLs effectively constitutes remote-driven instructions.
RemoteConfigLoader.fetchRemoteConfig = function(remoteConfigUrl) { return new Promise(function(resolve, reject) { Logger.log("RemoteConfigLoader: fetchConfig " + remoteConfigUrl); fetch(remoteConfigUrl) .then(function(response) { if (!response.ok) return reject(new Error("error fetching " + remoteConfigUrl + " status: " + response.status)); ... return resolve(response.json()); })Periodically polls `params.gostudyhq.com/ptag` and applies the server-supplied `searchParams` object (PC, FROM, PTAG monetization tags) into the new-tab search URL, then pushes them live to every open extension tab. This lets the operator silently rewrite search-monetization parameters at runtime — a remote-controlled monetized search redirector.
PTagService.handlePTagServiceResponse = function(pTagServiceResponse) { if (!pTagServiceResponse || !pTagServiceResponse.searchParams || typeof pTagServiceResponse.ttl !== "number") { return Promise.reject(new Error("Invalid response from server: \"" + pTagServiceResponse + "\"")); } ... var newSearchParams = JSON.stringify(pTagServiceResponse.searchParams); ... extensionState.toolbarData.searchParams = newSearchParams; ... if (searchParamsChanged) { var data = { data: pTagServiceResponse.searchParams, destination: "searchParams", }; ConnectionManager.sendMessageToOpenWTT(data); }Injects a hidden iframe with a remote `pixelUrl` (built from affiliate placeholders: partnerId, sub_id, coId, toolbarId, s2-s5, country, sig) on first new-tab open. This is a covert install-conversion / affiliate tracking beacon — silent third-party telemetry executed without user awareness.
FirstOpenNT.firePixel = function(state) { return new Promise(function(resolve) { if (!state.toolbarData.pixelUrl || !state.configVars) return resolve(); var pixelURL = FirstOpenNT.replaceChildDomainToParent(state.toolbarData.pixelUrl, state.configVars .downloadDomain); var iframe = document.createElement("iframe"); iframe.addEventListener("load", function(e) { iframe.parentNode.removeChild(iframe); Logger.log("UnifiedLogging: pixel fired " + pixelURL); }, true); iframe.setAttribute("src", pixelURL); document.body.appendChild(iframe); state.toolbarData.pixelUrl = null; resolve(); });};Continuously beacons telemetry (toolbarId, partnerId, sub_id, coId, version, userSegment, event name) to `anx.gostudyhq.com` on install, every 6-hour live-ping alarm, every notification show/click, every uninstall API event, and every error. The extension also fires "on behalf of DLP" pings to a download-domain endpoint. This is heavy persistent affiliate tracking far beyond what's needed for extension functionality.
UnifiedLogging.fireEvent = function(eventName, url, state, eventSpecificData) { return new Promise(function(resolve, reject) { ... var data = eventSpecificData ? Object.assign(UnifiedLogging.createStandardData(eventName, state), eventSpecificData) : UnifiedLogging.createStandardData(eventName, state); var searchParamsFromData = UnifiedLogging.getParamsFromData(data); url += ~url.indexOf("?") ? searchParamsFromData : searchParamsFromData.replace("&", "?"); fetch(url) ... UnifiedLogging.createStandardData = function(eventName, state) { return { anxa: "CAPNative", anxv: state.replaceableParams.toolbarVersion, anxe: eventName, anxt: state.toolbarData.toolbarId, anxtv: state.replaceableParams.toolbarVersion, anxp: state.toolbarData.partnerId, anxsi: state.toolbarData.partnerSubId, anxd: state.replaceableParams.buildDate, f: "00400000", anxr: +new Date(), coid: state.toolbarData.coId, userSegment: state.toolbarData.userSegment }; };By severity
Versions scanned
Showing 1 of 3 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 13.986.19.63728 | 13 |
Files with findings
12 distinct paths — top paths by unique finding count:
- js/extensionSetUpDLP.js2
- config/config.json1
- js/extensionDetectForPPContentScript.js1
- js/firstOpenNT.js1
- js/localStorageContentScript.js1
- js/notificationService.js1
- js/otherDomainToExtensionPageRedirect.js1
- js/pTagService.js1
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.