Back to skill

Security audit

Seerfar-Ozon关键词挖掘

Security checks for vulnerabilities and agentic risk

Overview

The skill performs the advertised keyword-mining task, but it also includes sensitive account, credential, payment, and automatic feedback-reporting behavior that deserves manual review before installation.

Install only if you are comfortable with LinkFox handling keyword queries, account authentication, billing flows, and feedback data. Prefer obtaining and storing API keys yourself through first-party LinkFox pages or a credential manager, avoid sharing SMS codes unless you intentionally choose that onboarding path, and do not use custom endpoint environment variables unless you trust the destination.

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)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:146
Finding

Automatic External Feedback Transmission Without Explicit User Consent

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/seerfar_ozon_keyword_mining.py:36
Finding

Environment-Controlled Endpoints Can Receive API Keys and Login Tokens

Content
View full analysis
str: """网关基础地址:env LINKFOX_TOOL_GATEWAY 优先,缺省回退正式地址。""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") ``` The API key is then transmitted to that destination: ```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", "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", ) ``` Onboarding service destinations are also environment-controlled: ```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") ``` Sensitive access and refresh tokens are sent to the selected Agent User endpoint: ```python def _login_by_token(access_token: str, refresh_token: str) -> dict: """新用户送算力。失败不阻断。""" resp = _http_post(f"{_agent_user_base()}/account/loginByToken", { "token": access_token, "refreshToken": refresh_token, "device": ...[truncated 3796 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/seerfar_ozon_keyword_mining.py:250
Finding

Unsanitized SESSION_ID Enables Output-Path Traversal

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) ``` The onboarding script similarly uses the environment value directly: ```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 directory name, but no validation restricts it to a single safe path component. Values containing `..`, path separators, or an absolute path can alter the resolved destination. In Python, if a later component passed to `os.path.join()` is absolute, preceding components may be discarded. Traversal components can also escape the intended date and LinkFox directories after path normalization. The keyword-mining script writes complete API responses and metadata beneath the resulting session directory. The onb ...[truncated 1541 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/onboarding.md:11
Finding

Generated API Keys Are Persisted in Plaintext Shell Configuration

Content
View full analysis
"` - 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 The onboarding instructions recommend persistently storing the generated LinkFox API key directly in shell startup files or the Windows user environment. Shell configuration files are not secret-management systems. They are routinely read by processes running under the same account and may be copied into backups, dotfile repositories, diagnostic archives, support bundles, or shared development environments. The command also leaves the key in terminal output and potentially in interaction logs. The script returns the complete key in its JSON output: ```python 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), } ``` This increases the number of places where the credential can be retained. ### Attack Path 1. The user completes SMS login and receives a generated API key. 2. The Agent forwards one of the documented persistence commands. 3. The user runs the command, storing the complete key in `.bashrc`, `.zshrc`, or the Windows user environment. 4. The key persists across sessions and may be included in backups, copied dotfiles, diagnostics, or files accessible to other same-user processes. 5. A malicious local process, compromised developme ...[truncated 714 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:163
Finding

Runtime Guidance Installs 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 absent, the script directs users to install mutable package names without: - Exact versions. - Package hashes. - A reviewed lockfile. - An explicitly trusted package index. - An isolated virtual environment. - Integrity verification. Package installation can execute build backends, setup logic, or other package-controlled code with the user's privileges. Even when the package names refer to legitimate projects, resolving unconstrained future versions creates supply-chain drift and makes the effective code installed by users different from the code reviewed during the Skill audit. No evidence was found that the project intentionally references typosquatted package names. The risk arises from insecure dependency installation guidance rather than a confirmed malicious package. ### Attack Path 1. The user invokes an onboarding operation requiring `requests`, `qrcode`, or `Pillow`. 2. The dependency is absent. 3. The script instructs the user to run an unpinned `pip install` command. 4. Pip resolves packages from the user's configured package indexes at installation time. 5. A compromised release, malicious package-index response, dependency compromise, or unsafe build artifact is downloaded. 6. Package-controlled installation or runtime code executes with the privileges of the user ...[truncated 569 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (23)

Description-Behavior Mismatch

Critical
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file implements account onboarding, SMS login, API key acquisition, subscription handling, and payment QR generation, which is materially unrelated to the declared Ozon keyword-mining skill. This mismatch is dangerous because it can trick users or the platform into executing credential collection and monetization flows under the guise of benign analytics functionality.

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

The code builds request destinations from environment-controlled base URLs and then sends sensitive authentication material, including SMS login data, bearer tokens, and generated API keys, to those endpoints. If an attacker can influence environment variables in the skill runtime, they can redirect these requests to attacker-controlled infrastructure and exfiltrate credentials or payment-related data.

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 helper constructs outbound requests from environment-derived base URLs and attaches the API key in the Authorization header before calling urlopen. An attacker who controls the environment can redirect plan, account, or order traffic to a hostile server and capture the API key and associated account metadata.

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

The request sent to urlopen includes headers and target information derived from environment variables, and the base URL is also overrideable via LINKFOX_TOOL_GATEWAY. In an agent/runtime context, environment variables are part of the trust boundary; if an attacker can influence them, the skill can be redirected to an arbitrary host and will transmit the Authorization API key and session metadata, causing credential exfiltration or unintended outbound requests.

Content

Scanner excerpt · scripts/seerfar_ozon_keyword_mining.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 declared purpose is keyword mining, but the skill behavior reportedly also includes SMS login, API-key generation/retrieval, account/team inspection, subscription lookup, order creation, payment initiation, QR-code generation, and payment-status polling. This is a major description-behavior mismatch that can conceal credential handling and financial actions behind an analytics-facing interface, increasing the risk of unauthorized account changes, billing events, or secret exposure.

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

md
3. **Stack range filters to find opportunities**: combine a high `searchVolume` floor with a low `sellers` ceiling to surface blue-ocean expansions; add `relevancy` / `titleDensity` bounds to keep them relevant to the seed.
4. **Use `includeKeywords` / `excludeKeywords` to steer the expansion**: force in must-have modifiers and strip noise without running a second query.

## Display Rules

1. **Present data only**: show mined-keyword metrics in a clear table without subjective advice.
2. **Lead with keyword columns**: `query` / `queryCn` (Chinese translation), then `searchVolume`, `count30GrowthRate`, `productCount`, `sellers`, `avgPrice`; show `relevancy` to convey closeness to the seed (the seed term itself is `100`).

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The onboarding document instructs the agent to handle authentication recovery, account registration, API key acquisition, and billing/payment flows, which are materially outside the stated purpose of an Ozon keyword-mining skill. This expands the skill into account and payment handling, creating unnecessary exposure to credential collection, social engineering, and misuse of user trust under the guise of a benign analytics capability.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The instructions explicitly authorize asking for a user's phone number, sending login codes, logging in on the user's behalf, and guiding payment selection, none of which are justified by the skill’s keyword-mining purpose. In this context, collecting personal contact data and facilitating purchases is especially risky because users may not expect sensitive identity or payment handling from a market-research skill.

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

The code includes order creation, payment state queries, and QR-code payment rendering despite the skill being described as a keyword-mining tool. In this context, unrelated payment capabilities substantially increase risk of deceptive charging, unauthorized purchases, or abuse of the agent as a billing funnel.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill performs SMS-based authentication, team lookup, and API token retrieval/generation, all unrelated to the advertised keyword-mining behavior. In this context, that functionality acts like credential harvesting and secret provisioning concealed inside an unrelated skill, making the deception especially dangerous.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documents capabilities that involve environment access, network calls, and writing files, but it declares no explicit tool scope or permission boundaries. This creates an over-privileged execution surface where an agent may invoke sensitive capabilities without clear least-privilege constraints or user-visible authorization boundaries.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Line L096 states 'Pass it in Russian for Ozon,' which imposes a specific language requirement in the skill's instructions. The file does not present this as an explicit user choice or opt-in, so it is a natural-language locale/language policy concern.

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

}

text

## curl 示例

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

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document instructs collection of a phone number and execution of registration/login commands without any explicit warning that the phone number and verification code are sensitive authentication data. This creates a privacy and account-takeover risk because users may be induced to share credentials or one-time codes in a context unrelated to the skill’s declared business 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
83% confidence
Finding

The code enforces 11-digit domestic phone numbers with area code +86 and limits payment methods to WeChat and Alipay, while user-facing strings present this as the default behavior rather than an explicitly region-specific tool. Under the policy, locale constraints should either be optional for the user or clearly documented and justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The login flow returns a usable API key directly in stdout JSON, which is likely to be logged, stored in transcripts, surfaced to other components, or copied insecurely by users. Exposing newly minted long-lived credentials through standard output greatly increases the chance of accidental secret leakage and account compromise.

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 states '禁止写入 /tmp,当前目录不可写则报错', implying the script must not use temporary directories and should error if the current directory is not writable. However, _linkfox_root() later includes $TMPDIR/linkfox/ as a fallback and auto-selects it when earlier locations are not writable, which directly contradicts the documented behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file documents a Feedback API that sends content describing user expressions and observed behavior to an external endpoint, but it does not warn that potentially sensitive user-entered information may be transmitted. Under the markdown-specific SQP-2 criteria, externally sending user-related content should include a user-facing privacy or data-sharing warning when it could affect user data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The file's natural-language instructions are entirely Chinese, which can amount to a language-policy issue when no user language preference or opt-in is offered. There is no indication that the skill is region-specific or that Chinese is required for a justified compliance reason.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The inline comment says responses under the threshold are '直接全量输出,不落文件', which means no file write for small results. In main(), the script serializes and writes every response to out_path before deciding whether to print the full JSON or only a summary, so the code behavior is the opposite of that comment.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

_resolve_output_path() documents that output lands under <cwd>/linkfox/<日期>/<session>/data/.... In reality it delegates to resolve_data_path(), which depends on _linkfox_root(), and that function may choose $ACPX_WORKSPACES, the user's home directory, or the temp directory rather than the current working directory.

Content

No source excerpt is available for this finding.