Back to skill

Security audit

出海匠 TikTok 直播带货洞察

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does the advertised TikTok livestream research, but it also handles login, API keys, and payment flows with insufficient endpoint and credential-safety boundaries.

Review this skill before installing. Use it only in an environment where LinkFox endpoint variables are trusted, avoid pasting OTPs or API keys into shared agent transcripts, prefer temporary or secret-manager credential storage over shell-profile exports, and inspect/delete saved response, cache, and payment QR files after use.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/chuhaijiang_live_search.py:39
Finding
Credential Disclosure Through Unrestricted API Endpoint Overrides<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/chuhaijiang_live_search.py:39-80` - `scripts/chuhaijiang_live_detail.py:39-80` - `scripts/chuhaijiang_live_related_products.py:39-80` - `scripts/onboarding.py:78-85, 195-221, 399-418, 451-456` **Vulnerability Type**: Credentials sent to environment-controlled network destinations **Risk Level**: High ### Vulnerable Code The three livestream API scripts contain equivalent implementations: ```python def get_api_base() -> str: """Gateway base address: LINKFOX_TOOL_GATEWAY takes precedence.""" 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")) ``` The onboarding script similarly permits overrides for services receiving login credentials and access tokens: ```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("LIN ...[truncated 2658 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Allow credential-bearing production requests only to an explicit hostname allowlist, such as the documented LinkFox service domains. 2. Require the resolved URL scheme to be `https`. 3. Reject URLs containing user information, unexpected ports, fragments, or deceptive hostname suffixes. 4. Resolve and validate each final request URL after joining the base URL and path. 5. Disable endpoint overrides by default. If overrides are required for development, require an explicit development-mode flag and test-only credentials. 6. Never attach production authorization headers when the destination is not an approved origin. 7. Minimize telemetry headers. Send `SESSION_ID`, `MESSAGE_ID`, `MODE_ID`, and `APP_NAME` only where they are operationally required. 8. Add tests proving that HTTP destinations, subdomain-confusion values, and unapproved domains are rejected before any network request occurs. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/chuhaijiang_live_search.py:247
Finding
Arbitrary Filesystem Write Location Through Unsanitized SESSION_ID<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/chuhaijiang_live_search.py:247-263` - `scripts/chuhaijiang_live_detail.py:247-263` - `scripts/chuhaijiang_live_related_products.py:247-263` - `scripts/onboarding.py:155-159` **Vulnerability Type**: Path traversal in an environment-derived directory component **Risk Level**: Medium ### Vulnerable Code The three livestream scripts use the environment value directly as a path component: ```python def _session_id(ts: float) -> str: """Prefer env SESSION_ID; otherwise generate an 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 onboarding script has the same trust issue: ```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 trusted despite being read from the process environment. Values containing `..` components can escape the intended date and `linkfox` directories. On systems where an absolute final component overrides preceding components, ...[truncated 1531 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `SESSION_ID` against a strict allowlist such as `[A-Za-z0-9_-]{1,128}`. 2. Reject empty, absolute, dotted, separator-containing, or control-character-containing values. 3. Resolve both the root and candidate directory with `os.path.realpath`. 4. Confirm containment before writing: ```python root_real = os.path.realpath(root) candidate = os.path.realpath(os.path.join(root_real, date_str, sid)) if os.path.commonpath([root_real, candidate]) != root_real: raise ValueError("Invalid SESSION_ID") ``` 5. Use the sanitized ID consistently for local paths and metadata. 6. Consider keeping external session identifiers only in metadata and generating a separate random local directory name. 7. Add regression tests for `../`, absolute paths, mixed separators, Unicode separators, and symlink-based escape attempts. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:481
Finding
Full API Key Exposed Through Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboarding.py:481-485, 504-513` **Vulnerability Type**: Plaintext credential disclosure through command output **Risk Level**: Medium ### Vulnerable Code The successful onboarding result includes the complete API key: ```python 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 result is then serialized directly to standard output: ```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} Successfully obtained API key " f"(source: {r['source']})", file=sys.stderr, ) return 0 return 1 ``` ### Technical Analysis The API key is a reusable bearer credential. Printing it as ordinary JSON makes it available to every component that captures stdout. In an AI-agent workflow, command output may be retained in tool-call records, model context, terminal scrollback, CI logs, observability systems, or shared session transcripts. Although the user needs a secure method to configure the key, returning it in general command output is not a least-disclosure mechanism. The project's documentation also instructs the surrounding Agent to forward the key to the user, increasing the chance that it enters conversational history. ### Attack Path 1. A user completes SMS verification and invokes the onboarding `login` command. 2. The script obtains or generates an API key. 3. `_cmd_login` passes the complete result to `_emit`. 4. `_emit` prints the plaintext key to stdout. 5. A terminal logger, Agent tool tr ...[truncated 681 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not include the complete API key in normal stdout JSON. 2. Store the key directly through a protected secret-management interface or write it to a user-owned file with restrictive permissions after explicit approval. 3. Return only a masked identifier or fingerprint, for example the first and last four characters. 4. If one-time display is unavoidable, require a dedicated explicit option, warn the user, and write through a channel excluded from Agent transcripts and routine logs. 5. Add output-redaction controls that recursively redact fields named `api_key`, `apiKey`, `token`, `access_token`, and `refresh_token`. 6. Document immediate key rotation procedures and ensure generated keys can be revoked. 7. Avoid instructing an Agent to repeat the full key in conversational output. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:162
Finding
Unpinned Runtime Dependency Installation Instructions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboarding.py:162-166, 182-185` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code The script directs users to install packages without fixed versions or integrity hashes: ```python def render_qr(content: str, out_dir: str) -> dict: try: import qrcode except ImportError: err = ( "Missing qrcode dependency; run: " "pip install qrcode pillow" ) print(f"{TAG} render_qr: {err}", file=sys.stderr) return { "png_path": None, "ascii_qr": None, "error": err, } ``` ```python def _require_requests() -> None: if requests is None: raise RuntimeError( "Missing requests dependency; run: pip install requests" ) ``` ### Technical Analysis The installation commands resolve mutable package versions from the user's configured package index at installation time. There is no lockfile, exact version constraint, hash verification, or trusted-index requirement. This does not prove that the named packages are malicious. The weakness is that the Skill delegates code selection to an unpinned external package source after review. Package installation may execute build hooks or install a compromised future release, making the effective dependency set non-reproducible. ### Attack Path 1. The runtime lacks `requests`, `qrcode`, or `pillow`. 2. The script displays the suggested `pip install` command. 3. The user or Agent executes that command. 4. `pip` selects the current versions from the configured index or mirror. 5. A compromised index, malicious mirror, dependency compromise, or unsafe future release supplies attacker-controlled package code. 6. Installation hooks or subsequent imports execute that code with the privileges of the user running the Skill. ### Impact Assessment Malicious dependency code would execu ...[truncated 414 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Provide a reviewed dependency manifest with exact versions. 2. Use a hash-locked requirements file, for example: ```text requests==<reviewed-version> --hash=sha256:<reviewed-hash> qrcode==<reviewed-version> --hash=sha256:<reviewed-hash> Pillow==<reviewed-version> --hash=sha256:<reviewed-hash> ``` 3. Install with `pip install --require-hashes -r requirements.txt`. 4. Use a trusted package index or an internally controlled artifact repository. 5. Install dependencies in an isolated virtual environment rather than the user's global environment. 6. Perform software-composition analysis and routinely review dependency updates before changing pinned versions. 7. Avoid runtime instructions that cause an Agent to install arbitrary current package versions automatically. ]]>
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 (24)

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
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
95% confidence
Finding
The request sent to urlopen includes multiple headers populated directly from environment variables, including SESSION_ID, MESSAGE_ID, MODE_ID, APP_NAME, and potentially the gateway base URL via LINKFOX_TOOL_GATEWAY. Because the destination can also be overridden by environment configuration, a malicious or compromised runtime can redirect the request to an attacker-controlled host and exfiltrate sensitive identifiers and the API key in the Authorization header. In an agent/tooling environment where env vars are shared across components, this makes the tainted flow materially risky rather than merely theoretical.

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 allows API base URLs to be overridden via environment variables and then uses those values to send requests that may include SMS login data, access tokens, refresh tokens, API keys, and browser-like headers. In an agent/runtime environment where env vars can be influenced by a wrapper, deployment config, or another component, this becomes a credential exfiltration and SSRF-style sink.

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
94% confidence
Finding
The gateway request path constructs a Request from environment-derived base URLs and forwards the agent API key and session metadata in headers before calling urlopen. If the environment is tampered with, the skill can be redirected to an attacker-controlled host, leaking credentials and enabling unauthorized billing-related operations or internal network access attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose is read-only TikTok livestream research, but the skill also directs the agent into authentication, account, API-key, and payment/order workflows via onboarding scripts and LinkFox login/user/payment interfaces. This mismatch is dangerous because it hides materially more sensitive behavior than users would expect, enabling credential handling and paid transactions under the cover of a benign analytics skill.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
These examples were production-validated with non-empty semantic results on 2026-08-29. Public-market IDs are volatile; use a fresh search result if an example stops resolving.

## Display Rules

1. State the requested marketplace, filters, sort, page, page size, and returned total.
2. For search, show title, room ID/link, host, time range, audience, products, units sold, GMV, GPM, and OPM when returned.
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

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
99% confidence
Finding
This file implements account onboarding, SMS verification, API-key issuance, package listing, ordering, and payment QR generation, which is materially unrelated to a Chuhaijiang TikTok live research skill. Such capability expansion is dangerous because it adds credential collection and monetization flows that can trick users into performing actions outside the declared skill purpose.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The code creates orders, queries billing status, and renders payment QR codes despite the skill being described as a market research integration. In context, these payment capabilities are unjustified and increase the risk of deceptive purchases, unauthorized charges, or social engineering through the agent interface.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill advertises and appears to use environment access, file writes, and network calls, but it does not declare any explicit tool scope or permissions boundary. That increases the chance an agent will invoke broader capabilities than a reviewer or user expects, especially because the document also instructs writing responses to disk and handling auth/onboarding flows.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The document title and all operational instructions are written in Chinese, which imposes a specific language on users. The file does not state that the skill is region-specific or provide an opt-in or alternative locale, so this appears to violate the language/locale policy rule.

External Transmission

Medium
Category
Data Exfiltration
Content
入口脚本会把 HTTP 错误和网关 JSON 错误作为结构化内容回显,不应出现未处理的 Python 堆栈。

## curl 示例

```bash
curl -X POST "${LINKFOX_TOOL_GATEWAY}/chuhaijiang/lives/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
94% confidence
Finding
The onboarding instructions direct collection and handling of a user's phone number and one-time verification code to register/login via a local script, but provide no privacy notice, minimization guidance, or handling safeguards. This creates avoidable risk of exposing personal data and authentication secrets in chat history, logs, terminals, or agent telemetry, especially because the flow explicitly asks the user to provide sensitive data to the agent-driven process.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The file instructs users to persist an API key in shell startup files or via permanent environment-variable commands without warning that these locations store credentials in plaintext and may be readable by other local users, backups, support tools, or later disclosed during troubleshooting. Sourcing profile files immediately after appending the key also increases the chance of accidental exposure through shell history and copied commands.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script sends user-supplied parameters plus session metadata (SESSION_ID, MESSAGE_ID, MODE_ID, APP_NAME) to a remote service, but the runtime behavior is not clearly disclosed to the operator beyond generic usage text and comments. In a skill context, this can cause unintended transmission of sensitive prompts, identifiers, or research inputs to an external endpoint without meaningful consent or minimization.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script always persists the full API response under the current working directory, which may contain sensitive or regulated data, and does so by default without a clear runtime warning or opt-in. In shared workspaces or agent environments, this increases the chance of unintended local data exposure, later reuse by other tools, or accidental check-in to source control.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The script always writes full API responses plus session metadata into the current project directory, which can retain potentially sensitive commercial research data, identifiers, and activity traces beyond the immediate task. Persisting data by default broadens exposure to other local users, later tooling, commits, backups, or unintended workspace sharing.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code sends the JSON `params` payload plus session-related environment values (`SESSION_ID`, `MESSAGE_ID`, `MODE_ID`, `APP_NAME`) to a remote HTTPS endpoint. Although the module docstring mentions the API path and file-output behavior, it does not clearly warn users that their supplied data and contextual metadata will be transmitted over the network.

External Transmission

Medium
Category
Data Exfiltration
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
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The code forces the login flow to use areaCode '+86' and later restricts payment methods to WeChat and Alipay, indicating a fixed locale-specific experience. There is no natural-language indication in the code that this is optional, user-selectable, or justified as a region-specific skill, which can violate language/locale policy requirements.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill writes a payment QR PNG to a session directory on disk and returns the local file path, but this file provides no explicit warning about persistence, location, or cleanup. On shared hosts or agent workspaces, this can leave sensitive payment artifacts accessible to other users or processes beyond the immediate task.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The on-disk cache stores successful API responses for up to 24 hours under a predictable project-local path, creating additional retention of potentially sensitive query results outside the user's immediate expectation. While not overtly malicious, this increases the attack surface for local disclosure and stale-data reuse.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The top-level docstring presents key usage and behavior information partly in Chinese and partly in English, which imposes a language expectation on users without opt-in. The policy requires avoiding forced language or locale constraints unless the tool offers a choice or clearly documents a justified region-specific limitation.

Static analysis

No suspicious patterns detected.