Back to skill

Security audit

GeekBI Temu店铺研究

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches Temu shop research, but it adds automatic feedback reporting plus broad account, credential, and payment flows with weak consent and scoping safeguards.

Review this skill carefully before installing. Use it only if you are comfortable giving LinkFox an API key and possibly using its phone-login and paid-credit flows. Do not set gateway URL environment variables to untrusted hosts, avoid placing API keys in shell startup files when a secret store is available, and do not allow feedback to be sent unless you have reviewed and approved the exact content.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

other

Error
Location
SKILL.md:162
Finding

Automatic Disclosure of User Feedback Without Explicit Consent

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/geekbi_temu_mall_search.py:26
Finding

Environment-Controlled API Destinations Can Exfiltrate Credentials and Session Metadata

Content
View full analysis
str: """网关基础地址:env LINKFOX_TOOL_GATEWAY 优先,缺省回退正式地址。""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") ``` The selected destination receives the API key and session metadata: ```python def call_api(params): global _LAST_CALL_WAS_HTTP_ERROR _LAST_CALL_WAS_HTTP_ERROR = False req = Request( get_api_url(), data=json.dumps(params).encode("utf-8"), headers={ "Authorization": get_api_key(), "Content-Type": "application/json", "User-Agent": "LinkFox-Skill/2.0", "SESSION_ID": (os.environ.get("SESSION_ID") or "").strip(), "MESSAGE_ID": os.environ.get("MESSAGE_ID", ""), "MODE_ID": os.environ.get("MODE_ID", ""), "APP_NAME": os.environ.get("APP_NAME", ""), }, method="POST", ) try: with urlopen(req, timeout=150) as response: raw = response.read().decode("utf-8") ``` The onboarding script exposes additional configurable destinations: ```python def _agent_base() -> str: return _env_base("LINKFOX_AGENT_API_URL", "https://tool-gateway.linkfox.com", "LINKFOX_TOOL_GATEWAY") def _login_base() -> str: return _env_base("LINKFOX_LOGIN_API_URL", "https://api.linkfox.com") def _agent_user_base() -> str: return _env_base("LINKFOX_AGENT_USER_API_URL", "https://agent-api.linkfox.com") ``` Its requests can contain an access token: ```python def _headers(source: str, origin ...[truncated 2534 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/geekbi_temu_mall_search.py:35
Finding

Unvalidated Session Identifier Enables Writes Outside the Intended Workspace

Content
View full analysis
str: """优先 env SESSION_ID;缺省按 HHMMSS-<6 hex> 生成(进程内稳定)。""" env = (os.environ.get("SESSION_ID") or "").strip() if env: return env if "_auto" not in _SESSION_CACHE: _SESSION_CACHE["_auto"] = time.strftime("%H%M%S", time.localtime(ts)) + "-" + secrets.token_hex(3) return _SESSION_CACHE["_auto"] ``` The value is used directly as a path component: ```python def _ensure_session(ts: float) -> tuple[str, str]: date_str = time.strftime("%Y-%m-%d", time.localtime(ts)) sid = _session_id(ts) root = _linkfox_root() session_dir = os.path.join(root, date_str, sid) os.makedirs(session_dir, exist_ok=True) _ensure_meta(root, session_dir, date_str, sid, ts) return root, session_dir ``` The onboarding script uses the same unsafe pattern: ```python def session_dir() -> str: ts = time.time() sid = (os.environ.get("SESSION_ID") or "").strip() or ( time.strftime("%H%M%S", time.localtime(ts)) + "-" + secrets.token_hex(3)) path = os.path.join(_linkfox_root(), time.strftime("%Y-%m-%d", time.localtime(ts)), sid) os.makedirs(path, exist_ok=True) return path ``` ### Technical Analysis `SESSION_ID` is treated as a trusted directory name. It can contain `..` components, path separators, or an absolute path. In Python, an absolute later component passed to `os.path.join` discards preceding components. Traversal components can likewise escape the intended session directory after normalization. The wrappers write `_meta.json`, response JSO ...[truncated 1506 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:466
Finding

API Key Is Printed to Standard Output and Recommended for Plaintext Shell Storage

Content
View full analysis
dict: masked = _mask_phone(phone) if not re.fullmatch(r"\d{11}", phone): return {"error": f"login: 手机号格式不正确: {phone}", "phone": masked} if not re.fullmatch(r"\d{4,8}", code): return {"error": f"login: 验证码格式不正确: {code}", "phone": masked} lg = _login_v3(phone, code, channel) if "error" in lg: return {"error": lg["error"], "phone": masked} if lg.get("is_new_user"): lbt = _login_by_token(lg["access_token"], lg["refresh_token"]) if "error" in lbt: print(f"{TAG} {lbt['error']}(不影响拿 key)", file=sys.stderr) info = _fetch_user_info_v3(lg["access_token"], lg["user_id"]) if "error" in info: return {"error": info["error"], "phone": masked} tok = _get_or_generate_api_token(lg["access_token"], lg["user_id"], info["group_id"]) if "error" in tok: return {"error": tok["error"], "phone": masked} return { "api_key": tok["api_key"], "phone": masked, "group_id": info["group_id"], "member_id": info["member_id"], "source": tok["source"], "nick_name": lg.get("nick_name", ""), "team_name": info.get("team_name", ""), "is_new_user": lg.get("is_new_user", False), } ``` The returned object is printed unredacted: ```python def _emit(obj: dict) -> None: print(json.dumps(obj, ensure_ascii=False, indent=2)) def _cmd_login(args) -> int: r = login_and_get_key(args.phone.strip(), args.code.strip(), args.channel) _emit(r) if "api_key" in r: print(f"{TAG} 成功获取 API key(来源: {r['source']})", file=sys.stderr) return 0 return 1 ``` The onb ...[truncated 1930 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:163
Finding

Onboarding Recommends Installation of Unpinned Runtime Dependencies

Content
View full analysis
dict: try: import qrcode except ImportError: err = "缺少 qrcode 依赖,请运行: pip install qrcode pillow" print(f"{TAG} render_qr: {err}", file=sys.stderr) return {"png_path": None, "ascii_qr": None, "error": err} ``` The HTTP dependency is handled similarly: ```python def _require_requests() -> None: if requests is None: raise RuntimeError("缺少 requests 依赖,请运行: pip install requests") ``` ### Technical Analysis The installation commands do not specify versions, hashes, a lockfile, an isolated environment, or an approved package index. They therefore resolve mutable package versions at installation time. The package names shown are established packages and no typosquatting was identified. Nevertheless, an unpinned installation path creates supply-chain exposure: future compromised releases, dependency confusion caused by index configuration, malicious mirrors, or incompatible updates could introduce code execution during installation or import. Because onboarding handles phone numbers, OTPs, access tokens, API keys, and payment information, dependency integrity is especially important. ### Attack Path 1. The onboarding command encounters a missing `requests`, `qrcode`, or `pillow` dependency. 2. The user follows the displayed unversioned `pip install` command. 3. Package resolution uses the current configured package index and latest compatible releases. 4. A compromised release, malicious mirror, or index-resolution attack ...[truncated 651 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (30)

Tainted flow: 'req' from os.environ.get (line 151, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/geekbi_temu_category_list.py (reported line 166)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)

Tainted flow: 'req' from os.environ.get (line 151, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The request URL and several outbound headers are influenced by environment variables, especially LINKFOX_TOOL_GATEWAY and SESSION_ID/MESSAGE_ID/MODE_ID/APP_NAME. In an agent runtime, attacker-controlled or insufficiently trusted environment data can redirect requests to an arbitrary host and exfiltrate the API key and request metadata via the Authorization header, making this a real SSRF/credential-leak risk.

Content

Scanner excerpt · scripts/geekbi_temu_mall_search.py (reported line 166)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)

Tainted flow: 'req' from os.environ.get (line 151, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The request sent via urlopen includes multiple HTTP headers sourced directly from environment variables, including SESSION_ID, MESSAGE_ID, MODE_ID, and APP_NAME. Because the destination base URL is also environment-controlled via LINKFOX_TOOL_GATEWAY, an attacker who can influence the runtime environment can redirect requests to an arbitrary host and exfiltrate these identifiers and the API key-bearing request, creating an SSRF-plus-secret-leak channel. In an agent skill context, trusting environment input for outbound network targets is especially risky because skills often run in shared or orchestrated environments where env vars may be user-influenced or misconfigured.

Content

Scanner excerpt · scripts/geekbi_temu_site_list.py (reported line 166)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)

Tainted flow: 'url' from os.environ.get (line 234, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The POST target is derived from environment-controlled base URLs, and the request may include sensitive authentication material such as access tokens, uid/tid headers, or login payloads. In an agent or hosted execution environment, a malicious wrapper or misconfigured deployment can redirect these requests to an attacker-controlled host and exfiltrate credentials or verification data.

Content

Scanner excerpt · scripts/onboarding.py (reported line 195)May include surrounding context.

python
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""

Tainted flow: 'req' from os.environ.get (line 245, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The gateway request URL is constructed from environment-controlled base settings and then used with Authorization and session-related headers. If those environment variables are tampered with, the CLI can send API keys and account metadata to an attacker endpoint, making this a credential exfiltration path.

Content

Scanner excerpt · scripts/onboarding.py (reported line 247)May include surrounding context.

python
headers["Content-Type"] = "application/json"
    req = Request(url, method=method, data=body_bytes, headers=headers)
    try:
        with urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        status = e.code

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is presented as marketplace research, but the referenced onboarding flow reportedly includes authentication, account inspection, package purchase, order creation, payment QR generation, and local QR image storage. Mixing commerce, authentication, and billing operations into a research skill materially expands the trust boundary and can expose users to unintended account or payment actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as marketplace research, but the referenced onboarding flow reportedly includes authentication, account inspection, package purchase, order creation, payment QR generation, and local QR image storage. Mixing commerce, authentication, and billing operations into a research skill materially expands the trust boundary and can expose users to unintended account or payment actions.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 127)May include surrounding context.

python scripts/geekbi_temu_mall_search.py '{"regionId":211,"page":1,"size":3,"mallStarMin":4}'

text

## Display Rules

1. State the selected marketplace (`regionId`, site name, and currency when available), filters, current page, and page size.
2. Present shop name, `mallId`, rating, historical sales and revenue, average order value, followers, active products, hosting mode, categories, and opening time when returned.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · references/onboarding.md (reported line 14)May include surrounding context.

md
示 JSON 里的 phone/agreements
   - 收到验证码后:`python scripts/onboarding.py login <phone> <code>`
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 优先使用 `LINKFOX_AGENT_API_KEY`;兼容旧环境时可使用 `LINKFOXAGENT_API_KEY`

**billing 场景**:`errcode=402` 或消息含 `算力/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG > `pay_ur

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements phone login, API key acquisition, subscription listing, paid ordering, and payment QR generation, which are unrelated to a GeekBI Temu shop query skill. That mismatch materially increases risk because the skill can collect credentials and initiate billing workflows under the guise of analytics functionality.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill creates paid orders and renders payment QR codes, enabling monetary transactions unrelated to querying public Temu shop metrics. Because this capability is hidden inside an analytics-branded skill, it creates a strong risk of deceptive charges, social engineering, or abuse of the user's authenticated account context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code can fetch or generate API tokens for a user group after SMS-based login, effectively turning the skill into a credential acquisition tool. In the context of a store analytics skill, this is especially dangerous because it enables unauthorized persistence and later API access beyond the immediate user action.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises capabilities that clearly involve environment variables, local file writes, and network access, but it does not declare an explicit tool scope such as allowed-tools or permissions. That omission weakens review and enforcement boundaries, making it easier for a skill to exercise broader capabilities than a caller may expect.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file contains substantial user-facing guidance in Chinese under sections such as 调用方式 and 解决认证和算力问题, while other sections are in English. This creates a locale/language constraint without explicit opt-in or a documented justification, which can violate language-choice policy for general users.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill requires writing every full API response to a session-linked local file by default, regardless of whether all fields are needed for the user response. This creates unnecessary retention of potentially sensitive user queries, account-linked context, or third-party data, increasing exposure if the workspace, logs, or session directories are later accessed by unauthorized parties.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file is almost entirely presented in Chinese, which effectively forces a specific language on users reading the skill documentation. The policy allows locale constraints only when the skill offers user choice or clearly documents a justified region-specific limitation, neither of which is stated here.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 75)May include surrounding context.

当最小和最大时间同时提供时,二者都必须为合法 ISO-8601 date-time,且最小值不得晚于最大值。

bash
curl -X POST "${LINKFOX_TOOL_GATEWAY}/geekbi/temu/mallSearch" \
  -H "Authorization: ${LINKFOX_AGENT_API_KEY:-$LINKFOXAGENT_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "User-Agent: LinkFox-Skill/2.0" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 156)May include surrounding context.

无业务参数,Body 传 {}。只将非空且为正整数的 sites[].regionId 用于店铺搜索;sites[].siteId 是上游内部 ID,不得代替 regionId。如果没有有效 regionId,应停止链式调用并告知用户。

bash
curl -X POST "${LINKFOX_TOOL_GATEWAY}/geekbi/temu/siteList" \
  -H "Authorization: ${LINKFOX_AGENT_API_KEY:-$LINKFOXAGENT_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "User-Agent: LinkFox-Skill/2.0" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 189)May include surrounding context.

先用 {} 获取一级节点;需要下钻时,只把非空且为非负整数的 catId 作为下一次请求的 parentCatId;筛选店铺时,只把有效 catId 放入 catIds 数组。传 0 合法,但没有证据证明它与省略 parentCatId 等价。

bash
curl -X POST "${LINKFOX_TOOL_GATEWAY}/geekbi/temu/categoryList" \
  -H "Authorization: ${LINKFOX_AGENT_API_KEY:-$LINKFOXAGENT_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "User-Agent: LinkFox-Skill/2.0" \

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation adds a separate feedback-posting API unrelated to the stated shop-query purpose, creating an extra outbound action surface that could transmit user content to a third party. In an agent setting, this can enable unintended data exfiltration or unauthorized side effects if the agent is induced to submit feedback containing user prompts, results, or internal context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The instructions explicitly ask the user to provide a phone number so a local script can register or log in on their behalf, but they do not disclose how that personal data and subsequent verification code or API key will be handled, stored, or protected. In a skill context, this can normalize collection of sensitive identifiers without informed consent and increases privacy and account-takeover risk if logs, terminals, or support transcripts are retained.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes this skill as querying and filtering Temu public market shops and GeekBI shop metrics, but the code is hardwired to call /geekbi/temu/categoryList. A category list operation is semantically different from store/shop querying, so the implemented behavior does not match the skill's declared purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill always writes full API responses plus session metadata to local disk, even though the skill purpose is only to query/filter public shop data. Persisting complete responses and operational metadata broadens data exposure, creates retention risk, and may leak account-scoped API output or identifiers to other local users, later processes, or support artifacts.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/onboarding.py (reported line 195)May include surrounding context.

python
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Sending SMS codes and performing phone-based login is outside the expected scope of a store-query skill and allows the skill to collect and process identity/authentication factors. In this context, the feature is more dangerous because users may not expect an analytics skill to request login codes or act on their behalf to obtain account access.

Content

No source excerpt is available for this finding.