Back to skill

Security audit

Shopify店铺查询

Security checks for vulnerabilities and agentic risk

Overview

The skill's main Shopify query function is clear, but it also handles phone-based login, persistent API keys, and payment orders in ways users should review carefully.

Review this skill before installing if you are not comfortable with LinkFox account and billing automation. Use only trusted LinkFox endpoints, avoid setting custom gateway/login URL environment variables, do not paste SMS codes or phone numbers unless you intend to create or recover a LinkFox account, and store any API key in a proper secret manager rather than shell startup files or chat logs.

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

Environment-Controlled API Endpoints Can Exfiltrate Authentication Credentials

Content
View full analysis
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: """Construct headers with browser-like fields; attach authorization and uid when present.""" h = { "Accept": "application/json, text/plain, */*", "Content-Type": "application/json;charset=UTF-8", "Origin": f"https://{origin_host}", "Referer": f"https://{origin_host}/", "source": source, "User-Agent": UA, } if access_token: h["authorization"] = access_token h["uid"] = _uid_header(access_token, user_id) if user_id else _LOGIN_FIXED_UID if group_id: h["tid"] = group_id return h ``` ```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": {"aid": "3026344186", "did": "", "type": "Windows", "os": "10", "model": "149.0.0.0", "brand": "Chrome"}, }, _headers("agent-linkfox-web", "agent.linkfox.com", access_token=access_token)) ``` ```python def _fetch_user_info_v3(access_token: str, user_id: str) -> d ...[truncated 3731 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:487
Finding

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

Content
View full analysis
str: if not isinstance(resp, dict): return "" for src in ( resp, resp.get("data") if isinstance(resp.get("data"), dict) else {}, ): for k in _TOKEN_KEYS: v = src.get(k) if isinstance(v, str) and v: return v d = resp.get("data") return d if isinstance(d, str) and d else "" def _get_or_generate_api_token( access_token: str, user_id: str, group_id: str) -> dict: hdr = _headers( "agent-linkfox-web", "ai.linkfox.com", access_token=access_token, user_id=user_id, group_id=group_id, ) for path, source in ( ("/group/getApiToken", "existing"), ("/group/generateApiToken", "generated"), ): resp = _http_post( f"{_agent_user_base()}{path}", {"id": group_id}, hdr, ) if "_error" in resp: return { "error": ( f"{path.rsplit('/', 1)[-1]}: " f"{resp.get('_body') or resp['_error']}" ) } tok = _extract_token(resp) if tok: return {"api_key": tok, "source": source} ``` ```python def login_and_get_key(phone: str, code: str, channel: str) -> dict: # ... 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), } def _emit(obj: ...[truncated 2337 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/shopify_store_query.py:249
Finding

Unsanitized SESSION_ID Enables Output Path Traversal

Content
View full analysis
str: """Prefer SESSION_ID; otherwise generate a 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 ``` ```python def _resolve_output_path(ts): """Resolve the response output path for the current session.""" sys.path.insert( 0, os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "..", "_shared", ), ) return resolve_data_path(SLUG, ts) ``` ```python 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)") except OSError as e: print(f"Failed to save to {out_path}: {e}", file=sys.stderr) ``` ### Technical Analysis `SESSION_ID` is accepted directly from the environment and passed as the final component of `os.path.join(root, date_str, sid)`. Python path joining has two relevant behaviors: - An absolute `sid` discards the preceding `root` and `date_str`. - A relative value containing `..` can t ...[truncated 1853 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:160
Finding

Onboarding Directs Users to Install Unpinned Runtime 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 instructs users to install `qrcode`, `pillow`, and `requests` without version constraints, integrity hashes, a lockfile, or a documented trusted package index. Package installation can execute package build logic, and later imports execute installed module initialization code. The effective dependency versions may change over time or be influenced by pip configuration, mirrors, proxies, and custom indexes. Consequently, the reviewed Skill package does not fully determine the code that will execute. The package names are established projects rather than apparent typosquats. The risk arises from unrestricted resolution and unsafe installation guidance, not from evidence that the named packages are currently malicious. ### Attack Path 1. The victim invokes an onboarding operation on a system where a dependency is absent. 2. The script displays an instruction such as `pip install requests`. 3. The victim runs the command in an environment using a compromised or attacker-controlled package index, mirror, proxy, or pip configuration. 4. Pip resolves an attacker-controlled or compromised package release because no reviewed version or hash is required. 5. Package installation or subsequent import executes attacker-controlled c ...[truncated 541 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (25)

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

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The code allows service base URLs to be overridden by environment variables and then uses those URLs in requests.post while attaching sensitive authentication material such as access tokens, API keys, and login-related data. In an agent or hosted execution environment, a malicious or compromised runtime can redirect these requests to attacker-controlled endpoints, causing credential exfiltration and unauthorized account takeover.

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

The gateway URL is derived from environment variables and passed to urllib.request.urlopen with the Authorization header containing the user's API key. If an attacker can influence the environment, they can redirect gateway traffic to an arbitrary server and capture the API key or manipulate downstream responses related to account, package, and order operations.

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

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

Content

Scanner excerpt · scripts/shopify_store_query.py (reported line 79)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 Shopify store discovery and analysis, but the referenced behavior includes SMS login, API key generation, account/team inspection, subscription lookup, payment order creation, QR-code generation, and payment-status polling against LinkFox account systems. This hidden expansion into authentication and billing flows creates a serious trust-boundary violation and could expose users to credential handling, account actions, and charges they did not intend when invoking a store-query skill.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file for a Shopify store-query skill embeds account onboarding, login recovery, and billing workflows that are unrelated to the declared purpose of store discovery and analysis. This creates unnecessary capability expansion into credential handling and payment enablement, increasing the chance that the agent will solicit secrets or guide users through sensitive account actions outside the expected trust boundary.

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 tell the agent to collect a user's phone number and drive a script-based send-code/login flow, which is unjustified for a store-query skill. This is dangerous because it normalizes collection of personal data and facilitates credential/account provisioning through an external service without clear necessity, minimization, or privacy safeguards.

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
证码后:`python scripts/onboarding.py login <phone> <code>`(workbuddy 宿主加 `--channel workbuddy`)
   - 拿到 `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 skill adds plan listing, order creation, payment-method selection, and payment guidance, none of which are necessary for analyzing Shopify stores. This broadens the agent into handling monetization workflows, exposing users to unintended purchases, phishing-like behavior, or manipulation into external payment actions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements SMS login, API key issuance, subscription discovery, order creation, and payment QR rendering, which are unrelated to the declared Shopify store-query capability. Such scope divergence is dangerous because it collects user credentials and initiates billing flows under the guise of a data-query skill, greatly increasing the chance of deceptive account abuse or unauthorized monetization.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code creates purchase orders and renders payment QR codes even though the advertised purpose is Shopify store querying. Embedding purchasing capability in an unrelated skill creates a clear risk of deceptive charging, social engineering, or unauthorized payment initiation, especially in agent contexts where users may trust the skill's stated purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill can obtain or generate persistent API tokens for the user after SMS-based login, despite the skill being described only as a Shopify store query tool. Persistent credential minting enables long-term access beyond the user's immediate request and could be abused for continued account access, data extraction, or billing actions without further user awareness.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
74% confidence
Finding

The skill declares no explicit tool scope or permission boundaries even though it appears to rely on environment variables, file output, and network access. In an agent setting, missing scope declarations can enable broader-than-expected capability use, reducing reviewability and increasing the chance of unintended data access or side effects.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The activation criteria are broad enough to trigger on general Shopify-related discussion rather than a clear request to run a store-query workflow. Over-broad triggering is dangerous here because the skill also appears tied to authentication, quota, and payment flows, so accidental activation could initiate sensitive external actions or push users into commercial workflows unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The Feedback API sends free-form content to a separate public endpoint, but the documentation does not warn that this may include user-related information, conversation details, or sensitive operational context. Because feedback text is unconstrained and destined for a different service, an agent or operator could unintentionally disclose personal data, confidential prompts, or proprietary business information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The content instructs collection and transmission of a phone number to an external onboarding script but provides no privacy notice, purpose limitation, retention policy, or consent language. Even if the backend is legitimate, this creates privacy and compliance risk because the user is not informed how their personal data will be used or protected.

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 and command descriptions are entirely in Chinese, and later help text/messages continue this pattern. Because the file does not offer user opt-in for language selection or state that the skill is intentionally China/Chinese-only, this is a natural-language locale policy issue under the rule.

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

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring explicitly promises cwd-only storage and forbids /tmp, but the implementation in _linkfox_root falls back to the home directory and then the system temp directory. This mismatch can cause sensitive API responses to be written to less controlled locations than users or operators expect, increasing disclosure risk on shared systems or ephemeral environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script sends user-supplied query parameters along with session and app metadata to a third-party API and does not provide any inline disclosure, minimization, or consent mechanism. In this skill context, store-search parameters may include competitive intelligence targets, internal research context, or identifiers that users may not expect to leave the local environment, so the privacy risk is real even though remote API use is core functionality.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The natural-language instructions and operational guidance are all presented in Chinese, which can impose a language expectation on users without opt-in. The file does not state that the skill is China-specific or otherwise justify limiting guidance to this language.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The API documentation instructs sending user-supplied search terms and store query parameters to an external gateway without any privacy, retention, or data-handling notice. While the data appears business-oriented rather than highly sensitive, agents may still transmit user-provided identifiers or commercially sensitive research terms to a third party without adequate disclosure or minimization.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a skill for filtering and analyzing Shopify stores. However, this file also documents posting user-result feedback to an external skill-api.linkfox.com endpoint, which is a distinct telemetry/reporting capability rather than part of store query functionality.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The file presents all user-facing instructions in Chinese and does not indicate that users may choose another language or that the skill is intentionally limited to a Chinese-speaking audience. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language instructions and descriptions in the file are entirely in Chinese, including the title, usage notes, and operational behavior, with no indication that users may choose another language. Under the stated policy, forcing a specific language without opt-in is a locale-policy issue unless the restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The inline comment for SMALL_THRESHOLD says responses at or below the threshold are output directly '不落文件' (not written to file). In main(), the script serializes and writes the full response to out_path before deciding whether to print inline or summarize, so even small responses are persisted.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.