Is 小满助手 safe?
小满助手 is medium risk. Using the search panel on Google results reads the search term or a history item and sends a search-history record via the background handler, resolving to POST crm.xiaoman.cn/api/external/searchHistoryWrite/add. No body captured live.…
Who publishes it深圳市小满科技有限公司 - 4 other listings from the same operator, none carrying a finding
深圳市小满科技有限公司 - 4 other listings from the same operator, none carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
2 other listings published from this account, 13k+ users between them, none of them carrying a finding.
Same operator - 2 listings
Published under a different store account, but sharing the registered address, contact or declared legal entity this one gave the store.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Google search history is posted to Xiaoman CRM
Using the search panel on Google results reads the search term or a history item and sends a search-history record via the background handler, resolving to POST crm.xiaoman.cn/api/external/searchHistoryWrite/add.
No body captured live.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You submit a search from the extension panel on a Google results page.
The extension reads the search term and selected search context, then routes it to Xiaoman CRM.
- Search termvendor contacts
Shows the words you searched for in Google or selected from the extension history panel.
- Selected command关键词挖掘
Shows which extension search template was applied to your search term.
- Search filtersexample.com
Shows which domain filters the extension included with the submitted search-history record.
No captured response body was available; the URL and method are resolved from the shipped request helper and API map.
Google search submission and background CRM route
Content script request helper
dist/content/google/content.jsrequest = async (api, body) => chrome.runtime.sendMessage({ event: "api-request", data: { api: api, body: body }}).then(response => { try { if (-1 === response.code) { const error = new Error("request error"); throw error.data = response.data, error } return response.data } catch (e) { return Promise.reject(e.data) }})Content script search submission
dist/content/google/content.jssaveHistory: data => request("google.addSearchHistory", data),submit() { const filterList = this.checkedFilterList, keyword = this.checkedKeyword, history = this.checkedHistory; localStorage.setItem("advanced-search-filter-list", JSON.stringify(filterList)); const searchInput = document.querySelector("textarea.gLFyf"), value = history && history.keyword || searchInput.value; searchInput.value = keyword ? keyword.command.replace(/{{keyword}}/, value) : value, this.saveHistory({ keyword: value, command: keyword ? keyword.name : void 0, filters: filterList }).then(() => { const submit = document.querySelector(".Tg7LZd[type=submit]"); submit && (submit.click(), this.hide()) })}Background CRM POST mapping
dist/background/index.mjsvar request = import_axios.default.create({ withCredentials: !0, crossOrigin: !0, timeout: 3e4, baseURL: env.SERVERS.CRM + "/api/external", headers: { "x-xiaoman-platform-type": "chrome-extension", "x-xiaoman-platform-version": package_default_version }});function post(url, preData = {}) { return (data = {}, params = {}) => (data => request.request({ url: url, method: "post", data: import_lib.default.stringify(Object.assign({}, preData, data)), params: params }))(data)}var google_default = { fetchSearchKeywordDigRule: get$1("/chore/keywordDigRule"), fetchSearchFilterList: get$1("/filterRead/List?filter_type=2"), addSearchFilter: post("/filterWrite/add?filter_type=2"), removeSearchFilter: post("/filterWrite/remove?filter_type=2"), addSearchHistory: post("/searchHistoryWrite/add"), fetchSearchHistoryRecently: get$1("/searchHistoryRead/list"), checkCrawledHost: post("/crawlRead/checkCrawledHost")}- crm.xiaoman.cn
Receives the search-history POST routed by the extension background service worker.
Advanced Google searches are saved to Xiaoman CRM
Submitting a search from the advanced-search panel reads the Google search box value, packaging it with selected command/filter context, then POSTs to crm.xiaoman.cn/api/external/searchHistoryWrite/add.
Earlier capture missed this; no body.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You submit a search from the extension panel on a Google results page.
The extension reads the search term and selected search context, then routes it to Xiaoman CRM.
- Search termvendor contacts
Shows the words you searched for in Google or selected from the extension history panel.
- Selected command关键词挖掘
Shows which extension search template was applied to your search term.
- Search filtersexample.com
Shows which domain filters the extension included with the submitted search-history record.
No captured response body was available; the URL and method are resolved from the shipped request helper and API map.
Google search submission and background CRM route
Content script request helper
dist/content/google/content.jsrequest = async (api, body) => chrome.runtime.sendMessage({ event: "api-request", data: { api: api, body: body }}).then(response => { try { if (-1 === response.code) { const error = new Error("request error"); throw error.data = response.data, error } return response.data } catch (e) { return Promise.reject(e.data) }})Content script search submission
dist/content/google/content.jssaveHistory: data => request("google.addSearchHistory", data),submit() { const filterList = this.checkedFilterList, keyword = this.checkedKeyword, history = this.checkedHistory; localStorage.setItem("advanced-search-filter-list", JSON.stringify(filterList)); const searchInput = document.querySelector("textarea.gLFyf"), value = history && history.keyword || searchInput.value; searchInput.value = keyword ? keyword.command.replace(/{{keyword}}/, value) : value, this.saveHistory({ keyword: value, command: keyword ? keyword.name : void 0, filters: filterList }).then(() => { const submit = document.querySelector(".Tg7LZd[type=submit]"); submit && (submit.click(), this.hide()) })}Background CRM POST mapping
dist/background/index.mjsvar request = import_axios.default.create({ withCredentials: !0, crossOrigin: !0, timeout: 3e4, baseURL: env.SERVERS.CRM + "/api/external", headers: { "x-xiaoman-platform-type": "chrome-extension", "x-xiaoman-platform-version": package_default_version }});function post(url, preData = {}) { return (data = {}, params = {}) => (data => request.request({ url: url, method: "post", data: import_lib.default.stringify(Object.assign({}, preData, data)), params: params }))(data)}var google_default = { fetchSearchKeywordDigRule: get$1("/chore/keywordDigRule"), fetchSearchFilterList: get$1("/filterRead/List?filter_type=2"), addSearchFilter: post("/filterWrite/add?filter_type=2"), removeSearchFilter: post("/filterWrite/remove?filter_type=2"), addSearchHistory: post("/searchHistoryWrite/add"), fetchSearchHistoryRecently: get$1("/searchHistoryRead/list"), checkCrawledHost: post("/crawlRead/checkCrawledHost")}- crm.xiaoman.cn
Receives the search-history POST routed by the extension background service worker.
Instagram DM URLs are resolved through inactive tabs
Code shows a RESOLVE_IG_URL background handler for Messenger/Instagram messaging.
Given a username, it opens an inactive tab at an Instagram messaging URL, waits 5s, reads the redirected URL, closes it, and returns that URL for navigation.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You start an Instagram messaging workflow that includes a target username.
The extension opens an inactive Instagram messaging tab, reads its resolved URL, closes it, and returns the result.
- Instagram usernameacme
Identifies the messaging destination that the extension asks Instagram to resolve.
- Initial messaging URLhttps://www.instagram.com/m/acme
Shows the Instagram messaging address opened by the inactive tab.
- Resolved conversation pathhttps://www.instagram.com/direct/t/17841400000000000/
Shows the redirected conversation URL returned to the content script for page navigation.
- Wait time5 seconds
Shows how long the background handler waits before reading and closing the tab.
Illustrative username shown; no captured response body was recorded for this source-built GET navigation.
Background resolver and content-script navigation
Background RESOLVE_IG_URL handler
dist/background/index.mjsif ("RESOLVE_IG_URL" === request.event) { const { name: name } = request.data, targetUrl = `https://www.instagram.com/m/${name}`; return chrome.tabs.create({ url: targetUrl, active: !1 }, tab => { const tabId = tab.id, timer = setTimeout(() => { chrome.tabs.get(tabId, updatedTab => { chrome.tabs.remove(tabId), sendResponse(updatedTab.url) }), clearTimeout(timer) }, 5e3) }), !0}Messenger/Instagram content-script caller
dist/content/messenger/content.jsasync locationToConversation(userid, name) { const targetPath = await import_browser_polyfill.runtime.sendMessage({ event: "RESOLVE_IG_URL", data: { name: name } }); if (console.log("locationToConversation resolved path:", targetPath), !targetPath.includes("direct/t/")) throw new Error("无法打开会话"); const state = { timestamp: Date.now(), source: "mass_sender" }; window.history.pushState(state, "", targetPath), window.dispatchEvent(new PopStateEvent("popstate", { state: state })), window.dispatchEvent(new HashChangeEvent("hashchange")), await this.delay(3e3)}- www.instagram.com
Receives the inactive-tab navigation used to resolve the direct-message URL.
+2 more findings not shown