Back to skill

Security audit

出海匠 TikTok 达人情报

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed LinkFox creator-research client, but it also includes account login, API-key generation, billing order creation, redirectable authenticated endpoints, and unsafe local path handling that warrant Review before installation.

Install only if you trust LinkFox with your API key, session metadata, creator-query results, and any account/billing actions. Avoid setting custom LINKFOX_* endpoint variables unless you control and trust the destination, use a dedicated low-privilege API key when possible, do not paste keys into shared logs or synced dotfiles, and review any payment order before scanning or opening a QR code.

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/chuhaijiang_creator_search.py:29
Finding
Redirectable API Endpoints Can Exfiltrate Authentication Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/chuhaijiang_creator_search.py:29-31, 139-174`; identical behavior exists in the other seven `scripts/chuhaijiang_creator_*.py` files. Related endpoint overrides occur in `scripts/onboarding.py:69-85, 189-221, 399-459`. **Vulnerability Type**: Unrestricted credential transmission to environment-controlled endpoints **Risk Level**: High ### Vulnerable Code ```python def get_api_base() -> str: """Gateway base address: environment override, then production default.""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") def get_api_key(): key = (os.environ.get("LINKFOX_AGENT_API_KEY") or os.environ.get("LINKFOXAGENT_API_KEY")) if not key: sys.exit(1) return key 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: raw = response.read().decode("utf-8") try: return json.loads(raw) except json.JSONDecodeError: return {"error": "Invalid JSON response", "details": raw[:500]} except HTTPError as e: _LAST_CALL_WAS_HTTP_ERROR = True body = e.read().decode("utf-8", errors="replace") if e.fp else "" try: return json.loads(body) if body else { "error": f"HTTP { ...[truncated 2929 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove production endpoint overrides unless they are essential for a documented development mode. 2. Require `https` for every configured endpoint and reject all other schemes. 3. Parse endpoints with `urllib.parse.urlsplit` and enforce an explicit allowlist such as: - `tool-gateway.linkfox.com` - `api.linkfox.com` - `agent-api.linkfox.com` 4. Reject URLs containing user information, fragments, unexpected ports, malformed hosts, or IP-literal destinations. 5. Disable automatic redirects or validate every redirect destination against the same allowlist before forwarding credentials. 6. Separate development credentials from production credentials. Never send production bearer tokens to a development override. 7. Add tests proving that HTTP URLs, lookalike domains, subdomain confusion, user-information tricks, and redirects to untrusted hosts are rejected. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/chuhaijiang_creator_search.py:156
Finding
Unnecessary Agent and Session Metadata Is Forwarded to the Gateway<![CDATA[ ## Vulnerability Details **File Location**: All eight `scripts/chuhaijiang_creator_*.py` files at `156-174`; `scripts/onboarding.py:231-247` **Vulnerability Type**: Excessive disclosure of execution-context metadata **Risk Level**: Medium ### Vulnerable Code ```python 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", ) with urlopen(req, timeout=150) as response: raw = response.read().decode("utf-8") return json.loads(raw) ``` The onboarding gateway repeats the behavior: ```python def _gateway(method: str, path: str, body: Optional[dict] = None) -> dict: url = f"{_agent_base()}{path}" body_bytes = json.dumps(body or {}).encode() if method == "POST" else None headers = { "Authorization": _api_key(), "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", ""), } if method == "POST": headers["Content-Type"] = "application/json" req = Request(url, method=method, data=body_bytes, headers=headers) with urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode()) ``` ### Technical Analysis The creator endpoints require request parameters and an authorization credential. The reviewed code also for ...[truncated 1558 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `MESSAGE_ID`, `MODE_ID`, and `APP_NAME` unless the server contract demonstrably requires each field. 2. Make nonessential telemetry explicitly opt-in rather than enabled by default. 3. Use a short-lived, pseudonymous request identifier instead of host-provided session or message identifiers. 4. Document the purpose, retention period, access controls, and privacy implications of every transmitted metadata field. 5. Never forward these values to an endpoint that has not passed strict HTTPS and hostname validation. 6. Add integration tests confirming that creator requests contain only the minimum required headers. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/chuhaijiang_creator_search.py:38
Finding
Unsanitized SESSION_ID Enables Path Traversal and Arbitrary Writable-Path Output<![CDATA[ ## Vulnerability Details **File Location**: All eight `scripts/chuhaijiang_creator_*.py` files at `38-45, 88-95, 341-366`; related behavior in `scripts/onboarding.py:153-159` **Vulnerability Type**: Path traversal through an environment-controlled directory component **Risk Level**: High ### Vulnerable Code ```python def _session_id(ts: float) -> str: """Prefer SESSION_ID; otherwise generate a process-stable identifier.""" 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]: 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 selected directory is subsequently used for persistent files: ```python def resolve_data_path(slug: str, ts: float, ext: str = "json") -> str: _, session_dir = _ensure_session(ts) data_dir = os.path.join(session_dir, "data") os.makedirs(data_dir, exist_ok=True) out = os.path.join( data_dir, f"{slug}-{int(ts * 1_000_000)}.{ext}", ) _update_meta( session_dir, skill=slug, file_rel=os.path.relpath(out, session_dir), ts=ts, ) return out ``` ```python out_path = _resolve_output_path(ts) with open(out_path, "w", encoding="utf-8") as f: f.write(serialized) ``` ### Technical Analysis `SESSION_ID` is accepted without validation and passed directly to `os.path.join`. An absolute value causes earlier path components to be discarded on applicable platforms. Relative values containing `..` can esca ...[truncated 1746 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict session IDs to a conservative format, for example: ```python if not re.fullmatch(r"[A-Za-z0-9_-]{1,64}", sid): raise ValueError("Invalid SESSION_ID") ``` 2. Reject absolute paths, path separators, `.` components, and `..` components. 3. Resolve the root and candidate paths with `os.path.realpath`. 4. Verify containment before every write: ```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("Session path escapes output root") ``` 5. Open predictable metadata files safely and avoid following symbolic links where the platform permits. 6. Use restrictive directory and file permissions for locally cached API data. 7. Apply the same validation to `scripts/onboarding.py`. 8. Add tests for absolute paths, nested traversal, mixed separators, symbolic-link escapes, long identifiers, and platform-specific path syntax. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:475
Finding
Onboarding Exposes Bearer API Keys Through Standard Output and Shell Startup Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboarding.py:475-512`; `references/onboarding.md:9-15` **Vulnerability Type**: Plaintext credential disclosure and insecure persistent credential storage **Risk Level**: Medium ### Vulnerable Code ```python def login_and_get_key(phone: str, code: str, channel: str) -> dict: masked = _mask_phone(phone) if not re.fullmatch(r"\d{11}", phone): return {"error": f"login: invalid phone format: {phone}", "phone": masked} if not re.fullmatch(r"\d{4,8}", code): return {"error": f"login: invalid verification-code format: {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']}", 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), } 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 obtained", file=sys.stderr) return 0 return 1 ``` The setup reference recomm ...[truncated 1823 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not emit the complete API key in ordinary JSON output. 2. Return only a redacted fingerprint, such as the first and last four characters, plus a success indicator. 3. Provide a dedicated setup mode that writes the secret directly to an approved credential store. 4. Prefer the operating system's secure credential manager or a secrets-management service over shell startup files. 5. If an environment file is unavoidable, create it without placing the key on the command line and enforce owner-only permissions. 6. Warn users that tool output, shell history, screenshots, and dotfile synchronization can expose the key. 7. Ensure application logs redact fields named `api_key`, `authorization`, `access_token`, `refresh_token`, and equivalent aliases. 8. Support key revocation and rotation, and advise rotation after suspected log exposure. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/onboarding.py:38
Finding
Onboarding Recommends Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboarding.py:38-42, 162-169, 183-186` **Vulnerability Type**: Unpinned runtime dependencies **Risk Level**: Low ### Vulnerable Code ```python try: import requests except ImportError: requests = None ``` ```python def render_qr(content: str, out_dir: str) -> dict: try: import qrcode except ImportError: return { "png_path": None, "ascii_qr": None, "error": "Missing qrcode dependency; install qrcode and pillow", } ``` ```python def _require_requests() -> None: if requests is None: raise RuntimeError( "Missing requests dependency; install requests" ) ``` The original runtime messages instruct users to install `requests`, `qrcode`, and `pillow` without version or hash constraints. ### Technical Analysis The package names are common and no typosquatting or deliberately malicious package was identified. Nevertheless, installing dependencies by mutable name without a version lock or integrity hash makes the runtime non-reproducible. A future compromised release, malicious package-index response, dependency substitution, or incompatible update could execute code during installation or import. The Skill does not include a lockfile or hash-verified requirements manifest in the reviewed project. ### Attack Path 1. The user invokes an onboarding command on a system missing one of the optional packages. 2. The script instructs the user to install packages without version or hash restrictions. 3. The package installer resolves the currently available release from its configured index. 4. A compromised package release, compromised index, or maliciously configured package source supplies attacker-controlled code. 5. Installation hooks or subsequent imports execute that code with the user's operating-system privileges. ### Impact Assessment If the dependency supply chain is compromised, arbitrary co ...[truncated 408 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a reviewed dependency manifest with exact versions. 2. Include cryptographic hashes and install with hash verification. 3. Document the expected canonical package index and reject untrusted extra indexes in deployment guidance. 4. Install dependencies in an isolated virtual environment rather than the user's global Python environment. 5. Add automated vulnerability and provenance scanning for locked dependency versions. 6. Review and update dependencies through a controlled release process. 7. Consider replacing optional dependencies with standard-library functionality where practical. ]]>
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 (45)

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
Confidence
94% confidence
Finding
The script allows the destination base URL to be overridden by the LINKFOX_TOOL_GATEWAY environment variable and sends the API key plus session-related identifiers in request headers to that URL. If an attacker can influence the environment, they can redirect requests to an attacker-controlled endpoint and exfiltrate credentials and request data, making this a real SSRF/credential-leakage risk.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
Confidence
94% confidence
Finding
The request sent to the gateway includes multiple HTTP headers populated directly from environment variables, including SESSION_ID, MESSAGE_ID, MODE_ID, and APP_NAME, and the destination base URL is also overrideable via LINKFOX_TOOL_GATEWAY. Because these values are attacker-controllable in many execution environments, the script can be induced to exfiltrate workflow metadata and API credentials to an arbitrary endpoint or enable header abuse against the upstream service. In this skill context, the script is explicitly designed to call an external API with sensitive authorization, which makes environment-to-network taint especially dangerous.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
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 167, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
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 167, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
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 167, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
Confidence
96% confidence
Finding
The script copies multiple environment variables directly into outbound HTTP headers, including SESSION_ID, MESSAGE_ID, MODE_ID, and APP_NAME, and also allows the destination base URL to be overridden via LINKFOX_TOOL_GATEWAY. In an agent or multi-tenant runtime where environment variables may be influenced by upstream context, this creates a tainted-data-to-network sink that can leak sensitive execution metadata or send it to an attacker-controlled endpoint, especially because the Authorization key is included on the same request.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
Confidence
95% confidence
Finding
The request sent via urlopen includes multiple headers sourced directly from environment variables, and the destination base URL is also environment-controlled via LINKFOX_TOOL_GATEWAY. This creates a tainted-flow issue where untrusted runtime metadata and potentially sensitive identifiers are transmitted over the network, and if the gateway is overridden, the API key and session metadata could be exfiltrated to an attacker-controlled endpoint.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            raw = response.read().decode("utf-8")
            try:
                return json.loads(raw)
Confidence
95% confidence
Finding
The script forwards multiple environment-derived values into outbound HTTP headers and allows the base URL to be overridden by LINKFOX_TOOL_GATEWAY. In an agent environment where these variables may be influenced by other components, this can exfiltrate session identifiers, message metadata, and the API key to an attacker-controlled endpoint or unintended service.

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 POST target is derived from environment-controlled base URLs, and this function sends sensitive data including phone numbers, SMS codes, access tokens, refresh tokens, and generated API tokens. In a skill execution environment, an attacker who can influence environment variables can redirect these requests to an attacker-controlled host and exfiltrate credentials or payment-related data.

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
92% confidence
Finding
The gateway request URL is built from environment-controlled base URLs and then invoked with Authorization and session headers via urlopen. If those environment variables are manipulated, API keys and account metadata can be sent to an attacker-controlled endpoint, enabling credential theft and abuse of billing or account operations.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
If the broader skill package actually includes SMS login, token handling, API-key generation, account/team inspection, subscription listing, order creation, QR-code payment generation, and payment-status queries while presenting itself as a public TikTok market research skill, that is a serious description-behavior mismatch. Undisclosed authentication and payment operations materially increase the attack surface and could enable account abuse, token exposure, or unauthorized billing workflows under misleading pretenses.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the broader skill package actually includes SMS login, token handling, API-key generation, account/team inspection, subscription listing, order creation, QR-code payment generation, and payment-status queries while presenting itself as a public TikTok market research skill, that is a serious description-behavior mismatch. Undisclosed authentication and payment operations materially increase the attack surface and could enable account abuse, token exposure, or unauthorized billing workflows under misleading pretenses.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the broader skill package actually includes SMS login, token handling, API-key generation, account/team inspection, subscription listing, order creation, QR-code payment generation, and payment-status queries while presenting itself as a public TikTok market research skill, that is a serious description-behavior mismatch. Undisclosed authentication and payment operations materially increase the attack surface and could enable account abuse, token exposure, or unauthorized billing workflows under misleading pretenses.

Ae1

High
Category
analysis-evasion
Content
Response fields vary by endpoint and optional detail expansion. Read `references/api.md` before parsing nested fields and preserve the runtime types returned by
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Response fields vary by endpoint and optional detail expansion. Read `references/api.md` before parsing nested fields and preserve the runtime types returned by
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Response fields vary by endpoint and optional detail expansion. Read `references/api.md` before parsing nested fields and preserve the runtime types returned by
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Response fields vary by endpoint and optional detail expansion. Read `references/api.md` before parsing nested fields and preserve the runtime types returned by
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Direct Prompt Extraction

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

## Display Rules

1. State the marketplace, filters, ranking window, total count, and current page when available.
2. For creator lists, show identity, audience size, engagement, content volume, commerce metrics, category, and creator ID 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 SMS login, API-key retrieval, subscription listing, order creation, and payment QR generation, which are materially unrelated to a TikTok creator-research skill. That scope mismatch is dangerous because it introduces account, credential, and billing capabilities into a data-analysis skill, expanding the blast radius far beyond the declared purpose.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The skill can create orders and render payment QR codes, which enables real billing actions not justified by the stated research use case. In the context of an agent skill, this is especially risky because a compromised or misleading invocation could trigger unauthorized purchases or social-engineer a user into paying.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs use of environment variables, networked API calls, and mandatory local file writes, but it does not declare any explicit tool scope such as allowed tools or permissions. That gap weakens security boundaries because reviewers and runtime policy layers cannot clearly enforce or audit what the skill is allowed to access.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The file presents core usage and safety-relevant operating instructions in Chinese only for sections such as invocation, output behavior, and authentication/quota handling, while other sections are in English. This imposes a language constraint without explicit user opt-in or a documented locale-specific justification.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
该 markdown 文档标题及整体说明均以中文撰写,没有说明这是仅面向中文用户或特定区域的限定文档,也未提供其他语言选择。根据策略,若技能在自然语言层面强制特定语言而无用户选择或明确正当性,应视为语言/locale 策略风险。

External Transmission

Medium
Category
Data Exfiltration
Content
| 501 | 参数校验失败 | 根据 `errmsg` 修正参数 |
| 其他非 200 | 业务异常 | 回显错误信息,不自动连续重试付费接口 |

## curl 示例

### 达人搜索
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.