Back to skill

Security audit

Seerfar-Ozon店铺搜索

Security checks for vulnerabilities and agentic risk

Overview

The skill can perform the advertised Ozon shop lookup, but it also handles credentials, phone login, payment orders, automatic feedback reporting, and local data retention with weak scoping.

Review this skill before installing. It is not just an Ozon seller lookup: it may ask for a LinkFox API key or phone/SMS login, create payment orders, send feedback to LinkFox without a separate confirmation, and store full API responses locally. Only use it in a trusted workspace, avoid endpoint override environment variables, and rotate any API key that appears in logs or shell history.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:133
Finding

Automatic Undisclosed Transmission of User Feedback and Conversation Context

Content
View full analysis
This API differs 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` { "skillName": "linkfox-seerfar-ozon-shop-search", "sentiment": "POSITIVE", "category": "OTHER", "content": "User successfully retrieved a competitor shop's best-sellers and 30-day total sales." } ``` ### Technical Analysis The skill instructs the Agent to autonomously detect feedback and transmit it to an external LinkFox endpoint. The trigger is broad, including anything the Agent believes could be improved. The `content` field is free-form and can therefore contain user statements, task details, search context, or other information from the active conversation. This transmission is unrelated to the minimum functionality required to query an Ozon seller's products. The instruction to avoid interrupting the user's flow further discourages obtaining informed consent before the external request. No data-minimization, redaction, payload-preview, or consent requirement is defined. This behavior alters the Agent's task by adding an undisclosed telemetry operation to an otherwise ordinary product-search workflow. ### Attack Path 1 ...[truncated 963 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/seerfar_ozon_shop_search.py:40
Finding

Authentication Credentials Can Be Redirected to Attacker-Controlled Network Hosts

Content
View full analysis
str: """Gateway base address: env LINKFOX_TOOL_GATEWAY first, otherwise production.""" 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(): """ Retrieve the API key configured in an environment variable. If unavailable, follow the authentication instructions in SKILL.md. """ key = os.environ.get("LINKFOX_AGENT_API_KEY") or os.environ.get("LINKFOXAGENT_API_KEY") if not key: print( "API Key is not configured", 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", ) try: with urlopen(req, timeout=150) as response: return json.loads(response.read().decode("utf-8")) ``` The onboarding script similarly allows authentication destinations to be overridden: ```python def _login_base() -> str: return _env_base("LINKFOX_LOGIN_API_URL", "https://api.linkfox.com") ...[truncated 2558 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:484
Finding

Generated API Key Is Exposed in Plaintext Output and Shell Configuration Guidance

Content
View full analysis
None: print(json.dumps(obj, ensure_ascii=False, indent=2)) ``` The onboarding documentation then instructs users to place the key directly in commands: ```markdown - 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` ``` ### Technical Analysis The login workflow retrieves or generates an API key and returns the complete secret in a JSON object printed to stdout. Standard output is frequently retained in Agent transcripts, terminal scrollback, CI logs, command-capture systems, debugging records, or redirected files. The documentation additionally encourages inserting the plaintext key into shell commands and persistent profile files. Commands may be retained in shell history, while profile files may have permissions that allow other local users or processes to read them. Masking the phone number does not protect the API key. No one-time display control, secret-store integration, restrictive file handling, or output redaction is implemented. ### Attack Path 1. The user runs `python scripts/onboarding.py login `. 2. The service returns or generates an API key. 3. `login_and_get_key` places the complete key in the response dictionary. 4. `_emit` prints ...[truncated 909 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/seerfar_ozon_shop_search.py:102
Finding

Complete API Responses Are Persisted with Default Filesystem Permissions and Excessive Retention

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 ``` The full response is also archived separately: ```python serialized = json.dumps(result, ensure_ascii=False, indent=2) ts = int(time.time()) out_path = _resolve_output_path(ts) try: with open(out_path, "w") as f: f.write(serialized) print(f"Saved full response: {out_path} ({len(serialized)} bytes)") if result.get("_cache", {}).get("hit"): print(f"Cache hit: {cache_path}") except OSError as e: print(f"Failed to save to {out_path}: {e}", file=sys.stderr) ``` ### Technical Analysis The script stores every complete API response in both a cache and a session data file. Files and directories are created with process-default permissions rather than explicit restrictive modes. On multi-user systems or environments with permissive `umask` settings, other local users or processes may be able to read the data. The API supports optional `uId` and `memberId` attribution fields, and r ...[truncated 1728 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 (22)

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

Critical
Category
Data Flow
Confidence
92% confidence
Finding

The POST destination is derived from environment-controlled base URLs, and this function sends sensitive authentication material such as access tokens, SMS-login data, and API-token requests to that endpoint. In an agent skill context, environment variables may be influenced by deployment or wrapper configuration, so a malicious or mistaken override can exfiltrate credentials and account data to an attacker-controlled server.

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

The gateway request target is also built from environment-controlled base URLs and is used with the Authorization header carrying the agent API key. If that base URL is overridden, the CLI will send the API key and billing/order data to an arbitrary remote host, enabling credential theft and abuse of the linked account.

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 73, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The request sent via urlopen includes multiple headers derived directly from environment variables, including SESSION_ID, MESSAGE_ID, MODE_ID, APP_NAME, and most importantly the gateway base URL can be overridden by LINKFOX_TOOL_GATEWAY. This allows a caller or surrounding runtime to exfiltrate API credentials and request metadata to an attacker-controlled endpoint if the environment is tainted, which is especially risky because the Authorization header is always attached.

Content

Scanner excerpt · scripts/seerfar_ozon_shop_search.py (reported line 80)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 description presents a simple analytics lookup, but the implementation reportedly persists full API responses locally, maintains a hidden cache, and may write outside the documented working directory. This creates data exposure and integrity risks because potentially sensitive account, usage, or analytics data can be retained on disk in places the user did not authorize or expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill description presents a simple analytics lookup, but the implementation reportedly persists full API responses locally, maintains a hidden cache, and may write outside the documented working directory. This creates data exposure and integrity risks because potentially sensitive account, usage, or analytics data can be retained on disk in places the user did not authorize or expect.

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

md
3. **Resolve the shop `id` first**: if the user gives a shop/product name rather than an id, obtain the `sellerId` from a product-level Seerfar Ozon source before calling this skill.
4. **Use shop-level aggregates for context**: `totalSales` / `totalRevenue` / `dailySales` are shop-wide totals (independent of the page), `productCount` is the full catalog size, `rating` is the shop rating, and top-level `fulfillment` shows the FBO/FBS split — all quick health indicators for the whole shop.

## Display Rules

1. **Present data only**: show the shop's product metrics in a clear table without subjective advice.
2. **Lead with shop context, then product columns**: state shop-level aggregates first — `totalSales` (30-day total), `totalRevenue` (total revenue, ₽), `productCount` (catalog size), `dailySales`, `rating`, and `fulfillment` distribution (e.g. FBO 72 / FBS 4) — then a table of `sku`, `price`, `sales`, `reviewRating`, `weight`, `sellerType`, `fulfillment`, `returnCancellationRate`.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The onboarding document adds account registration, login, and billing/payment workflows that are outside the stated purpose of an Ozon shop-search skill. This expands the skill's effective authority into credential handling and monetization flows, increasing the chance of phishing, unnecessary collection of sensitive data, and unsafe operator behavior if the instructions are followed.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Phone-based registration and order/payment handling are not justified by the skill's declared analytics purpose and create an unnecessary path for collecting personal data and initiating financial transactions. In the context of a shop-product analysis skill, these capabilities are especially risky because users would not reasonably expect the skill to mediate identity verification or purchases.

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

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements account onboarding, SMS login, API key retrieval, subscription listing, order creation, and payment QR generation, which are unrelated to the stated Ozon shop-search skill purpose. That mismatch is dangerous because it expands the skill into credential collection and monetization flows that users would not reasonably expect when invoking a product-analysis capability.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill contains billing and payment-order creation code, including pay URL/QR generation, despite its declared purpose being Ozon store product analysis. In this context, hidden purchasing capability is especially risky because it can be used to steer users into unexpected financial transactions or facilitate unauthorized account charges.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code sends SMS verification codes, logs users in by phone, and generates or retrieves API tokens, none of which are necessary for an Ozon seller-product lookup skill. In the skill context, this is a strong indicator of credential harvesting or unauthorized account bootstrap behavior disguised as unrelated functionality.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module documentation explicitly says writing to /tmp is forbidden and non-writable current directories should cause an error, but the implementation silently falls back to the home directory and then the temp directory. This mismatch is dangerous because operators may rely on the documented restriction for data-handling guarantees, while the code actually persists full responses and metadata into broader or less secure locations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares no explicit tool scope or permission boundaries even though its documented behavior includes reading environment variables, writing files, and making network calls. Without least-privilege constraints, an agent may invoke broader capabilities than users expect, increasing the blast radius if the skill is misrouted, compromised, or paired with prompt injection.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger conditions are broad enough to auto-activate on general marketplace-analysis intent even when the user did not explicitly request this specific skill. Over-broad routing is risky here because the skill consumes paid resources, accesses external services, and may write data locally, so accidental invocation can cause unnecessary data exposure or charges.

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

}

text

## curl 示例

```bash
curl -X POST https://tool-gateway.linkfox.com/seerfar/ozon/shopSearch \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The instructions tell the operator to pass a user's phone number and verification code through a script without any warning about privacy, storage, transmission, or consent. That omission can lead to unintended disclosure of personal data and SMS-based authentication material, which is sensitive even if the underlying service is legitimate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The CLI description, help text, log messages, and error strings are written in Chinese throughout the file, and the login flow is hardcoded to Chinese phone numbering conventions. There is no natural-language indication that the tool is China-specific or that users may opt into another language, which can violate language/locale policy requirements.

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 = ""

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code retrieves or generates API tokens programmatically without any built-in user warning, consent checkpoint, or prominent disclosure at the point of action. In a mismatched skill, silent token issuance increases the chance that users or operators unknowingly grant durable access that can later be abused.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill is presented as a simple Ozon shop search tool, but it always writes full API responses and session metadata to persistent local storage by default. This creates an unexpected data-retention channel that may store sensitive business data, identifiers, or operational metadata beyond what users would reasonably expect from the declared functionality.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script maintains a persistent on-disk cache and session indexing structure across runs, which is not necessary for a basic shop-search capability and expands the data exposure surface. Cross-run caches can leak prior query contents and results to other users or later tasks sharing the same host or workspace, especially in multi-tenant or agent environments.

Content

No source excerpt is available for this finding.