Back to skill

Security audit

出海匠 TikTok 店铺情报

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed paid TikTok Shop research integration, but it needs Review because sensitive credentials and login data can be sent to environment-configured hosts and local output paths are not safely constrained.

Install only if you trust LinkFox and the environment running the skill. Do not set LINKFOX_TOOL_GATEWAY, LINKFOX_LOGIN_API_URL, LINKFOX_AGENT_API_URL, or LINKFOX_AGENT_USER_API_URL to non-LinkFox hosts; avoid giving phone numbers or SMS codes through the agent unless you intentionally want account setup; confirm any paid plan/order before scanning a QR code; and expect full API responses plus caches to be saved locally under the workspace linkfox directory.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/chuhaijiang_seller_search.py:37
Finding
Credentials and personal authentication data can be forwarded to unrestricted configurable origins<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/chuhaijiang_seller_search.py:37-39, 62-80` - `scripts/chuhaijiang_seller_detail.py:37-39, 62-80` - `scripts/chuhaijiang_seller_related_creators.py:37-39, 62-80` - `scripts/chuhaijiang_seller_related_products.py:37-39, 62-80` - `scripts/chuhaijiang_seller_related_videos.py:37-39, 62-80` - `scripts/chuhaijiang_seller_rank_most_promoted.py:37-39, 62-80` - `scripts/chuhaijiang_seller_rank_top_selling.py:37-39, 62-80` - `scripts/onboarding.py:71-85, 208-229, 376-418, 451-459` **Vulnerability Type**: Unrestricted credential forwarding to environment-controlled network origins **Risk Level**: High ### Vulnerable Code Representative code shared by the seven seller API scripts: ```python def get_api_base() -> str: """Gateway base URL: LINKFOX_TOOL_GATEWAY takes priority.""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") def get_api_url(): return get_api_base() + API_PATH def call_api(params): global _LAST_CALL_WAS_HTTP_ERROR _LAST_CALL_WAS_HTTP_ERROR = False api_url = get_api_url() api_key = get_api_key() data = json.dumps(params).encode("utf-8") headers = { "Authorization": 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", ""), } req = Request( api_url, data=data, headers=headers, method="POST", ) try: with urlopen(req, timeout=150) as response: return json.loads(response.read().decode("utf-8")) ``` Relevant onboarding origin configuration and credential-header construction: ```python def _agent_base() -> str: return _env_base( "LINKFOX_AGENT_API_URL", ...[truncated 5244 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use hard-coded HTTPS production origins for normal operation: - `https://tool-gateway.linkfox.com` - `https://api.linkfox.com` - `https://agent-api.linkfox.com` 2. If endpoint overrides are required for development, require an explicit development-mode flag that is disabled by default. 3. Parse each override with `urllib.parse.urlsplit` and enforce: - `scheme == "https"` - An exact allowlisted hostname - No username or password component - No query string or fragment - No IP-literal or localhost destination - No non-approved port 4. Apply separate allowlists for gateway, login, and agent-user services. Do not allow one environment variable to redirect credentials intended for another trust domain. 5. Reject invalid configuration before retrieving credentials or constructing authorization headers. 6. Ensure authorization headers are not forwarded to a different origin during redirects. Prefer rejecting redirects for authenticated requests or explicitly validating every redirect target before following it. 7. Keep development credentials isolated from production credentials. Tests using custom endpoints should use non-production tokens with minimal permissions and short expiration periods. 8. Add automated tests proving that HTTP URLs, unapproved hosts, embedded credentials, IP literals, and unauthorized ports are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/chuhaijiang_seller_search.py:247
Finding
Unsanitized SESSION_ID permits filesystem path traversal and writes outside the intended session directory<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/chuhaijiang_seller_search.py:247-265` - `scripts/chuhaijiang_seller_detail.py:247-265` - `scripts/chuhaijiang_seller_related_creators.py:247-265` - `scripts/chuhaijiang_seller_related_products.py:247-265` - `scripts/chuhaijiang_seller_related_videos.py:247-265` - `scripts/chuhaijiang_seller_rank_most_promoted.py:247-265` - `scripts/chuhaijiang_seller_rank_top_selling.py:247-265` - `scripts/onboarding.py:153-159` **Vulnerability Type**: Path traversal through an environment-derived directory name **Risk Level**: Medium ### Vulnerable Code Representative code shared by the seven seller API scripts: ```python def _session_id(ts: float) -> str: """Prefer env SESSION_ID; otherwise generate a stable process-local ID.""" 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"] def _ensure_session(ts: float) -> tuple[str, str]: """Return (linkfox_root, session_dir); session_dir always exists.""" 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 resulting directory is subsequently used for metadata and API-response files: ```python def resolve_data_path(slug: str, ts: float, ext: str = "json") -> str: _, session_dir = _ensure_session(ts) sub = os.path.join(session_dir, "data") os.makedirs(sub, exist_ok=True) out = os.path.join(sub, f"{slug}-{int(ts * 1_000_000)}.{ext}") _update_meta( session_dir, skill=slug, kind="data", file_rel=os.path.relpat ...[truncated 3047 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `SESSION_ID` before using it in a path. Use a strict allowlist such as: ```python _SESSION_ID_RE = re.compile(r"^[A-Za-z0-9_-]{1,64}$") def validated_session_id(value: str) -> str: value = value.strip() if not _SESSION_ID_RE.fullmatch(value): raise ValueError("Invalid SESSION_ID") return value ``` 2. Explicitly reject absolute paths, path separators, `.` and `..`, even if a regular expression is also used. 3. Enforce containment after constructing the path: ```python base = os.path.realpath(os.path.join(root, date_str)) candidate = os.path.realpath(os.path.join(base, sid)) if os.path.commonpath([base, candidate]) != base: raise ValueError("SESSION_ID escapes the session root") ``` 4. Apply the same centralized validation function to all seven business scripts and `scripts/onboarding.py`. 5. Avoid silently normalizing malicious identifiers. Reject them and generate a new random session identifier only when `SESSION_ID` is absent, not when it is present but invalid. 6. Create files using restrictive permissions where practical. API response data and payment artifacts should not be world-readable. 7. Add cross-platform tests covering: - `../` and `..\` traversal - Absolute POSIX paths - Windows drive and UNC paths - Empty, overlong, and special-character identifiers - Symbolic-link and containment edge cases ]]>
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 (42)

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
96% confidence
Finding
The request target is derived from an environment-controlled base URL via LINKFOX_TOOL_GATEWAY and then sent with the Authorization API key and session headers. If an attacker can influence the environment, they can redirect the request to an attacker-controlled host and exfiltrate credentials and request data, which is especially risky because this script blindly trusts the override and performs no allowlisting.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
91% confidence
Finding
The request URL is derived from LINKFOX_TOOL_GATEWAY, an environment variable, and the request also includes sensitive headers such as the API key plus session/app metadata. If an attacker can influence the runtime environment, they can redirect the POST to an attacker-controlled host and exfiltrate credentials and identifiers. In a skill that should only query a fixed vendor API, allowing endpoint override materially increases SSRF and secret-leak risk.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
96% confidence
Finding
The request sends multiple environment-derived values, including the API key and metadata headers, to a network endpoint whose base URL is also controlled by the LINKFOX_TOOL_GATEWAY environment variable. If an attacker can influence the environment, they can redirect requests to an arbitrary host and exfiltrate credentials and session identifiers; in this skill context, that is especially risky because the skill is expected to query public research data, not transmit sensitive local execution metadata to arbitrary destinations.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
95% confidence
Finding
The script builds its destination URL from the environment variable LINKFOX_TOOL_GATEWAY and then sends the API key, session identifiers, and request data to that endpoint via urlopen. Because this network sink is controllable through environment input and there is no allowlist or validation, a poisoned runtime environment can redirect sensitive data to an attacker-controlled server, causing credential and metadata exfiltration.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
96% confidence
Finding
The request target and multiple headers are derived from environment variables, including LINKFOX_TOOL_GATEWAY and session/app identifiers, and are sent directly via urlopen. Because the gateway base URL is overrideable, a compromised or untrusted runtime can redirect requests and exfiltrate the API key, user query parameters, and session metadata to an attacker-controlled endpoint.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        _LAST_CALL_WAS_HTTP_ERROR = True
Confidence
97% confidence
Finding
The request URL is derived from LINKFOX_TOOL_GATEWAY, an environment variable, and the code sends the Authorization API key plus session headers to whatever host that variable points to. In an agent/runtime environment where skills may inherit attacker-influenced environment variables, this enables credential exfiltration and arbitrary outbound POSTs to untrusted infrastructure.

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

Critical
Category
Data Flow
Content
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 = ""
Confidence
93% confidence
Finding
The code builds request destinations from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys to those endpoints. If an attacker can influence environment variables in the skill runtime, they can redirect authentication traffic to attacker-controlled infrastructure and exfiltrate credentials or tokens.

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

Critical
Category
Data Flow
Content
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
Confidence
93% confidence
Finding
The gateway request target is also derived from environment variables and used in urlopen with authentication headers, including the agent API key and request metadata. A malicious runtime configuration could redirect these authenticated requests to an attacker endpoint, leaking secrets and enabling unauthorized actions such as order creation or account queries.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill is presented as a public TikTok Shop market-intelligence tool, but the referenced behavior includes account login, API key issuance, account/team queries, package purchase, order creation, payment QR generation, and payment-status checks. That mismatch is security-significant because users may authorize a benign-seeming research skill without realizing it can interact with billing, identity, and account systems outside the stated purpose.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
python scripts/chuhaijiang_seller_rank_top_selling.py '{"country":"us","date":"20260824","granularity":"daily","pageSize":10}'
```

## Display Rules

1. State the marketplace, filters, current page, total count, and ranking date/granularity used.
2. For store lists, show store name, rating, product count, recent or interval sales/GMV, creator reach, region, and store ID when available.
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The onboarding document directs the agent to handle authentication failures by walking users through account registration, SMS login, API key acquisition, and billing/purchase flows that are unrelated to the skill's declared read-only TikTok Shop research purpose. This expands the skill into credential handling and monetization workflows, increasing phishing, privacy, and unauthorized account/payment interaction risk if the instructions are followed automatically or presented as trusted guidance.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The file explicitly authorizes SMS-based registration/login and paid plan ordering via `scripts/onboarding.py`, which is unjustified for a TikTok Shop analytics skill and teaches the agent to participate in identity verification and commerce flows. That creates a dangerous precedent for collecting sensitive inputs such as phone numbers and one-time codes, and for steering users into transactions outside the expected skill function.

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

High
Category
YARA Match
Content
示 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
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This file implements account onboarding, SMS login, API key acquisition, subscription discovery, order creation, and payment QR generation, which are unrelated to the declared TikTok Shop public-store research purpose. Such scope expansion is dangerous because it introduces credential handling and monetization capabilities that can be abused and are not necessary for the advertised function.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The order and payment functions create purchasable orders and generate payment QR codes despite the skill being described as a market-research integration. In context, hidden or unjustified billing capability increases the risk of unauthorized charges, social engineering, or misuse of the agent environment for purchases unrelated to user intent.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The skill performs SMS login and API token generation for LinkFox accounts, which is not justified by the stated Chuhaijiang store-research role. This greatly expands the trust boundary by collecting authentication factors and minting reusable API credentials, creating a high-value target for abuse or interception.

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill describes capabilities that involve environment variables, local file writes, and network access, but it does not declare any explicit tool scope or allowed-tools restrictions. In an agent setting, missing least-privilege boundaries increases the chance that the skill can access broader capabilities than users expect, especially since it also includes credential handling and persistent storage behavior.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill states that complete API responses are always written to a JSON file under the working directory, but it does not prominently warn users that fetched data will be persisted locally. Even if the source is 'public market intelligence,' responses may still contain session-linked context, expiring signed URLs, or other operational metadata that users did not expect to retain on disk.

Ssd 3

Medium
Confidence
91% confidence
Finding
The skill instructs saving full API responses in a session-linked path inside the project directory for every call. Persisting complete responses by default broadens data exposure, increases retention of unnecessary fields, and can leak marketplace data or signed links to other users, tools, or future tasks that can access the same workspace.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This markdown file presents all operational instructions, warnings, and API usage details only in Chinese. Under the language/locale policy rule, forcing a single language without user opt-in or a documented justification can exclude users and constitutes a natural-language policy violation.

External Transmission

Medium
Category
Data Exfiltration
Content
入口脚本会把 HTTP 错误或业务错误保存并回显,不会缓存失败结果。参数错误不会自动改条件重试。

## curl 示例

```bash
curl -X POST "${LINKFOX_TOOL_GATEWAY}/chuhaijiang/sellers/search" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The instructions tell the user to provide a phone number and later a verification code for script-based registration without any privacy notice, consent language, or guidance on safe handling of personal data. In the context of an agent skill, this can normalize sensitive-data collection for a feature that does not need it, exposing users to privacy misuse or social-engineering risk.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The file-level docstring presents usage and output behavior entirely in Chinese, and the script's summary/help messaging is oriented around that fixed locale. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless the locale constraint is clearly documented and justified, which is not present here.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The script always writes the full API response to persistent storage under the working directory, regardless of whether the data is needed after the call. This creates unnecessary local retention of potentially sensitive business data and increases the risk of cross-task data exposure in shared workspaces or later unintended reuse.

Static analysis

No suspicious patterns detected.