Back to skill

Security audit

Shopee-店铺健康

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Shopee account-health purpose, but it handles API keys, SMS login, billing orders, and plaintext saved account data with weak scoping and disclosure.

Install only if you trust LinkFox with Shopee account-health data and are comfortable with the skill handling API keys, phone/SMS login, and unpaid order/payment flows. Avoid custom gateway environment variables unless you control the endpoint, do not paste OTPs or API keys into shared logs, rotate any exposed key, and review saved linkfox response files because they may contain sensitive store data.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_shopee_account_health_common.py:18
Finding

Credential Exfiltration Through an Environment-Controlled Gateway

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", "SESSION_ID": os.environ.get("SESSION_ID", ""), "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: return json.loads(response.read().decode("utf-8")) ``` ### Technical Analysis Every Account Health request places the LinkFox API key in the `Authorization` header. The destination is derived from `LINKFOX_TOOL_GATEWAY` or `SHOPEE_API_BASE_URL`, both of which can completely replace the trusted default host. No validation requires HTTPS, checks the destination against an approved hostname, or asks the user to confirm that credentials will be disclosed to a non-default service. Consequently, an environment modification can redirect the API key, session metadata, shop or merchant identifier, and API request parameters to an arbitrary endpoint. The Account Health functionality legitimately requires network access and authentication, but allowing unrestricted redirection o ...[truncated 1291 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_shopee_account_health_common.py:183
Finding

Plaintext Response Persistence With Session-ID Path Traversal and Undocumented Temporary-Directory Fallback

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 ``` ```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): """落盘完整响应到 linkfox///data/-.json;大响应只打印摘要。无缓存。""" 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, exi ...[truncated 2711 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:478
Finding

Newly Issued API Key Is Printed to Standard Output and Recommended for Plaintext Shell-Profile 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), } ``` ```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 onboarding documentation further recommends persistent plaintext shell configuration: ```text Wi ...[truncated 2168 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 (35)

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

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The request destination and multiple outbound headers are derived from environment variables, including the base URL and session/application metadata, and the Authorization API key is sent to whatever endpoint API_BASE_URL resolves to. If an attacker can influence environment variables or runtime configuration, they can redirect requests to an attacker-controlled server and exfiltrate credentials and identifiers.

Content

Scanner excerpt · scripts/_shopee_account_health_common.py (reported line 88)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The code builds destination URLs from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys via requests.post. If an attacker can influence these environment variables, the CLI can be redirected to an attacker-controlled endpoint, causing credential exfiltration and account compromise.

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
92% confidence
Finding

The gateway request path uses a URL derived from environment variables and attaches the LinkFox API key in the Authorization header before calling urlopen. An attacker who controls the environment can redirect these authenticated requests to a malicious server and capture the API key and account data.

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
98% confidence
Finding

If the underlying behavior includes SMS login, token retrieval, API key generation, subscription ordering, and payment flows while claiming only account-health queries, the skill crosses into credential handling and financial operations without transparent disclosure. That creates significant risk of secret exposure, account misuse, unintended purchases, and user deception in a context where only read-oriented shop health data was expected.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the underlying behavior includes SMS login, token retrieval, API key generation, subscription ordering, and payment flows while claiming only account-health queries, the skill crosses into credential handling and financial operations without transparent disclosure. That creates significant risk of secret exposure, account misuse, unintended purchases, and user deception in a context where only read-oriented shop health data was expected.

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
示 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

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements LinkFox onboarding, login, token generation, subscription purchase, and payment operations, which are unrelated to the declared Shopee Account Health read/query scope. Such scope mismatch is dangerous because users or orchestrators may grant trust and permissions appropriate for a read-only Shopee skill while the code performs unrelated sensitive account and billing actions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The order creation and payment QR flow introduces real billing capability into a skill advertised as a Shopee account-health query tool. In context, this is especially dangerous because it expands from passive data retrieval to financial transactions, creating risk of unauthorized charges or deceptive purchase flows.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The SMS login, access-token handling, team discovery, and API-token generation functionality is unjustified for a Shopee account-health query skill and materially increases the skill's power. This can expose highly sensitive credentials and enable account takeover or unauthorized API access if misused, especially because users may not expect such onboarding behavior from the stated skill purpose.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill advertises shell, network, environment-variable access, and file writes, but does not declare any explicit tool scope or allowed-tools boundary. In an agent environment, this weakens least-privilege controls and can allow broader execution than reviewers or users would expect, especially because the skill also instructs writing responses to disk and depends on environment secrets.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

An overly broad trigger can cause the skill to activate for loosely related Shopee topics, increasing the chance that shell/network/file-writing behavior runs when the user did not intend to invoke this integration. In an agent setting, unnecessary invocation expands attack surface and may expose store identifiers, local files, or API-backed data more often than necessary.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The example explicitly directs authenticated requests and account-health data to an external endpoint, which establishes a clear external transmission path for sensitive commercial and account-status information. In this skill context, the transmitted data can include store performance, enforcement history, and order issues, so misuse, interception in downstream systems, or over-collection by the proxy could expose sensitive business information.

Content

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


curl 示例

bash
curl -X POST https://tool-gateway.linkfox.com/shopee/developerProxy \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The document provides a ready-to-use authenticated curl example that sends an API key, access token, and shop identifier to an external gateway, but it does not warn about the sensitivity of those credentials or the account data being transmitted. In a skill that handles store health, penalty, punishment, listing issue, and late-order data, this increases the chance that operators will copy real secrets into requests without understanding the exposure and trust boundary.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file’s instructional content is written entirely in Chinese, including the title, parameter descriptions, and usage notes, with no indication that language selection is optional or that the skill is intended only for a Chinese-speaking or region-specific audience. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instructions explicitly tell the agent to ask for a user's phone number and use it to drive a registration/login flow, but they provide no requirement to obtain informed consent, minimize retention, or warn about handling sensitive personal data and one-time codes. In an agent setting, this can normalize unsafe collection of PII and authentication material, increasing the risk of privacy violations, account takeover abuse, or accidental disclosure through logs/transcripts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The billing workflow instructs the agent to create payment orders and display payment artifacts such as PNGs, pay URLs, or ASCII QR codes without requiring a clear warning, confirmation step, or provenance check. In practice this can lead users to follow payment links or scan codes without understanding they are leaving the trusted flow, making phishing, misbilling, or payment redirection more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code performs a network call through developerProxy and may transmit identifiers, query parameters, and POST bodies including account-health-related data. While the module docstring states the purpose at a high level, there is no confirmation prompt, user-facing log/print, or explicit warning in this file that request data will be sent to an external service.

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_account_health_common.py (reported line 37)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
92% confidence
Finding

The code forwards SESSION_ID, MESSAGE_ID, MODE_ID, and APP_NAME from the environment on every API request without any minimization or disclosure in this file. These identifiers may enable tracking, correlation, or unintended sharing of internal context with upstream services, especially when combined with the configurable outbound endpoint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module persistently writes full API responses to local disk under predictable directories, even though the stated purpose is API querying rather than local retention. Account-health responses may contain sensitive operational, penalty, and shop-identifying data, so unnecessary persistence increases exposure through local compromise, accidental disclosure, or cross-session data leakage.

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

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language messages and request payload hard-code domestic 11-digit phone numbers and area code +86, effectively constraining the skill to Chinese phone numbers. There is no visible opt-in or justification in the user-facing text that this is a China-specific flow, which can violate language/locale policy when a fixed locale is imposed silently.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code performs multiple network calls involving a phone number, SMS code, access token, refresh token, and generated API key, but the only disclosure is a generic module docstring saying environment-variable instructions are shown elsewhere. Within this code path there is no confirmation prompt or explicit user-facing warning that sensitive account data and credentials will be sent to remote LinkFox services and that an API key will be generated/retrieved.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The file presents core invocation and usage instructions in a fixed Chinese/English mixed form, but does not state whether the user can choose language or locale. Under the language/locale policy rule, forcing a specific presentation language without opt-in can be a policy concern.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation states at L014 that using the tool '会消耗算力' and requires the user to be warned before additional retrieval attempts, but later states at L098 '不消耗算力'. These statements cannot both be true and create intent ambiguity about resource usage and when the user should be cautioned.

Content

No source excerpt is available for this finding.