Is 小满助手 safe?

Medium risk

小满助手 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.…

小满科技技术团队v3.2.78Chrome Web Store
52Risk
Who publishes it

深圳市小满科技有限公司 - 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.

Publisher
小满科技技术团队
Declared legal entity
深圳市小满科技有限公司
Registered address
南山区深南大道9678号, 大冲商务中心B座14层, Shenzhen Shi, Guangdong Sheng 518000, CN

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
What actually happens
You did this

You submit a search from the extension panel on a Google results page.

The extension did this

The extension reads the search term and selected search context, then routes it to Xiaoman CRM.

Fields prepared for the search-history POST
  • Search term
    vendor 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 filters
    example.com

    Shows which domain filters the extension included with the submitted search-history record.

Captured request
POSThttps://crm.xiaoman.cn/api/external/searchHistoryWrite/add

No captured response body was available; the URL and method are resolved from the shipped request helper and API map.

The code that does this

Google search submission and background CRM route

Readable version

Content script request helper

dist/content/google/content.js
request = 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.js
saveHistory: 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.mjs
var 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")}
Destination host
    • 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
What actually happens
You did this

You submit a search from the extension panel on a Google results page.

The extension did this

The extension reads the search term and selected search context, then routes it to Xiaoman CRM.

Fields prepared by the advanced-search submission
  • Search term
    vendor 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 filters
    example.com

    Shows which domain filters the extension included with the submitted search-history record.

Captured request
POSThttps://crm.xiaoman.cn/api/external/searchHistoryWrite/add

No captured response body was available; the URL and method are resolved from the shipped request helper and API map.

The code that does this

Google search submission and background CRM route

Readable version

Content script request helper

dist/content/google/content.js
request = 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.js
saveHistory: 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.mjs
var 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")}
Destination host
    • 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
What actually happens
You did this

You start an Instagram messaging workflow that includes a target username.

The extension did this

The extension opens an inactive Instagram messaging tab, reads its resolved URL, closes it, and returns the result.

Values used during Instagram URL resolution
  • Instagram username
    acme

    Identifies the messaging destination that the extension asks Instagram to resolve.

  • Initial messaging URL
    https://www.instagram.com/m/acme

    Shows the Instagram messaging address opened by the inactive tab.

  • Resolved conversation path
    https://www.instagram.com/direct/t/17841400000000000/

    Shows the redirected conversation URL returned to the content script for page navigation.

  • Wait time
    5 seconds

    Shows how long the background handler waits before reading and closing the tab.

Captured request
GEThttps://www.instagram.com/m/acme

Illustrative username shown; no captured response body was recorded for this source-built GET navigation.

The code that does this

Background resolver and content-script navigation

Readable version

Background RESOLVE_IG_URL handler

dist/background/index.mjs
if ("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.js
async 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)}
External host used for URL resolution
    • www.instagram.com

    Receives the inactive-tab navigation used to resolve the direct-message URL.

+2 more findings not shown

Updated 30 September 2026lkacpincnpeaopanmojlgibodfibghjc