Back to skill

Security audit

MPSTATS-Ozon商品搜索

Security checks for vulnerabilities and agentic risk

Overview

The skill can search Ozon products, but it also includes account login, API key creation, billing/payment order flows, silent feedback reporting, and broad local/network handling that users should review before installing.

Review this skill before installing. It is not just a read-only Ozon search helper: it can collect phone/SMS login information, generate and persist API keys, create payment orders, write response and QR data to disk, and send feedback externally. Use only with trusted LinkFox credentials, verify environment variables point to official HTTPS LinkFox hosts, avoid storing secrets in shared shell profiles, and do not use the billing/onboarding flows unless you intentionally want those account actions.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mpstats_ozon_product_search.py:36
Finding

Environment-controlled endpoints permit credential exfiltration

Content
View full analysis
str: """Gateway base URL: LINKFOX_TOOL_GATEWAY takes precedence.""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") 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", ) ``` The onboarding flow similarly permits all sensitive API origins to be replaced: ```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") ``` Tokens are subsequently attached to requests sent to those configurable origins: ```python if access_token: h["authorization"] = access_token h["uid"] = _uid_header(access_token, user_id) if user_id else _LOGIN_FIXED_UID ``` ```python resp = _http_post(f"{_agent_user_base()}/account/loginByToken", { "token": access_token, "refreshToken": refresh_token, "device": ...[truncated 2540 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:116
Finding

Silent and overly broad feedback transmission exceeds the Skill’s declared purpose

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mpstats_ozon_product_search.py:250
Finding

Unvalidated SESSION_ID enables path traversal and writes outside the intended storage root

Content
View full analysis
str: """Prefer SESSION_ID; otherwise generate a process-stable identifier.""" 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]: """Return (linkfox_root, session_dir); session_dir always exists.""" date_str = time.strftime("%Y-%m-%d", time.localtime(ts)) sid = _session_id(ts) root = _linkfox_root() session_dir = os.path.join(root, date_str, sid) os.makedirs(session_dir, exist_ok=True) _ensure_meta(root, session_dir, date_str, sid, ts) return root, session_dir ``` The onboarding implementation uses the same unsafe pattern: ```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 even though it comes from the environment. It is not checked for: - Absolute paths - `..` traversal components - `/` or `\` separators - Platform-specific drive or UNC path syntax - Excessive length - Symlink-assisted escape With `os.path.join`, an absolute final component can replace the preceding root on supported platforms. Relative traversal compone ...[truncated 1449 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/onboarding.py:163
Finding

Runtime instructions install unpinned third-party dependencies

Content
View full analysis
dict: try: import qrcode except ImportError: err = "Missing qrcode dependency; run: pip install qrcode pillow" print(f"{TAG} render_qr: {err}", file=sys.stderr) return {"png_path": None, "ascii_qr": None, "error": err} ``` ```python def _require_requests() -> None: if requests is None: raise RuntimeError( "Missing requests dependency; run: pip install requests" ) ``` ### Technical Analysis The onboarding script directs users to install mutable packages by name without pinned versions, hashes, a lock file, or a trusted package-index requirement. Package resolution therefore depends on the user’s current pip configuration and the state of external repositories at installation time. The packages named here are established public packages, and the audit found no direct evidence that they are malicious. The vulnerability is the unsafe dependency acquisition process rather than a confirmed malicious package. A compromised upstream release, dependency-confusion condition, malicious configured index, or incompatible future release could introduce unreviewed code into the runtime. ### Attack Path 1. The runtime does not contain `requests`, `qrcode`, or Pillow. 2. The user invokes onboarding and receives the installation instruction. 3. The user runs the unpinned `pip install` command. 4. pip resolves packages and transitive dependencies from its configured indexes. 5. A compromised, substituted, or unexpected package version is installed. 6. Package installation hooks or subsequently imported package code executes with the user’s privileges. ### Impact Assessment A malicious dependency could execute code with the privileges of the Python en ...[truncated 428 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 (26)

Tainted flow: 'req' from os.environ.get (line 73, 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 overrideable via LINKFOX_TOOL_GATEWAY. In an agent setting, this can exfiltrate sensitive execution metadata and the API key to an attacker-controlled endpoint if the environment is influenced, making the tainted network flow a real issue rather than a harmless configuration pattern.

Content

Scanner excerpt · scripts/mpstats_ozon_product_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 ""

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The script builds outbound request destinations from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys to those endpoints. If an attacker can influence environment variables in the runtime, they can redirect these requests to attacker-controlled servers and exfiltrate credentials or payment-related data. The mismatch with the declared Ozon product-search purpose makes this more suspicious because the file performs privileged onboarding and billing actions unrelated to read-only search.

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

The gateway request path uses an environment-derived base URL and attaches the LinkFox API key in the Authorization header before calling urlopen. A hostile or tampered environment can therefore redirect authenticated traffic to an attacker-controlled endpoint, exposing the API key and enabling unauthorized use of the user's account or paid resources. In this skill context, that danger is elevated because authenticated billing and account-management operations are present even though the manifest claims a marketplace search function.

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 simple Ozon product lookup, but the detected behavior includes phone-based authentication, API key issuance, account/team data access, plan listing, payment order creation, QR rendering, and payment-status queries. This is a major capability mismatch that can mislead users and reviewers, enabling sensitive account actions and financial workflows under the cover of a benign search 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 73)May include surrounding context.

md
2. **Brand drill-down**: For brand-scoped product listings with full metrics, call `mpstats-ozon-brand-products` directly with the brand display name.
3. **Seller drill-down**: For seller-scoped product listings with full metrics, call `mpstats-ozon-seller-products` directly with the seller ID.

## Display Rules

1. **Lead with identity columns** — this endpoint returns only 10 identity fields. Headline the table with `productId`, `title`, `brand`, `sellerName`; include `productPageUrl` / `imageUrl` as secondary columns. Do **not** add price / sales / rating / stock columns — they are not in the response.
2. **Russian titles** — preserve the original Russian title; optionally offer an English or Chinese translation on user request.

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 acquisition, plan listing, order creation, and payment QR generation, none of which are necessary for an MPSTATS Ozon product-search skill. Such capability drift is dangerous because it can induce users to disclose credentials and initiate purchases under the guise of a read-only search tool, violating least privilege and user expectations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code creates orders, renders payment QR codes, and queries payment state, which materially exceeds the read-only semantics of a product-search skill. This can be abused to trigger unauthorized or deceptive payment workflows from a context where users would not reasonably expect commerce or billing actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

SMS-based login and API key generation are highly privileged account actions that are unrelated to searching Ozon products. Embedding them in this skill creates a credential-harvesting and account-bootstrap path that can obtain long-lived access for downstream misuse, especially because the resulting API key can be used for further authenticated operations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares capabilities that imply environment access, file writing, and network use, but it does not constrain them with an explicit tool scope. That increases the blast radius if the skill is invoked unexpectedly or extended later, because the runtime could access secrets, write files, or make outbound calls beyond the narrowly described search use case.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file states that if the user supplies an English or Chinese keyword, it must be translated to Russian first. This imposes a specific language workflow rather than offering it as a choice, which is a natural-language locale policy concern under the rule for forced language without opt-in.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill requires every response to be written to session-scoped files under the current project directory, creating persistent local copies of potentially sensitive API data. Storing data by default in a shared working directory increases the risk of unintended retention, exposure through version control, or access by other tools/processes in the workspace.

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 the agent to auto-report broad categories of feedback via a Feedback API, including anything that could be improved, without tying that reporting to the user's explicit intent. That can result in unsolicited transmission of user content, session context, or behavioral metadata to an unrelated endpoint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The parameter description explicitly requires a Russian search keyword example, and the error-code section states non-Russian keywords are a common failure case. This amounts to a language/locale constraint in natural-language documentation without an explicit opt-in or justification as a region-specific requirement.

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

| 402 | 算力或余额不足 | HTTP 402:按 SKILL.md 的 ## 解决认证和算力问题 处理。 | | 其他非 200 值 | 业务异常 | 查看 errmsg / msg 获取具体原因;常见为 keyword/productIds 均缺失、日期超过昨日、非俄语关键词等 |

curl 示例

bash
curl -X POST https://tool-gateway.linkfox.com/mpstats/ozon/productSearch \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The onboarding flow explicitly invites the user to provide a phone number so a local script can perform registration, but it does not disclose how that personal data will be transmitted, stored, or protected. In a security-sensitive agent skill, collecting PII without a clear privacy notice and consent boundary can lead to unintended disclosure or misuse, especially if users assume the agent is handling the data safely by default.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring promises that writing to /tmp is forbidden and that failure to write to the current directory should error out, but the implementation silently falls back to home and temp directories. This discrepancy is dangerous because operators and reviewers may rely on the documented storage boundary, while the actual code expands persistence into less controlled locations, increasing the chance of unintended data exposure.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill stores full API responses, cache entries, session IDs, and metadata on local disk even though its declared purpose is only product search. In an agent/runtime context this creates unnecessary data retention and cross-task persistence, which can expose user queries, returned marketplace data, and session linkage information to other processes or later tasks.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script writes session directories and QR code image files to local disk even though persistent local artifacts are unnecessary for a simple product-search skill. Those files can leak payment URLs or session correlation data to other local users/processes and expand the skill's attack surface beyond its declared function.

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

The skill enforces a +86 area code and 11-digit domestic phone number format, and all help text and user-facing messages are in Chinese. This is a locale constraint presented as the default behavior without any visible user opt-in or explicit documented justification in the file, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The API key generation flow handles sensitive login-derived credentials and returns a usable API key, but this file contains no strong in-band warning, consent gate, or disclosure that the user is granting durable access. In a mismatched skill context, that omission increases the risk of users being socially engineered into providing authentication material they would not otherwise share.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The trigger/description repeatedly binds the skill to Ozon Russia and Russian-keyword search, including mixed-language invocation examples, but does not explicitly offer the user a language or locale choice. Because the file includes natural-language instructions that steer behavior toward a fixed locale, this can be read as a policy issue unless documented as a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file documents POST requests to external endpoints and instructs use of an Authorization header sourced from environment variables. Under the markdown-specific warning criterion, it lacks any explicit user warning about privacy, credential handling, or the fact that search inputs are sent to third-party services.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes a skill for searching or reverse-looking up Ozon products in MPSTATS and returning product identity information. The documented Feedback API adds a distinct capability to send user feedback to another service, which is not necessary to perform Ozon product search and is outside the stated functional scope.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.