Back to skill

Security audit

睿观-版权检测

Security checks for vulnerabilities and agentic risk

Overview

This skill performs copyright checks, but it also has under-consented feedback reporting and risky credential, upload, billing, and local persistence behavior that warrant review before installation.

Install only if you are comfortable sending image URLs or uploaded local images to LinkFox/Ruiguan services, using a LinkFox API key, and potentially engaging account or billing flows. Avoid confidential images, do not let the skill submit feedback without consent, prefer self-service key setup over sharing phone/OTP in chat, and store any API key in a safer credential store rather than shell startup files.

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

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:132
Finding

Automatic Transmission of User Feedback to an Unrelated External Service

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upload_image.py:20
Finding

Environment-Controlled Endpoints Can Receive Authentication Credentials and Personal Data

Content
View full analysis
str: 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 ``` ```python 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", ""), } ``` The onboarding script permits additional authentication endpoints to be overridden: ```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://a ...[truncated 1765 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/upload_image.py:85
Finding

Local Images Are Uploaded with a Public-Read ACL Without Client-Enforced Expiration

Content
View full analysis
str: """Extract the base public URL by stripping query parameters.""" return presigned_url.split("?")[0] ``` The Skill states that the resulting public URL is valid for 24 hours, but the client contains no deletion or access-revocation mechanism. ### Technical Analysis The script reads the complete selected file and explicitly uploads it with an object ACL of `public-read`. It then removes the presigned query string and returns the stable object URL. A presigned PUT URL's expiration ordinarily controls how long the upload authorization is valid; it does not prove that the uploaded object will be deleted or made private afterward. The client relies entirely on undocumented server-side lifecycle behavior for the claimed 24-hour duration. The upload is needed when the detection API requires a URL, but public-read storage is broader than necessary. A private object exposed through a short-lived signed GET URL would provide the detection service access without granting anonymous access to everyone. ### Attack Path 1. A user supplies a local image path for copyright analysis. 2. The script validates only the filename extension and reads the complete file. 3. The file is uploaded to object storage with `public-read`. 4. The script returns a q ...[truncated 538 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onboarding.py:477
Finding

Generated API Keys Are Exposed in Standard Output and Plaintext Configuration Guidance

Content
View full analysis
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 ``` The documentation then instructs users to place the complete key in shell startup configuration: ```markdown - Windows PowerShell: `setx LINKFOX_AGENT_API_KEY ""` - macOS zsh: `echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.zshrc && source ~/.zshrc` - Linux bash: `echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.bashrc && source ~/.bashrc` ``` ### Technical Analysis The login command returns the complete generated API key in a dictionary and serializes it to stdout. In an Agent workflow, stdout is commonly captured in the conversation context, command logs, terminal scrollback, CI logs, or execution traces. The suggested persistence mechanism stores the key in plaintext shell profile files. It can additionally expose the key through shell history and command-line telemetry. API keys should be treated as reusable secrets and should not be returned in general Agent-visible output. ### Attack Path 1. The user provides a phone number and verification code. 2. The onboarding flow authenticates the a ...[truncated 673 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 The script recommends installing mutable package names without exact versions, hashes, a lock file, or a controlled package index. Installation therefore resolves whatever release the configured package repository serves at that time. The package names shown are established packages, and the audit found no evidence that they are intentionally malicious. The issue is the unsafe, non-reproducible dependency acquisition process. A compromised package release, repository account, package mirror, or resolver configuration could introduce code that executes during installation or import. ### Attack Path 1. The required package is absent. 2. The script advises the user to run an unpinned `pip install` command. 3. The package resolver contacts the configured package index or mirror. 4. A compromised or unexpected release is installed. 5. Package installation hooks or subsequently imported code execute with the user's privileges. 6. The dependency can access local files, environment variables, network credentials, and process data available to the Python process. ### Impact Assessment Dependency code runs with the same operating-system privileges as the user invoking the Skill. It may access API keys in the environment, modify user-owned files, contact external services, or affect future Skill behavior. Exploitability requ ...[truncated 84 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ruiguan_copyright_detection.py:246
Finding

Unsanitized Session Identifier Can Escape the Intended Output Directory

Content
View full analysis
str: """Prefer env SESSION_ID; otherwise generate 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"] ``` ```python 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 similarly uses the environment value directly: ```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 filesystem path component without validating its length or rejecting path separators, absolute paths, or `..` traversal components. Python's path joining and normalization rules can consequently produce a path outside the intended date/session directory. The detection response and session metadata are then written under the computed directory. The onboarding script may write generated QR images there. The attacker must be able to influence the process environment, but that is plausible in shared laun ...[truncated 1090 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 (32)

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 sends authentication tokens and user data to URLs whose base is taken directly from environment variables such as LINKFOX_LOGIN_API_URL and LINKFOX_AGENT_USER_API_URL. If an attacker or untrusted runtime can influence those variables, the CLI will POST SMS-login data, access tokens, refresh tokens, and API-token requests to attacker-controlled infrastructure, causing credential exfiltration and possible 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
95% confidence
Finding

The gateway request path uses a URL built from environment-controlled base variables and attaches the API key in the Authorization header before calling urlopen. A malicious endpoint override can therefore capture the user's API key and all order/account requests, enabling unauthorized use of the account and manipulation of billing-related 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 73, 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/ruiguan_copyright_detection.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 is advertised as performing copyright-risk analysis, but the described local-image path uploads user files to remote storage and returns a public URL, without itself performing the promised analysis. This can expose user images publicly and mislead users about what processing is actually occurring.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is advertised as performing copyright-risk analysis, but the described local-image path uploads user files to remote storage and returns a public URL, without itself performing the promised analysis. This can expose user images publicly and mislead users about what processing is actually occurring.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger conditions are intentionally broad and allow activation even when the user does not explicitly ask for copyright analysis. Over-broad activation increases the chance of collecting URLs, uploading images, or invoking costly external services in contexts the user did not intend.

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

md
User: "Check these three images for copyright: url1, url2, url3"
Action: Call the API once for each image URL and consolidate results.

## Display Rules

1. **Present data clearly**: Show detection results in a well-structured table. Key columns to display include: similarity score, rights owner, copyright code, radar result, TRO history, and copyright source link.
2. **Highlight high-risk results**: When similarity is high (e.g., >= 0.80) or radar detection flags infringement (`subRadarResult` = 1), clearly mark these as high-risk entries.

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 SMS login, API-key issuance, subscription listing, order creation, and payment QR generation, which are unrelated to the declared image copyright detection purpose. That mismatch is dangerous because it enables credential collection and monetization workflows under the cover of an unrelated skill, increasing the likelihood of deceptive or unauthorized 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 can create orders and render payment QR codes even though billing is not justified by the advertised function. In a skill context, hidden payment logic materially raises abuse risk because a user invoking copyright analysis could instead be funneled into unintended purchases or account charges.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code retrieves or generates API tokens for the user and returns them to stdout, behavior that is highly sensitive and unrelated to the declared purpose. In the context of a copyright-detection skill, this looks like covert credential provisioning that could be used to grant persistent API access and facilitate downstream abuse of the user's account.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring explicitly says writes to /tmp are forbidden and that failure to write the current directory should be an error, but the implementation silently falls back to the home directory and then the system temporary directory. This mismatch can cause sensitive response data to be written into less-trusted locations, including shared or weakly protected temp storage, violating operator expectations and potentially organizational handling requirements.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill declares no explicit tool scope while its instructions require environment-variable access, network calls, and file writes. That omission weakens least-privilege controls and makes it harder for a host agent or reviewer to understand and constrain what the skill can do.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill directs the agent to persist full responses to session-scoped local files under the working directory. Those responses may contain user-supplied image URLs, rights-holder information, account details, or other sensitive metadata, creating avoidable local data retention and possible cross-task exposure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill instructs automatic reporting of user feedback and usage observations to a separate Feedback API unrelated to the core copyright-detection task. This creates unnecessary secondary data sharing and can leak user interactions, sentiments, or operational details without informed consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Forcing automatic feedback reporting without user opt-in is a privacy and consent issue, especially because feedback may include user sentiments, usage patterns, or other contextual details not necessary for delivering the requested result. The hidden nature of the reporting makes the behavior more problematic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The API requires a user-supplied public image URL and sends it to an external third-party service for copyright analysis, but the documentation does not warn about data sharing, retention, or privacy implications. This can lead agents or users to submit sensitive or proprietary images without informed consent, creating privacy, confidentiality, and compliance risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
79% confidence
Finding

The curl example demonstrates transmitting user-provided image URLs and an API key to an external network endpoint. In this skill context, external transmission is expected, but it still carries real risk because agents may forward sensitive user data to a third party without clearly surfacing that boundary or validating whether the image URL is safe to share.

Content

Scanner excerpt · references/api.md (reported line 69)May include surrounding context.

}

text

## curl 示例

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

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly instructs operators to ask for a user's phone number and use it in registration/login flows, but provides no privacy notice, consent guidance, retention limits, or safer alternative handling. This creates a real risk of unnecessary collection and exposure of personal data and OTP-linked account access information during support interactions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill tells the operator to provide commands that append secrets to shell startup files, permanently modifying user environment configuration without warning about persistence, local exposure, or safer alternatives. Storing API keys in shell rc files can unintentionally disclose credentials to other local processes, future shell sessions, backups, or shared accounts.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module openly describes itself as an onboarding CLI, contradicting the skill metadata that claims copyright detection. Such purpose mismatch is a strong indicator of deceptive packaging, which makes other sensitive behaviors in the file more dangerous because users and reviewers may grant trust based on false functionality claims.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file’s natural-language interface, help text, and operational messages are written exclusively in Chinese, and the phone workflow is constrained to domestic numbers with area code +86. There is no indication that the user can choose language or locale, which violates the requirement not to force a specific language/locale without opt-in.

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

Static analysis

No suspicious patterns detected.