Back to skill

Security audit

Shopee-店铺分类

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly implements Shopee shop-category API calls, but it also handles account login, API-key generation, billing orders, credential-bearing network calls, and broad local persistence in ways that need review before use.

Install only if you trust LinkFox and are comfortable with this skill managing Shopee category data plus LinkFox account setup and billing assistance. Before use, prefer obtaining and storing API keys through a secure secret manager, avoid entering phone/SMS codes into shared logs, verify any payment order before proceeding, and avoid setting custom LINKFOX_* gateway URL environment variables unless you fully trust the destination. Treat saved linkfox output files as sensitive business data and delete them when no longer needed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_shopee_shop_category_common.py:18
Finding

Credential Exfiltration Through Environment-Controlled Service Endpoints

Content
View full analysis
dict: api_key = get_api_key() data = json.dumps(params).encode("utf-8") req = Request( endpoint, data=data, headers={ "Authorization": api_key, "Content-Type": "application/json", "User-Agent": "LinkFox-Skill/1.0", }, method="POST", ) try: with urlopen(req, timeout=150) as response: return json.loads(response.read().decode("utf-8")) ``` Onboarding uses the same trust pattern for additional credential-bearing services: ```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") ``` ```python def _http_post(url: str, body: dict, headers: dict, timeout: int = 30) -> dict: try: _require_requests() except RuntimeError as e: return {"_error": str(e)} try: r = requests.post(url, json=body or {}, headers=headers, timeout=timeout) return r.json() ``` ### Technical Analysis The Skill reads network destinations from environment variables and transmits sensitive authentication material to those destination ...[truncated 1847 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/onboarding.py:402
Finding

Automatic Secondary Disclosure of Access and Refresh Tokens for Promotional Credits

Content
View full analysis
dict: resp = _http_post(f"{_agent_user_base()}/account/loginByToken", { "token": access_token, "refreshToken": refresh_token, "device": {"aid": "3026344186", "did": "", "type": "Windows", "os": "10", "model": "149.0.0.0", "brand": "Chrome"}, }, _headers("agent-linkfox-web", "agent.linkfox.com", access_token=access_token)) if "_error" in resp: return {"error": f"loginByToken: {resp.get('_body') or resp['_error']}"} if resp.get("errcode") != 200: return {"error": f"loginByToken: {resp.get('errmsg') or json.dumps(resp, ensure_ascii=False)}"} return {} ``` ```python 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']}", file=sys.stderr) ``` ### Technical Analysis After an SMS login, the Skill automatically forwards both the access token and refresh token to a second service when the account is considered new. It also supplies synthetic browser/device metadata. This call is intended to trigger new-user promotional credits. It is not required to authenticate a Shop Category API request and is not necessary for the Skill's declared store-category functionality. The onboarding documentation does not clearly request informed user consent for this additional token replay and account-side effect. Refresh tokens are particularly sensitive because they may remain useful after an access token expires. Forwarding both token types expands the number of services and request paths that must remain trusted. ### Attack Pat ...[truncated 950 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_shopee_shop_category_common.py:183
Finding

Path Traversal and Insecure Persistence of Complete API Responses

Content
View full analysis
str: cached = _LF_SESSION_CACHE.get("_root") if cached: return cached candidates = [] acpx = (os.environ.get("ACPX_WORKSPACES") or "").strip() if acpx: acpx = acpx.split(os.pathsep)[0].strip() if acpx: candidates.append(os.path.join(acpx, "linkfox")) candidates.append(os.path.join(os.getcwd(), "linkfox")) candidates.append(os.path.join(os.path.expanduser("~"), "linkfox")) candidates.append(os.path.join(_lf_tempfile.gettempdir(), "linkfox")) for root in candidates: try: os.makedirs(root, exist_ok=True) probe = os.path.join(root, ".write_probe") with open(probe, "w", encoding="utf-8") as f: f.write("") os.remove(probe) except OSError: continue root = os.path.abspath(root) _LF_SESSION_CACHE["_root"] = root return root fallback = os.path.abspath(candidates[-1]) _LF_SESSION_CACHE["_root"] = fallback return fallback ``` ```python def _lf_session_id(ts: float) -> str: env = os.environ.get("SESSION_ID") if env: return env.strip() if "_auto" not in _LF_SESSION_CACHE: _LF_SESSION_CACHE["_auto"] = ( _lf_time.strftime("%H%M%S", _lf_time.localtime(ts)) + "-" + _lf_secrets.token_hex(3) ) return _LF_SESSION_CACHE["_auto"] ``` ```python def emit_result(result, slug=SLUG, inline=False): serialized = json.dumps(result, ensure_ascii=False, indent=2) ts = _lf_time.time() date_str = _lf_time.strftime("%Y-%m-%d", _lf_time.localtime(ts)) sid = _lf_session_id(ts) root = _lf_root() session_dir = os.path.join(root, date_str, sid) os.makedirs(session_dir ...[truncated 2991 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:486
Finding

Full API Key Disclosure Through Standard Output and Plaintext Shell Configuration

Content
View full analysis
None: print(json.dumps(obj, ensure_ascii=False, indent=2)) ``` ```python 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 acquired successfully: {r['source']}", file=sys.stderr) return 0 return 1 ``` The onboarding documentation recommends persistent plaintext storage using commands equivalent to: ```bash setx LINKFOX_AGENT_API_KEY "" echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.zshrc echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.bashrc ``` ### Technical Analysis The login command returns the complete API key in a dictionary and serializes that dictionary directly to standard output. Standard output is commonly captured by Agent transcripts, command runners, CI logs, terminal history systems, debugging infrastructure, and parent processes. The documented setup procedure then recommends writing the key directly into shell startup files. These files are persistent, frequently backed up or synchronized, and may be readable by other local processes or users depending on permissions. The combination creates multiple long-lived copies of a bearer credential outside a dedicated secret-storage mechanism. ### Attack Path 1. The user runs the onboarding login command with a valid SMS code. 2. The Skill obtains or generates an API key. 3. The complete key is prin ...[truncated 820 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:163
Finding

Unpinned Runtime Dependency Installation Guidance

Content
View full analysis
dict: try: import qrcode except ImportError: return {"png_path": None, "ascii_qr": None, "error": "pip install qrcode pillow"} ``` ```python def _require_requests() -> None: if requests is None: raise RuntimeError("pip install requests") ``` ### Technical Analysis The recommended commands install the latest versions selected by the active pip configuration and package index. The project does not provide a lockfile, exact versions, integrity hashes, or a documented trusted index for these runtime dependencies. Package installation can execute package build backends and installation hooks. An altered package index, dependency-confusion condition, compromised upstream release, or malicious future version could therefore introduce code that executes in the user's environment. No evidence was found that the Skill automatically executes these pip commands. The risk arises when users follow the runtime remediation guidance. ### Attack Path 1. The runtime lacks `requests`, `qrcode`, or Pillow. 2. The Skill displays an installation command without pinned versions or hashes. 3. The user runs the command in an environment configured to use an untrusted or compromised package index. 4. Pip resolves mutable package versions and dependencies from that index. 5. A malicious package or build dependency executes during installation or later import. 6. The malicious code obtains the permissions of the user running pip or the Skill. ### Impact Assessment A compromised Python package can execut ...[truncated 342 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (36)

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The POST destination is derived from environment-controlled base URLs, and the request can carry sensitive data including phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys. If an attacker can influence environment variables in the skill runtime, they can redirect these requests to an attacker-controlled endpoint and exfiltrate credentials; the mismatch between the skill's Shopee category purpose and this onboarding/login behavior makes the risk more suspicious, not less.

Content

Scanner excerpt · scripts/onboarding.py (reported line 196)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 244, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The gateway URL used by urllib is also built from environment-controlled base URLs and is invoked with the Authorization API key header. An attacker who can set the environment can redirect authenticated requests to an external host and capture API keys and account/order data; in a skill that claims to manage Shopee categories, this hidden onboarding and billing traffic is especially dangerous because users would not expect credential and payment flows.

Content

Scanner excerpt · scripts/onboarding.py (reported line 246)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
99% confidence
Finding

A shop-category skill should not also contain or invoke phone login, token handling, API-key management, subscription/order/payment flows, or QR-code generation unless those functions are explicitly disclosed and required. Bundling account/payment and credential operations into a different business function significantly expands attack surface and can expose users to credential misuse, unauthorized charges, or covert account actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A shop-category skill should not also contain or invoke phone login, token handling, API-key management, subscription/order/payment flows, or QR-code generation unless those functions are explicitly disclosed and required. Bundling account/payment and credential operations into a different business function significantly expands attack surface and can expose users to credential misuse, unauthorized charges, or covert account actions.

Content

No source excerpt is available for this finding.

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
证码后:`python scripts/onboarding.py login <phone> <code>`(workbuddy 宿主加 `--channel workbuddy`)
   - 拿到 `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

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file's implemented behavior is materially different from the declared skill purpose: instead of Shopee Shop Category API forwarding, it performs LinkFox onboarding, login, API-key issuance, plan browsing, ordering, and payment QR generation. This kind of capability mismatch is dangerous because it can trick users or the host platform into granting execution to a skill that harvests credentials and initiates commercial flows unrelated to the advertised functionality.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Embedding order creation, payment URL handling, and QR code rendering inside a Shopee category-management skill introduces unjustified billing capability. This enables unexpected payment initiation and could be used to socially engineer users into paying for unrelated services under the guise of routine store-management actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code logs users in via SMS, exchanges tokens, fetches team metadata, and generates API tokens even though the skill is advertised for Shopee category management. That creates an unnecessary credential collection and token minting surface that can be abused to obtain persistent access to LinkFox accounts without users expecting such account-level operations from this skill.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises capabilities that imply shell, network, environment-variable access, and file writes, but it does not declare any explicit tool scope or permission boundaries. In an agent environment, this increases the chance of over-privileged execution and makes it harder to constrain what the skill may do if invoked unexpectedly or modified later.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger condition is intentionally broad enough to activate even when the user does not explicitly ask for category operations, which raises the risk of accidental invocation. In an agent system with network and file-write capabilities, overbroad triggering can cause unintended API calls, local persistence, or prerequisite checks against the wrong task context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill states that full API responses are automatically persisted to disk, but it does not require explicit user warning or consent for local retention. Because Shopee/store API responses can contain operational, catalog, or account-linked data, silent persistence increases privacy and data-handling risk beyond the immediate interaction.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the agent to always write complete API responses into session-scoped local files, creating durable storage of potentially sensitive shop, category, and item data. Persistent local copies increase exposure through later reuse, unintended sharing, weak workspace permissions, or inclusion in subsequent agent context.

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 45)May include surrounding context.

md
---

## curl 示例

请求地址从环境变量 `${LINKFOX_TOOL_GATEWAY}` 读取(默认 `https://tool-gateway.linkfox.com`)。认证从 `LINKFOX_AGENT_API_KEY` 或 `LINKFOXAGENT_API_KEY` 任一环境变量读取(如未配置 按 SKILL.md 的 **## 解决认证和积分问题** 处理)。

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation exposes a write-capable API that creates shop categories on a remote Shopee store and explicitly encourages passing the full request body, but it does not warn that this action mutates production store data. In an agent-skill context, missing mutation warnings increases the risk of unintended or overly broad execution, causing unauthorized or accidental store changes when a user request is ambiguous.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file documents an API whose stated purpose is to 'Remove items from shop category' and calls a delete_item_list endpoint, but it does not include any warning about the operation affecting user/shop data. For markdown files, destructive behaviors that may affect data or system integrity should be disclosed to the user.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instructions explicitly tell the operator to solicit a user's phone number and pass it into a registration/login script, but provide no privacy notice, consent language, retention guidance, or warning not to log/share the number and OTP. This creates a real privacy and social-engineering risk because operators may collect sensitive contact data and verification codes in chat or tooling without clear safeguards.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The billing flow directs the operator to create purchase orders and display payment URLs or QR codes, but it does not require an explicit confirmation that a paid transaction is about to be initiated. In an agent workflow, this can lead to unintended charges, phishing-like user experiences, or pressure to complete payment without transparent notice.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

For a skill whose stated purpose is handling Shopee Shop Category API calls, spawning a subprocess to run another script is not an obvious or necessary capability. This introduces process-execution behavior unrelated to category CRUD/proxying and broadens operational risk beyond the manifest's described function.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/_shopee_shop_category_common.py (reported line 41)May include surrounding context.

python
print(f"DEPENDENCY_MISSING: {json.dumps(payload, ensure_ascii=False)}", file=sys.stderr)
        sys.exit(DEPENDENCY_EXIT_CODE)
    try:
        result = subprocess.run(
            [sys.executable, str(checker)],
            capture_output=True,
            text=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The helper reads an API key from environment variables and sends it in an Authorization header while also POSTing caller-supplied parameters to remote endpoints. Although network access is part of the helper's function, there is no user-facing disclosure in this code path indicating that request contents and credentials will be transmitted to an external service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

emit_result() serializes and writes full API responses to local disk under a predictable workspace hierarchy. Because this skill handles store tokens, shop identifiers, category contents, and potentially proxied Shopee API output, the persisted files may contain sensitive business data or credentials that outlive the request and become accessible to other local users, logs, backups, or later processes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The helper writes complete response payloads to disk without prior user warning or consent, which can expose sensitive API output beyond the active execution context. In the context of an ecommerce management skill, persisted responses may include inventory/category mappings, identifiers, operational metadata, or other confidential business data that should not be retained by default.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring openly describes an account onboarding CLI that contradicts the manifest's statement that this skill forwards Shopee Shop Category APIs. This discrepancy is a strong indicator of deceptive packaging, increasing the likelihood that users or reviewers are being misled about what the code actually does.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The login command emits the API key directly to stdout JSON, which is commonly captured by calling agents, logs, terminals, shell history wrappers, or orchestration systems. Exposing long-lived credentials this way increases the chance of accidental disclosure and unauthorized reuse, especially in an ecosystem where tool outputs may be observed by multiple components.

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 196)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 = ""