Back to skill

Security audit

PatSight-MolVision

Security checks for vulnerabilities and agentic risk

Overview

This skill performs the advertised molecular image recognition, but it can send account credentials, tokens, and uploaded molecular images to configurable network destinations without strong scoping.

Review before installing. Use only trusted PatSight endpoints, avoid command-line passwords or tokens, prefer short-lived credentials, and do not upload confidential or unpublished molecular structures unless your organization approves sending them to the external service and storing local result files.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_ocsr.py:208
Finding

Unrestricted API Base URL Can Disclose Tokens and Molecular Images

Content
View full analysis
Dict[str, Any]: """POST 到 /patent/api/v1/u/extractor/image/molecules,必须传有效 token(与 patsight 一致获取)。""" if not base_url: raise ValueError("Missing base URL. Set --base-url or PATSIGHT_BASE_URL.") base_url = base_url.rstrip("/") if "patent.xinsight-ai.com" in base_url and "/patent/api" not in base_url: base_url = f"{base_url}/patent/api" auth_token = get_valid_token(token=token, account=account, password=password) url = f"{base_url}/v1/u/extractor/image/molecules" params = {"request_id": request_id} files = [] handles = [] try: for path in images: fh = open(path, "rb") handles.append(fh) files.append(("image", (path.name, fh, guess_mime(path)))) files.append(("label", (None, "molvision"))) response = requests.post( url, params=params, files=files, headers={ "Accept": "application/json", "Authorization": auth_token, }, timeout=timeout, ) ``` The destination originates from an unrestricted command-line option or environment variable: ```python p.add_argument( "--base-url", default=DEFAULT_PATENT_BASE_URL, help="Patent API base URL (default: PATSIGHT_BASE_URL)", ) ``` ### Technical Analysis The script accepts any `--base-url` value without validating its scheme, host, port, resolved IP address, or redirect behavior. It then sends both the PatSight authoriz ...[truncated 2350 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_ocsr.py:23
Finding

Configurable Authentication Endpoints Can Capture Account Passwords and Tokens

Content
View full analysis
Dict[str, Any]: if not account or not password: raise ValueError("Missing OPS account or password. Set PATSIGHT_ACCOUNT and PATSIGHT_PASSWORD.") credential = _encode_credential_from_password(password) headers = { "Accept": "application/json, text/plain, */*", "Content-Type": "application/json", } resp = requests.post( ops_token_url, json={"account": account, "credential": credential}, headers=headers, timeout=30, ) resp.raise_for_status() return resp.json() def _verify_ops_token( token: str, verify_url: str = DEFAULT_OPS_VERIFY_URL, ) -> Dict[str, Any]: if not token: raise ValueError("Empty token cannot be verified.") body_token = base64.b64encode(token.encode("utf-8")).decode("utf-8") resp = requests.post( verify_url, json={"token": body_token, "from": "login"}, headers={"Content-Type": "application/json"}, timeout=30, ) resp.raise_for_status() return resp.json() ``` ### Technical Analysis `PATSIGHT_OPS_TOKEN_URL` and `PATSIGHT_OPS_VERIFY_URL` completely control where authentication material is transmitted. Neither destination is validated or restricted to the documented OPS service. The passwo ...[truncated 2710 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run_ocsr.py:75
Finding

Command-Line Credential Options Expose Secrets Through Process and Shell Metadata

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Tainted flow: 'account' from os.environ.get (line 163, credential/environment) → requests.post (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/run_ocsr.py (reported line 127)May include surrounding context.

python
"Accept": "application/json, text/plain, */*",
        "Content-Type": "application/json",
    }
    resp = requests.post(
        ops_token_url,
        json={"account": account, "credential": credential},
        headers=headers,

Tainted flow: 'auth_token' from os.environ.get (line 202, credential/environment) → requests.post (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/run_ocsr.py (reported line 215)May include surrounding context.

python
files.append(("image", (path.name, fh, guess_mime(path))))
        files.append(("label", (None, "molvision")))

        response = requests.post(
            url,
            params=params,
            files=files,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to send molecular structure images and authentication material to a third-party PatSight API, but it does not explicitly warn that uploaded scientific data and credentials are transmitted off-box to an external service. In a chemistry/patent workflow, those images may contain confidential research or pre-publication IP, so the missing privacy/transmission warning can cause inadvertent disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README explicitly shows passing account passwords on the command line, which can expose secrets through shell history, process listings, audit logs, and shared terminal recordings. Because this skill uses external API credentials, this practice increases the chance of credential theft and unauthorized access to the PatSight account.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill clearly relies on sensitive capabilities—environment secrets, outbound network access to a third-party API, and file output—but does not declare any explicit tool scope or allowed-tools boundary. This weakens least-privilege controls and makes it easier for an agent runtime or reviewer to miss that the skill can access credentials, transmit data externally, and write artifacts locally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documentation says it calls the PatSight API, but it does not prominently warn users that uploaded molecular images and request metadata will be sent to an external service. In a chemistry/IP context, those images may contain proprietary or confidential structures, so inadequate disclosure can cause unintended data exfiltration and compliance/privacy issues.

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/run_ocsr.py (reported line 127)May include surrounding context.

python
"Accept": "application/json, text/plain, */*",
        "Content-Type": "application/json",
    }
    resp = requests.post(
        ops_token_url,
        json={"account": account, "credential": credential},
        headers=headers,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script sends credentials and uploaded molecular images to external services but gives no explicit user-facing notice at runtime. In an agent skill context, this can cause unintentional disclosure of sensitive research data or credentials because users may not realize the operation is remote rather than local.

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/run_ocsr.py (reported line 144)May include surrounding context.

python
if not token:
        raise ValueError("Empty token cannot be verified.")
    body_token = base64.b64encode(token.encode("utf-8")).decode("utf-8")
    resp = requests.post(
        verify_url,
        json={"token": body_token, "from": "login"},
        headers={"Content-Type": "application/json"},

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The script implicitly reads PATSIGHT_TOKEN, PATSIGHT_ACCOUNT, and PATSIGHT_PASSWORD from the environment without prominently informing the user. In automated agent environments, silent credential pickup can lead to unintended use of privileged secrets and surprise outbound authentication.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file contains user-facing natural-language content entirely in Chinese, but does not indicate that the skill is region-specific or provide any user opt-in for language/locale. Under the policy for natural-language violations, forcing a specific language without user choice can be a locale policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill name and tagline are presented in Chinese while the description is primarily in English, but the manifest does not explain whether the skill is intended for a specific locale or whether users can choose their preferred language. This can create a language-policy issue because the user-facing experience appears to impose mixed-language content without explicit opt-in or justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The tool stores raw API results and a rendered PNG report to local disk without warning, which may persist sensitive molecular structures and derived properties. This is a privacy and data-handling risk, especially on shared systems or managed agent runners.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.