T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/remove-metadata-from-pdf.py:60
- Finding
- Unrestricted API Endpoint Override Can Exfiltrate PDF Documents and Bearer Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/remove-metadata-from-pdf.py:60-71` and `scripts/remove-metadata-from-pdf.py:207-212` **Vulnerability Type**: Unrestricted sensitive-data destination and credential disclosure **Risk Level**: High ### Vulnerable Code ```python def create_job( base_url: str, api_key: str, pdf_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 PDFs under the SAME key: "files" files: List[Tuple[str, Tuple[str, Any, str]]] = [] opened = [] try: for p in pdf_paths: f = open(p, "rb") opened.append(f) files.append(("files", (os.path.basename(p), f, "application/pdf"))) resp = requests.post(url, headers=headers, files=files, timeout=timeout_s) ``` The destination is obtained from an unrestricted command-line argument or environment variable: ```python ap.add_argument( "--base-url", default=os.getenv("SOLUTIONS_BASE_URL", DEFAULT_BASE_URL), help="Base URL override", ) ``` ### Technical Analysis The Skill is declared to upload PDF files to a specific Solutions API endpoint. However, its implementation permits `base_url` to be replaced with an arbitrary value through either `--base-url` or `SOLUTIONS_BASE_URL`. The selected URL is used without validating its scheme or hostname. The script subsequently transmits two sensitive assets to that destination: 1. Every user-selected PDF file, as multipart form data. 2. The Solutions API key, in the `Authorization: Bearer` header. This exceeds the minimum privileges required for the declared functionality. Production operation requires access only to the documented Solutions API host, not permission to disclose credentials and documents to an arbitrary network destination. The absence of HTTPS enforcement also permits a caller to select a plaintext HTTP e ...[truncated 1805 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the production `--base-url` option and `SOLUTIONS_BASE_URL` override. Use the documented service URL as a fixed constant. 2. If endpoint overrides are required for development or testing: - Disable them by default. - Require an explicit development-mode flag. - Reject overrides in production builds. - Restrict destinations to an allowlist of approved hostnames. 3. Parse the destination with `urllib.parse.urlparse` and require: - The `https` scheme. - The exact approved hostname. - An expected port. - No embedded username or password. 4. Validate the final URL after all path joining and normalization, immediately before every request. 5. Ensure redirects cannot forward the bearer token or upload to an unapproved host. Prefer disabling redirects for these API calls or validating every redirect destination. 6. Inform the user clearly that the selected documents will leave the local system and identify the approved destination before uploading. 7. Prefer environment-based or secure secret-store credential input over command-line API keys, because command-line arguments can be exposed through process listings and shell history. 8. Add automated tests confirming that HTTP URLs, unapproved domains, user-information URLs, and redirect attempts are rejected. 9. Revoke and rotate any API key suspected of having been used with an untrusted endpoint. ]]>
