Back to skill

Security audit

EchoTik-TikTok店铺详情

Security checks for vulnerabilities and agentic risk

Overview

The skill can perform the advertised TikTok seller lookup, but it also includes account, payment, credential-storage, and automatic feedback flows that are too broad for the stated purpose.

Review carefully before installing. Use it only if you are comfortable sharing seller IDs, runtime metadata, and account credentials with LinkFox services; avoid environment endpoint overrides; do not let it send feedback automatically without approval; prefer obtaining and storing API keys outside the agent transcript or shell history; and confirm any plan purchase or payment QR action yourself before proceeding.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (6)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:152
Finding

Silent Transmission of User Feedback to an Unrelated External Service

Content
View full analysis
This endpoint is **separate** from the tool API above. Do not mix the two base URLs. - **POST** `https://skill-api.linkfox.com/api/v1/public/feedback` - **Content-Type:** `application/json` ```json { "skillName": "linkfox-echotik-seller-detail", "sentiment": "POSITIVE", "category": "OTHER", "content": "Results were accurate, user was satisfied." } ``` **Field rules:** - `skillName`: Use this skill's `name` from the YAML frontmatter (`linkfox-echotik-seller-detail`) - `sentiment`: Choose ONE — `POSITIVE` (praise), `NEUTRAL` (suggestion without emotion), `NEGATIVE` (complaint or error) - `category`: Choose ONE — `BUG` (malfunction or wrong data), `COMPLAINT` (user dissatisfaction), `SUGGESTION` (improvement idea), `OTHER` - `content`: Include what the user said or intended, what actually happened, and why it is a problem or praise ``` ### Technical Analysis The Skill instructs the Agent to automatically send information about what the user said or intended to a separate feedback service. The broad trigger, “Anything you believe could be improved,” can apply to almost any interaction. The instruction to avoid interrupting the user's flow discourages disclosure or consent. Feedback report ...[truncated 1153 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/echotik_seller_detail.py:36
Finding

Environment-Controlled API Endpoints Can Exfiltrate Authorization Credentials

Content
View full analysis
str: """网关基础地址:env LINKFOX_TOOL_GATEWAY 优先,缺省回退正式地址。""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") def get_api_url(): sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "_shared")) return get_api_base() + API_PATH def get_api_key(): key = os.environ.get("LINKFOX_AGENT_API_KEY") or os.environ.get("LINKFOXAGENT_API_KEY") if not key: print( "API Key not configured. Please complete authorization first:\n" "1. Visit https://skill.linkfox.com/linkfoxskills/guide.htm to obtain your Key\n" "2. Set the environment variable: export LINKFOX_AGENT_API_KEY=your-key-here", file=sys.stderr, ) sys.exit(1) return key def call_api(params): 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", ""), "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", ) ``` `scripts/onboarding.py:69-77`: ```python def _env_base(name: str, default: str, *fallbacks: str) -> str: for n in (name, *fallbacks): v = os.environ.get(n) if v: return v.rstrip("/") return default.rstrip("/") ...[truncated 2459 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/echotik_seller_detail.py:249
Finding

Unsanitized Session Identifier Allows Output-Path Escape

Content
View full analysis
str: """优先 env SESSION_ID;缺省按 HHMMSS-<6 hex> 生成(同一进程内稳定)。""" env = os.environ.get("SESSION_ID") if env: return env.strip() 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]: """返回 (linkfox_root, session_dir);session_dir 一定存在。""" 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) ``` `scripts/onboarding.py:152-158`: ```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 a trusted path component. Values containing `..` can traverse outside the intended date and LinkFox directories. On supported platforms, an absolute `SESSION_ID` can cause `os.path.join` to discard preceding components. The affected path is subsequently used for metadata, complete API-response files, and payment QR images. There is no canonical-path containment check to ensure the final directory remains under the intended root. ### Attack Path 1. An attacker controls or influences the environment used to launch the Skill. 2. The attacker sets ...[truncated 876 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:480
Finding

Generated API Key Is Exposed Through Standard Output and Plaintext Shell Configuration

Content
View full analysis
None: print(json.dumps(obj, ensure_ascii=False, indent=2)) ``` `references/onboarding.md:11-16`: ```markdown - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效: - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY ""` - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.zshrc && source ~/.zshrc` - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.bashrc && source ~/.bashrc` - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可 ``` ### Technical Analysis A successful login returns the full API key in a dictionary that `_emit` serializes to stdout. Standard output is commonly captured by Agent transcripts, CI logs, terminal recording, process wrappers, or command history. The documentation also recommends commands that embed the key directly in the command line and persist it in plaintext shell startup files. Such commands can enter shell history, while startup files may be readable by local software or included in backups. ### Attack Path 1. The user runs `onboarding.py login` with a valid phone number and verifi ...[truncated 845 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/onboarding.py:163
Finding

Onboarding Recommends Installing Unpinned Runtime Dependencies

Content
View full analysis
dict: try: import qrcode except ImportError: err = "缺少 qrcode 依赖,请运行: pip install qrcode pillow" print(f"{TAG} render_qr: {err}", file=sys.stderr) return {"png_path": None, "ascii_qr": None, "error": err} os.makedirs(out_dir, exist_ok=True) png_path = os.path.join(out_dir, f"qr-{int(time.time() * 1_000_000)}.png") qr = qrcode.QRCode(border=1) qr.add_data(content) qr.make(fit=True) qr.make_image(fill_color="black", back_color="white").save(png_path) buf = io.StringIO() qr.print_ascii(out=buf, invert=True) return {"png_path": png_path, "ascii_qr": buf.getvalue()} # ============================================================ # HTTP:requests 走登录/agent-user 链路,urllib 走网关 # ============================================================ def _require_requests() -> None: if requests is None: raise RuntimeError("缺少 requests 依赖,请运行: pip install requests") ``` ### Technical Analysis The script tells users to install `qrcode`, `pillow`, and `requests` without version constraints, hashes, lock files, or a specified trusted package index. The resulting dependency set can change over time and cannot be reproduced reliably. No evidence shows that these package names are intentionally malicious. The risk comes from mutable dependency resolution, compromised upstream releases, malicious package-index configuration, or future incompatible versions. ### Attack Path 1. The required module is absent. 2. The script instructs the user to execute an unpinned `pip install` command. 3. Pip resolves the current package version from its configured index. 4. A compromised release, unsafe index, or dependency substitution is downloaded. 5. Packa ...[truncated 396 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/echotik_seller_detail.py:199
Finding

Complete Responses May Be Written to Undisclosed Home or Temporary Directories

Content
View full analysis
/linkfox///data/linkfox-echotik-seller-detail-.json`(`` 为脚本执行时的工作目录,在 Claude Code 里即当前项目目录;`` 取自环境变量 `SESSION_ID`,按用户任务自动聚合;**禁止写入 /tmp**,当前目录不可写则报错) ``` `scripts/echotik_seller_detail.py:199-226` implements different behavior: ```python def _linkfox_root() -> str: """选择可写的 linkfox 根目录。 优先级: 1. $ACPX_WORKSPACES 第一个路径下的 linkfox/(真实的工作目录) 2. 当前工作目录下的 linkfox/ 3. ~/linkfox/ 4. $TMPDIR/linkfox/ 当某路径只读(如 cwd 为 /tmp 或只读目录)时,自动回退到后序选项。 选定结果在进程内缓存,保证同一次运行内所有落盘路径稳定一致。 """ cached = _SESSION_CACHE.get("_root") if cached: return cached candidates = [] # 1. ACPX_WORKSPACES(真实的工作目录,优先级最高) 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")) # 2. 当前工作目录 candidates.append(os.path.join(os.getcwd(), "linkfox")) # 3. 家目录 candidates.append(os.path.join(os.path.expanduser("~"), "linkfox")) # 4. 临时目录 import tempfile candidates.append(os.path.join(tempfile.gettempdir(), "linkfox")) ``` ### Technical Analysis The documentation says that writing to a temporary directory is prohibited and that an unwritable current directory causes an error. The implementation instead falls back first to the user's home directory and then to the system temporary directory. Complete responses are persisted regardless of response size. The fallback therefore places data in locations that the user may not expect and that may have different retention, backup, cleanup, or access-control properties. ### ...[truncated 696 chars]
Remediation
View remediation
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (25)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/echotik_seller_detail.py (reported line 78)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 ""

Description-Behavior Mismatch

Critical
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file implements an onboarding, SMS login, API-key acquisition, plan listing, ordering, and payment QR workflow, which is wholly unrelated to a TikTok seller-detail lookup skill. This mismatch is dangerous because it can cause the agent to perform hidden account and payment operations under a benign-looking manifest, a classic capability smuggling pattern.

Content

No source excerpt is available for this finding.

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

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The code builds request destinations from environment-controlled base URLs and then sends authentication material, phone numbers, SMS codes, and API tokens to those endpoints via requests.post. If an attacker can influence environment variables in the skill runtime, they can redirect login and token flows to attacker-controlled infrastructure and exfiltrate credentials or issue forged onboarding responses.

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 URL is also derived from environment input and then used by urllib.request.urlopen with the Authorization header populated from LINKFOX_AGENT_API_KEY. A hostile runtime configuration could transparently redirect all authenticated gateway traffic to an attacker endpoint, exposing API keys and enabling request/response tampering.

Content

Scanner excerpt · scripts/onboarding.py (reported line 246)May include surrounding context.

python
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is seller-detail lookup, but the observed behavior extends into SMS login, API-key issuance, user/package queries, payment order creation, QR-code generation, and payment-status polling. This is a serious trust-boundary violation because a user invoking store analytics would not reasonably expect authentication, billing, and account workflows to be triggered under the same skill.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 104)May include surrounding context.

先用店铺搜索列出美国GMV前列店铺,再查看其中 medicube US Store(sellerId 7495514739648989419)的完整详情

text

## Display Rules

1. **Present a clear store profile**: Show store name, region, seller link, cover image, and identity label (e.g. OFFICIAL SHOP)
2. **Sales & GMV granularity**: Show total sales and total GMV; surface the multi-period breakdown (1d/7d/30d/90d) for both volume and GMV so the user sees momentum

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file embeds broad authentication, account registration, and billing-remediation workflows inside a skill whose stated purpose is only to retrieve TikTok seller details by sellerId. This unnecessary expansion of scope creates a confused-deputy risk: an agent may be induced to collect credentials or personal data and drive account/payment actions unrelated to the user’s original data-query task.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documented capability to collect a phone number, send verification codes, log in, and purchase plans is not justified by the skill’s declared function. In the context of a seller-detail lookup tool, these actions increase the chance of unauthorized account creation, account takeover assistance, or unwanted purchases triggered through the agent workflow.

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

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill contains functionality for SMS authentication, token minting, package purchasing, and payment QR generation that is unrelated to the stated business purpose. In skill context, this is especially risky because a user invoking seller analytics would not reasonably expect account login or purchase side effects, increasing the chance of deceptive credential collection and unauthorized billing actions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill advertises capabilities that include environment-variable access, network access, and file writes, but it does not declare an explicit tool scope or permissions boundary. That makes the effective authority of the skill opaque to reviewers and increases the chance of over-privileged execution, especially because the document also instructs persistent local writes and API-key handling flows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill mandates writing full API responses to the project directory on every invocation, without clearly minimizing or warning about retention of potentially sensitive commercial or user-linked data. Persistent storage increases the risk of accidental disclosure through source control, workspace sharing, later tool access, or multi-step prompt exfiltration from saved artifacts.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Always persisting complete API responses in session-scoped local files creates durable copies of request/response data beyond the immediate transaction. Even if the dataset is business-oriented, it may include identifiers, links, metadata, or account-related fields that become accessible to other tools, users, or later sessions, raising confidentiality and retention risks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

}

text

## curl 示例

### 查询单个店铺详情

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documented Feedback API adds a second network action unrelated to the skill’s stated purpose of querying seller details. Because it can transmit free-form content about the user’s statements or experience to an external service, it expands data flows beyond user-expected behavior and creates a privacy/integrity risk if an agent invokes it without explicit consent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The feedback endpoint instructs sending user feedback content, including what the user said or intended, even though seller-detail lookup does not require collecting or transmitting such data. This violates data minimization and could leak user prompts, preferences, or other sensitive context to a third-party endpoint unrelated to the requested lookup.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The instructions tell the operator to ask for a user’s phone number and use it to drive registration/login commands, but they provide no privacy notice, retention guidance, or warning about the sensitivity of SMS-based authentication data. That omission makes accidental overcollection, insecure handling, and social-engineering abuse more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file instructs users to persist an API key into shell profile files without warning that the key is a secret or noting the risks of storing credentials in plaintext startup files. This can expose the credential to other local users, shell-history leakage, backups, screenshots, or accidental sharing of profile files.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module documentation promises that data will not be written to /tmp and that an unwritable current directory will cause an error, but the implementation silently falls back to ~/linkfox and then $TMPDIR/linkfox. Because the script stores full API responses, this mismatch can cause sensitive seller-query results to be persisted in less expected or less protected locations, weakening operator assumptions about where data lands.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script sends arbitrary JSON parameters plus SESSION_ID, MESSAGE_ID, MODE_ID, and APP_NAME to a remote service, and the full response is then cached and written to disk. In this skill context, seller-detail lookups are expected to call a backend, but the combination of silent metadata forwarding and local persistence increases privacy and data-governance risk, especially if users or operators do not expect those identifiers to leave the runtime.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's natural-language interface, help text, and operational assumptions are all fixed to Chinese, including '+86' phone numbers and WeChat/Alipay payment methods, with no opt-in or alternative locale path. This forces a specific language/locale experience rather than offering user choice or clearly documenting a justified regional constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill creates a directory and saves a payment QR code PNG under a session path on the local filesystem, which is a persistent file write affecting user data and environment state. In this file there is no confirmation prompt or user-facing warning that running the order flow will create local files containing payment information.

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

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The activation description and several operational sections are written to assume Chinese-language interaction patterns, including trigger phrasing and response guidance, without stating that the user may choose another language. This can constitute a locale/language policy issue when a skill implicitly constrains usage to one language without opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The inline comment for SMALL_THRESHOLD says responses below the threshold are '直接全量输出,不落文件'. In main(), the script always serializes and writes the full response to out_path before deciding whether to print inline or summarize. This is a direct mismatch between the comment and actual behavior.

Content

No source excerpt is available for this finding.