Back to skill

Security audit

睿观-外观专利检测

Security checks for vulnerabilities and agentic risk

Overview

The skill performs patent checks, but it also publicly uploads local images, handles account and billing flows, stores sensitive outputs, and can send feedback data without clear consent.

Review before installing. Use this only for images and product details you are willing to send to LinkFox and potentially expose through a public image URL. Avoid using the built-in phone/SMS login or billing/order commands unless you explicitly intend to manage a LinkFox account through the skill, and rotate any API key that appears in logs or transcripts. Do not rely on the stated 24-hour upload validity as proof that public access is revoked.

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

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:211
Finding

Automatic Feedback Reporting Exfiltrates User Statements Without Consent

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:468
Finding

Generated API Credentials Are Printed in Plaintext to Standard Output

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upload_image.py:86
Finding

Local Images Are Uploaded With Public-Read Access Without an Explicit Per-Upload Consent Boundary

Content
View full analysis
str: """Extract the base public URL by stripping query parameters.""" return presigned_url.split("?")[0] ``` ```python # Step 1: Get presigned URL presigned_url = get_presigned_url(content_type, extension) # Step 2: Upload file upload_file(presigned_url, file_path, content_type) # Step 3: Output public URL public_url = extract_public_url(presigned_url) print(json.dumps({"url": public_url}, indent=2, ensure_ascii=False)) ``` The associated skill instruction states: ```markdown This tool requires a **publicly accessible image URL**. If the user provides a local image file path [...], you must upload it first to obtain a public URL. Run the upload script: python scripts/upload_image.py /path/to ...[truncated 1980 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ruiguan_detection_patent_design.py:35
Finding

Unvalidated Gateway Overrides Can Redirect Bearer Credentials and User Data to Arbitrary Hosts

Content
View full analysis
str: """网关基础地址:env LINKFOX_TOOL_GATEWAY 优先,缺省回退正式地址。""" return (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") def get_api_url(): sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "_shared")) return get_api_base() + API_PATH def get_api_key(): key = os.environ.get("LINKFOX_AGENT_API_KEY") or os.environ.get("LINKFOXAGENT_API_KEY") if not key: print( "API Key 未配置", 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 same unrestricted override is used by the uploader: ```python _API_BASE = (os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com").rstrip("/") PRESIGN_URL = f"{_API_BASE}/oss/file/presignedPut" ``` Onboarding also accepts unrestricted base URLs through `LINKFOX_AGENT_API_URL`, `LINKFOX_LOGIN_API_URL`, and `LINKFOX_AGENT_USER_API_URL`. ### Technical Analysis The scripts trust endpoint base URLs ...[truncated 1827 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ruiguan_detection_patent_design.py:252
Finding

Unvalidated Session Identifier Enables Arbitrary Directory Selection for Output Files

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) _ensure_meta(root, session_dir, date_str, sid, ts) return root, session_dir ``` ```python def resolve_data_path(slug: str, ts: float, ext: str = "json") -> str: """普通 skill 的原始数据落到 /data/-.。""" _, session_dir = _ensure_session(ts) sub = os.path.join(session_dir, "data") os.makedirs(sub, exist_ok=True) out = os.path.join(sub, f"{slug}-{int(ts * 1_000_000)}.{ext}") _update_meta(session_dir, skill=slug, kind="data", file_rel=os.path.relpath(out, session_dir), ts=ts) return out ``` Onboarding contains the same construction: ```python 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) ``` ### Technical Analysis `SESSION_ID` is used as a path component without validation. Values containing `..`, path separators, or an absolute path can escape the intended session di ...[truncated 1548 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ruiguan_detection_patent_design.py:62
Finding

Undocumented Session and Message Metadata Is Transmitted With Patent and Upload Requests

Content
View full analysis
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 (31)

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 URLs from environment-controlled base URLs and then sends sensitive data to them via requests.post. Those requests include phone numbers, SMS codes, access tokens, refresh tokens, generated API keys, and browser-like headers, so a malicious or misconfigured environment can silently redirect credentials and session material to an attacker-controlled endpoint.

Content

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

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

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The gateway URL is also derived from environment variables and then used by urllib.request.urlopen with the Authorization header attached. This means an attacker who can influence environment variables can redirect authenticated gateway traffic, capturing API keys and manipulating account, package, or order operations against an attacker-controlled service.

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

The request sends multiple environment-derived values, including the API key and gateway base URL, into an outbound network call. Because LINKFOX_TOOL_GATEWAY is fully controlled by an environment variable, a compromised runtime or untrusted wrapper can redirect requests and headers to an attacker-controlled host, exfiltrating secrets and user data. In a skill context that handles patent-check inputs and writes responses to disk, this increases exposure of potentially sensitive business data.

Content

Scanner excerpt · scripts/ruiguan_detection_patent_design.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: 'req' from os.environ.get (line 57, 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/upload_image.py (reported line 73)May include surrounding context.

python
)

    try:
        with urlopen(req, timeout=150) as response:
            result = json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

Tainted flow: 'req' from os.environ.get (line 57, 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/upload_image.py (reported line 106)May include surrounding context.

python
)

    try:
        with urlopen(req, timeout=120) as response:
            if response.status not in (200, 201):
                print(f"Upload failed with status: {response.status}", file=sys.stderr)
                sys.exit(1)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to perform Ruiguan-based design patent detection, but the finding indicates it instead uploads local images to LinkFox OSS, uses LinkFox gateway authentication, and lacks visible patent-analysis behavior. That mismatch can mislead users into sharing proprietary product images under the belief they are being analyzed for infringement, when they may instead just be transmitted and stored by another service.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to perform Ruiguan-based design patent detection, but the finding indicates it instead uploads local images to LinkFox OSS, uses LinkFox gateway authentication, and lacks visible patent-analysis behavior. That mismatch can mislead users into sharing proprietary product images under the belief they are being analyzed for infringement, when they may instead just be transmitted and stored by another service.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger conditions are overly broad and fire on generic patent-, infringement-, and TRO-related language even when the user may not be asking for design-patent image analysis. In context, this increases the chance of unintended invocation of a skill that performs uploads, file writes, and external API interactions, leading to data exposure or unnecessary costly actions.

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

}

text

## Display Rules

1. **High-risk patent highlighting**: When generating summaries or reports, display ALL patents with `similarity >= 0.7` or `troCase = true` in full detail. For each such patent, include: application number, patent title (Chinese), inventors, TRO enforcement history, the most-similar patent drawing, every image in the patent image list, patent abstract, patent specification, LOC info, radar analysis result, and specification text. This detailed presentation is critically important -- do NOT abbreviate or omit these fields.
2. **Disclaimer**: Always append a friendly reminder at the end: "This detection result is generated by LinkfoxAgent. It is recommended to consult a professional IP attorney for legal advice."

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

The file implements account onboarding, SMS authentication, API-key retrieval, subscription browsing, order creation, and payment QR generation, which is materially unrelated to the declared design-patent detection purpose. This mismatch is dangerous because users or orchestrators may invoke a patent-analysis skill while actually being funneled into credential collection and commercial account operations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill includes billing and payment-order creation capabilities, including payment URL/QR handling, despite being presented as a patent-risk detection tool. Hidden monetization and purchasing logic broadens the attack surface and can enable unauthorized or deceptive purchase flows if the skill is triggered in contexts where users do not expect commerce actions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares no explicit tool scope while its instructions require environment-variable access, file writes, and network operations. In an agent setting, missing least-privilege boundaries increases the chance that the skill can access or exfiltrate more data than users expect, especially because it uploads files and persists responses locally.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill requires always writing full API responses to a session-associated local file, regardless of necessity. This creates avoidable data retention of user-provided images, product descriptions, patent results, and session-linked metadata, increasing the impact of local compromise, unauthorized access, or accidental disclosure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs users to upload arbitrary local image files to obtain a public URL, which expands the data flow beyond patent detection into public file publication. Because product images may contain confidential prototypes, metadata, or other sensitive business information, making them publicly accessible creates privacy, IP, and confidentiality risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation tells the agent to upload local images and generate a public URL but omits a clear privacy and data-handling warning. This is dangerous because users may not understand that their local files will leave the device and become externally accessible, potentially exposing proprietary product designs or personal information.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill directs automatic reporting to a Feedback API for broad categories including praise, dissatisfaction, mismatch, and anything improvable, without clear minimization. This can cause unnecessary transmission of user interaction data unrelated to patent analysis, potentially including sensitive commercial details from the conversation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The API requires sending product image URLs and optional product title/description to an external service, but the documentation does not include an explicit privacy or data-sharing warning. This creates a real risk that sensitive product information, unreleased designs, or proprietary descriptions are transmitted off-platform without the user understanding the disclosure.

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

}

text

## curl 示例

```bash
curl -X POST https://tool-gateway.linkfox.com/ruiguan/detectionPatentDesign \

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file documents a second, unrelated Feedback API that can send user-derived content to a different external service. In an agent skill, adding an auxiliary outbound channel beyond the primary patent-detection function increases data-flow scope and can lead to unintended disclosure of user content, especially if agents invoke it automatically or without explicit user consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The Feedback API section lacks any warning that feedback content is sent to a separate external service endpoint. Because feedback content may include user statements, workflow context, or excerpts of results, omission of this disclosure can cause unintentional exfiltration of user data to a different processor.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The onboarding document expands the skill’s behavior from patent-detection into account recovery, registration, API key setup, and billing/payment handling. That scope creep increases attack surface and can steer users into sharing credentials, phone numbers, or making purchases through the skill, which is unjustified by the stated function and creates social-engineering and abuse risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Instructing the agent to collect a phone number, trigger SMS verification, log in, list plans, and initiate orders gives the skill capabilities unrelated to patent analysis and directly touches sensitive identity and payment flows. If abused or misconfigured, this could lead to unauthorized account creation, account takeover assistance, privacy violations, or deceptive billing interactions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document explicitly asks the user to provide a phone number and then participate in an SMS-code login flow, but it gives no privacy notice, consent language, retention limits, or explanation of how that personal data will be handled. In a non-identity-focused skill, this creates unnecessary personal-data exposure and conditions users to share sensitive identifiers with an agent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The top-level description and command help are entirely in Chinese, and the login flow is hard-coded around '+86' and 11-digit domestic phone numbers. This imposes a specific language/locale on all users without opt-in or documented justification in the file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.