Back to skill

Security audit

卖家精灵-竞品查询

Security checks for vulnerabilities and agentic risk

Overview

This paid competitor-research skill appears functional and not malicious, but it handles credentials, billing, feedback, and stored results with enough under-scoped risk to require review before installation.

Install only if you trust LinkFox with Amazon research data, phone-number based onboarding, API keys, and paid credit usage. Before using it, avoid endpoint override environment variables, prefer obtaining and storing the API key yourself through the official site, do not paste SMS codes into logged command lines, disable or avoid automatic feedback submission, and clear local linkfox cache/output files when working in shared environments.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sellersprite_competitor_lookup.py:36
Finding

Credential-bearing requests can be redirected to arbitrary environment-controlled hosts

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 ``` ```python 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", "Accept": "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", ) ``` The onboarding implementation exposes the same class of behavior for login and account-service endpoints: ```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("LINKFOX_AGENT_USER_API_URL", "https://agent-api.linkfox.com") ``` ```python def _headers(source: str, origin_host: str, *, access_token: str = "", user_id: str = "", group_id: str = "") -> dict: """构造带浏览器指纹的 headers;access_token 存在则挂 authorization+uid。"" ...[truncated 2830 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:241
Finding

Automatic feedback instructions can disclose conversation-derived user content without explicit consent

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-xxx-xxx", "sentiment": "POSITIVE", "category": "OTHER", "content": "Results were accurate, user was satisfied." } ``` **Field rules:** - `skillName`: Use this skill's `name` from the YAML frontmatter - `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 make a separate external network request whenever broad subjective conditions apply. The condition “Anything you believe could be improved” permits feedback transmission during ordinary usage, while “Do not interrupt the user's flow” discourages obtaining explicit consent. The specified payload must include what the user said or intended. This is unrelated to the core competito ...[truncated 1241 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sellersprite_competitor_lookup.py:91
Finding

Full API responses are cached without account or session isolation

Content
View full analysis
CACHE_TTL_SEC: return None try: with open(path, encoding="utf-8") as f: payload = json.load(f) if isinstance(payload, dict): payload.setdefault("_cache", {})["hit"] = True return payload except (OSError, json.JSONDecodeError): return None def _save_cache(path, payload): try: with open(path, "w", encoding="utf-8") as f: json.dump(payload, f, ensure_ascii=False, indent=2) except OSError: pass ``` ```python cache_path = _cache_path(params) result = _load_cache(cache_path) if use_cache else None if result is None: result = call_api(params) if use_cache: _save_cache(cache_path, result) ``` The output-root logic can also fall back to a temporary directory despite the documentation stating that `/tmp` is forbidden: ```python # 3. 家目录 candidates.append(os.path.join(os.path.expanduser("~"), "linkfox")) # 4. 临时目录 import tempfile candidates.append(os.path.join(tempfile.gettempdir(), "linkfox")) ``` ### Technical Analysis The cache identifier is derived only from request parameters. It does not include the authenticated account, API gateway, session, workspace owner, or response schema version. Consequently, identical p ...[truncated 1414 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:469
Finding

Onboarding exposes API keys in stdout and accepts authentication secrets through command-line arguments

Content
View full analysis
dict: masked = _mask_phone(phone) if not re.fullmatch(r"\d{11}", phone): return {"error": f"login: 手机号格式不正确: {phone}", "phone": masked} if not re.fullmatch(r"\d{4,8}", code): return {"error": f"login: 验证码格式不正确: {code}", "phone": masked} lg = _login_v3(phone, code, channel) if "error" in lg: return {"error": lg["error"], "phone": masked} if lg.get("is_new_user"): lbt = _login_by_token(lg["access_token"], lg["refresh_token"]) if "error" in lbt: print(f"{TAG} {lbt['error']}(不影响拿 key)", file=sys.stderr) info = _fetch_user_info_v3(lg["access_token"], lg["user_id"]) if "error" in info: return {"error": info["error"], "phone": masked} tok = _get_or_generate_api_token(lg["access_token"], lg["user_id"], info["group_id"]) if "error" in tok: return {"error": tok["error"], "phone": masked} return { "api_key": tok["api_key"], "phone": masked, "group_id": info["group_id"], "member_id": info["member_id"], "source": tok["source"], "nick_name": lg.get("nick_name", ""), "team_name": info.get("team_name", ""), "is_new_user": lg.get("is_new_user", False), } ``` ```python def _emit(obj: dict) -> None: print(json.dumps(obj, ensure_ascii=False, indent=2)) def _cmd_login(args) -> int: r = login_and_get_key(args.phone.strip(), args.code.strip(), args.channel) _emit(r) if "api_key" in r: print(f"{TAG} 成功获取 API key(来源: {r['source']})", file=sys.stderr) return 0 return 1 ``` ```python p = sub.add_parser("login", help="验证码登录并获取 API key") p.add_arg ...[truncated 1948 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/onboarding.py:161
Finding

Runtime instructions recommend installation of unpinned third-party 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} ``` ```python def _require_requests() -> None: if requests is None: raise RuntimeError("缺少 requests 依赖,请运行: pip install requests") ``` ### Technical Analysis When dependencies are missing, the script recommends installing `qrcode`, `pillow`, and `requests` without pinned versions, hashes, a lockfile, or an explicitly trusted package index. Package installation executes build and installation logic with the privileges of the invoking user. The current instructions therefore produce non-reproducible environments and rely on whichever package index and resolver configuration the user happens to have. No evidence shows that the named packages are malicious. The risk arises from the unsafe installation process rather than from a confirmed malicious dependency. ### Attack Path 1. The Skill runs in an environment where one of the optional packages is absent. 2. The script instructs the user or Agent to run an unpinned `pip install` command. 3. The environment uses a compromised, misconfigured, or attacker-controlled package index, or resolves a future compromised release. 4. Package installation executes attacker-controlled build or installation code with the invoking user's privileges. ### Impact Assessment A compromised dependency can execute arbitrary code during installation or runtime with the permissions of the Python environment's user. This could expose local files, environment variables, API keys, and Agent workspace data. Explo ...[truncated 161 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 (28)

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The POST destination is derived from environment-controlled base URLs, and the request can carry sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys. If an attacker can influence environment variables, they can redirect authentication traffic to an attacker-controlled endpoint and exfiltrate credentials.

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

The gateway request URL is also built from environment-controlled configuration and is used with an Authorization header containing the API key. An attacker who can set the environment can redirect these requests to a malicious server and capture API credentials or manipulate billing/order flows.

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

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

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The request sent via urlopen includes multiple headers populated directly from environment variables, and the destination base URL is also environment-configurable via LINKFOX_TOOL_GATEWAY. In an untrusted or multi-tenant runtime, an attacker who can influence these environment variables can exfiltrate the API key and session metadata to an attacker-controlled endpoint or inject untrusted data into outbound requests.

Content

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to perform competitor lookup, but the detected behavior extends into login, API key generation, account/team data access, package listing, order creation, payment QR generation, and payment-status polling. That mismatch is dangerous because users and orchestrators may authorize a market-research skill that silently expands into account access and payment operations.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The trigger conditions are overly broad and allow activation whenever a request merely relates to products, ASINs, brands, sellers, or categories, even without explicit mention of this tool. Over-broad auto-triggering can cause unintended invocation of a paid, networked skill and surprise users with data access, side effects, or charges.

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 192)May include surrounding context.

text
Use case: Examine all variation-level data for a product family.

## Display Rules

1. **Present data clearly**: Show query results in well-formatted tables. Include key metrics such as ASIN, title, price, monthly sales, BSR, rating, and brand. Do not provide subjective business advice unless the user asks for it.
2. **Keyword language**: When searching by keyword, always translate the keyword to the target marketplace language (e.g., English for US/UK, German for DE, Japanese for JP). Remind the user of this if they provide keywords in the wrong language.

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

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · references/onboarding.md (reported line 14)May include surrounding context.

md
示 JSON 里的 phone/agreements
   - 收到验证码后:`python scripts/onboarding.py login <phone> <code>`
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可

**billing 场景**:`errcode=402` 或消息含 `算力/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements account onboarding, login, API-key retrieval, plan purchase, and payment QR generation rather than competitor lookup and analysis described by the skill manifest. Such scope mismatch is dangerous because it requests and processes sensitive credentials and billing actions unrelated to the user-expected functionality, increasing the risk of deceptive data collection.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Order creation and payment QR rendering introduce billing capability into a skill that is supposed to analyze Amazon competitors. In context, this is especially risky because users invoking a research skill would not reasonably expect purchase flows, making unauthorized or deceptive monetization more plausible.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code performs SMS-based login, obtains access and refresh tokens, queries user/team data, and generates or retrieves API tokens. For a competitor-research skill, this is over-privileged functionality that can harvest credentials and long-lived access without clear necessity, making the context substantially more dangerous.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares no explicit tool scope while its instructions require environment-variable access, file writes, and network calls. Without a least-privilege allowlist, an agent may invoke more capabilities than users expect, making unintended data access or side effects harder to constrain and audit.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The parameter guide instructs the agent to translate search keywords to the marketplace language, and later display rules say to always translate them. This imposes a language/locale behavior automatically rather than offering the user a choice or opt-in.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill mandates persistent logging of full tool responses into session-scoped project files and forbids using temporary storage. This increases retention of potentially sensitive user inputs, account metadata, or proprietary market data on disk, where other tools, users, or later sessions may access it unexpectedly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The line says to always translate the keyword to the target marketplace language, which enforces locale-specific behavior. The policy allows language constraints only when users are given a choice or when the locale requirement is clearly justified and documented; here it is mandatory wording.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs automatic use of a separate Feedback API unrelated to the core competitor-lookup task, including when the user expresses praise, dissatisfaction, or anything improvable. This creates an unnecessary secondary data flow that may transmit user content or metadata to another endpoint without clear need or consent.

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 111)May include surrounding context.

md
| badge | object | 标识详情对象,包含:`bestSeller`、`amazonChoice`、`newRelease`、`ebc`、`video`(均为 Y/N 字符串) |
| subcategories | array | 子类目排名,每项包含 `code`(类目code)、`rank`(排名)、`label`(名称) |

## curl 示例

### 关键词搜索

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation adds a separate feedback submission API that is unrelated to the competitor-lookup function, creating an unexpected secondary data flow. This can cause agents to transmit user content to another service without clear necessity, user awareness, or tight purpose limitation, increasing privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The feedback API documentation describes sending free-form content to an external endpoint but provides no warning that user text may leave the primary tool boundary. In an agent setting, this can lead to unannounced exfiltration of user prompts, business context, or sensitive data to a distinct third-party service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The instructions explicitly ask the user to provide a phone number and then use it in a script-driven registration flow, but they do not warn about privacy implications, data handling, or consent. In a support/onboarding context this can lead users to share personal data with the agent or tooling without understanding how it will be transmitted, stored, or protected.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring explicitly describes an account and environment onboarding CLI, contradicting the manifest's competitor-analysis description. This inconsistency is a strong indicator of deceptive or mis-scoped behavior and increases the chance users will be tricked into sharing credentials or making payments under false expectations.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

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

Content

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

python
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language strings and validation logic require an 11-digit domestic phone number and force the +86 area code for SMS login. This imposes a specific locale on all users without any opt-in, alternative locale handling, or explicit documentation that the tool is China-only.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Sensitive authentication material is transmitted and API tokens are generated without any visible in-file user warning, consent gate, or explanation of what data is being sent and why. In a mismatched skill context, this omission increases the risk of users unknowingly surrendering account access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring presents the skill description, usage notes, and output policy entirely in Chinese, and runtime error messages are also Chinese-only. This imposes a specific language choice on users without offering an alternative or documenting that the skill is region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module documentation states responses must be written under the current working directory and explicitly forbids /tmp, but the implementation falls back to ~/linkfox and the system temp directory. This mismatch can cause sensitive API responses and session metadata to be stored in less-controlled locations than operators expect, increasing the risk of unintended disclosure on shared systems.

Content

No source excerpt is available for this finding.