Back to skill

Security audit

Convert to PDF

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its document-to-PDF purpose, but it deserves review because it uploads documents and an API key to a remote service and the helper script can be redirected to an arbitrary URL.

Review this before installing. Use it only for documents you are allowed to send to Cross-Service-Solutions, protect the API key, avoid passing the key in shell history, and do not set SOLUTIONS_BASE_URL or --base-url unless you fully trust and control the destination. Sensitive, regulated, or confidential files should not be converted with this skill without approval and a clear understanding of the provider's retention and privacy terms.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/convert-to-pdf.py:46
Finding
Unrestricted Base URL Override Can Disclose Documents and API Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/convert-to-pdf.py`, lines 46-62, 77-84, and 213-216 **Vulnerability Type**: Unvalidated destination for sensitive network transfers **Risk Level**: High ### Vulnerable Code ```python def create_job( base_url: str, api_key: str, file_paths: List[str], timeout_s: int = 180, ) -> Dict[str, Any]: url = base_url.rstrip("/") + CREATE_PATH headers = make_headers(api_key) # multipart/form-data with multiple files under the SAME key: "files" files: List[Tuple[str, Tuple[str, Any, str]]] = [] opened = [] # We don't enforce input mime types; use octet-stream for broad compatibility. try: for p in file_paths: f = open(p, "rb") opened.append(f) files.append(("files", (os.path.basename(p), f, "application/octet-stream"))) resp = requests.post(url, headers=headers, files=files, timeout=timeout_s) ``` ```python def get_job( base_url: str, api_key: str, job_id: Any, timeout_s: int = 30, ) -> Dict[str, Any]: url = base_url.rstrip("/") + f"/api/{job_id}" headers = make_headers(api_key) resp = requests.get(url, headers=headers, timeout=timeout_s) ``` ```python ap.add_argument( "--base-url", default=os.getenv("SOLUTIONS_BASE_URL", DEFAULT_BASE_URL), help="Base URL override", ) ``` ### Technical Analysis The conversion workflow legitimately requires transmitting selected documents and a Bearer API key to the documented Solutions API. However, the destination is configurable through both the `--base-url` command-line argument and the `SOLUTIONS_BASE_URL` environment variable. The supplied URL is used without validation of its scheme, hostname, port, or relationship to the expected API domain. Consequently, it may reference: - An attacker-controlled HTTPS server. - A plaintext HTTP endpoint, exposing data to network interception. - An unexpected internal service reachable from ...[truncated 2436 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove arbitrary endpoint overrides where possible** - Always use the documented `DEFAULT_BASE_URL` in production. - Remove `--base-url` and `SOLUTIONS_BASE_URL` if alternate deployments are not a strict operational requirement. 2. **Apply a destination allowlist** - Parse the URL with `urllib.parse.urlsplit()`. - Require the normalized hostname to equal an explicitly approved API hostname. - Do not use suffix-only checks such as `hostname.endswith("trusted.example")` unless subdomains are intentionally trusted. - Reject URLs containing user information, fragments, or unexpected ports. 3. **Enforce transport security** - Require the `https` scheme. - Reject plaintext HTTP even for configurable development endpoints. - Retain TLS certificate verification and do not introduce `verify=False`. 4. **Separate credentials by destination** - Never forward the production Solutions API key to an alternate endpoint. - If alternate endpoints are required, provision separate least-privilege credentials for each approved host. 5. **Require explicit approval for non-default destinations** - Display the normalized destination before any document or credential is transmitted. - Require an explicit user confirmation when the destination differs from the official service. - Clearly disclose that selected documents are uploaded to a third party. 6. **Minimize token exposure** - Prefer environment-based secret input over `--api-key`, because command-line arguments may be visible in process listings or shell history. - Use narrowly scoped and short-lived API tokens where supported. - Continue avoiding credential values in logs and error messages. 7. **Add security tests** - Verify that HTTP URLs, attacker-controlled domains, embedded credentials, malformed URLs, and unauthorized ports are rejected. - Verify that no network request occurs before destination validation succeeds. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (11)

Lp1

High
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The script makes outbound network requests to a third-party service but the network capability is not covered by declared permissions. In an agent environment this is dangerous because it enables data exfiltration or remote interaction without an explicit permission boundary, especially since the skill uploads user-provided local files.

Lp1

High
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The script makes outbound network requests to a third-party service but the network capability is not covered by declared permissions. In an agent environment this is dangerous because it enables data exfiltration or remote interaction without an explicit permission boundary, especially since the skill uploads user-provided local files.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README explicitly instructs users to upload documents to a third-party service but does not clearly warn that potentially sensitive user files will leave the local environment and be transmitted to an external provider. In a file-conversion skill, users may reasonably supply confidential business documents, so omission of an explicit third-party data handling warning creates a meaningful privacy and data-governance risk.

External Transmission

Medium
Category
Data Exfiltration
Content
## How it works
1) Upload files to:
   `POST https://api.xss-cross-service-solutions.com/solutions/solutions/api/31`
2) Poll:
   `GET  https://api.xss-cross-service-solutions.com/solutions/solutions/api/<job_id>`
3) Return `output.files[].path` as download URL(s)
Confidence
90% confidence
Finding
This endpoint documents that user-supplied files are sent to an external domain for processing, which is a real external data transmission path. In the context of document conversion, this is expected functionality, but it remains security-relevant because the transferred content may contain sensitive data and the README does not provide strong disclosure or usage constraints.

External Transmission

Medium
Category
Data Exfiltration
Content
1) Upload files to:
   `POST https://api.xss-cross-service-solutions.com/solutions/solutions/api/31`
2) Poll:
   `GET  https://api.xss-cross-service-solutions.com/solutions/solutions/api/<job_id>`
3) Return `output.files[].path` as download URL(s)

## Script (CLI)
Confidence
88% confidence
Finding
The polling endpoint confirms ongoing interaction with the same external service and therefore reinforces that document metadata and job identifiers are exchanged with a third party. While necessary for the skill's operation, this still represents a genuine data-flow risk because users may not appreciate that processing status and output retrieval are tied to an outside service.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill uploads user-provided documents to an external third-party API, but the user-facing description does not clearly warn about that data transfer at the point of use. This can cause users to unknowingly send sensitive documents outside the local environment or trusted platform boundary, creating confidentiality and compliance risks.

External Transmission

Medium
Category
Data Exfiltration
Content
## API endpoints
Base URL:
- `https://api.xss-cross-service-solutions.com/solutions/solutions`

Create convert job:
- `POST /api/31`
Confidence
94% confidence
Finding
The skill is explicitly designed to transmit documents to an external service endpoint, which creates real data exposure risk because file contents leave the agent's environment and are handled by a third party. In this document-processing context, that behavior is expected, but it is still security-relevant and dangerous if users assume files are processed locally or do not understand the trust boundary.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This skill's core behavior is to upload local documents to a remote conversion API, yet there is no strong user-facing warning at execution time that file contents leave the local environment. That creates a real privacy and confidentiality risk if users supply sensitive documents expecting a local conversion workflow.

External Transmission

Medium
Category
Data Exfiltration
Content
import requests


DEFAULT_BASE_URL = "https://api.xss-cross-service-solutions.com/solutions/solutions"
CREATE_PATH = "/api/31"
Confidence
88% confidence
Finding
The hardcoded external endpoint confirms that the skill transmits data to an outside service. External transmission is expected for this skill's purpose, but it remains security-relevant because uploaded documents and metadata are sent off-host and returned as remote download URLs.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.32.0
Confidence
96% confidence
Finding
The dependency is specified as `requests>=2.32.0`, which allows future versions to be installed without review and prevents reproducible builds. In a security-sensitive skill that uploads documents to an external service, this increases supply-chain risk and makes it harder to verify whether a deployed version includes security fixes or breaking changes.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding
Because `requests` is not pinned, it is impossible to determine from this manifest whether the installed version is affected by known advisories. This is more concerning in this skill's context because it handles document uploads and likely processes remote URLs/responses, so using an affected `requests` release could expose credentials, transport security, or request-handling weaknesses.

Static analysis

No suspicious patterns detected.