T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/change-pdf-permissions.py:207
- Finding
- Arbitrary API Endpoint Can Receive Sensitive PDFs and Bearer Tokens<![CDATA[ ## Vulnerability Details **File Location**: `scripts/change-pdf-permissions.py:85-92`, `scripts/change-pdf-permissions.py:108-112`, and `scripts/change-pdf-permissions.py:207-210` **Vulnerability Type**: Unrestricted sensitive-data destination **Risk Level**: High ### Vulnerable Code ```python def create_job( base_url: str, api_key: str, pdf_path: str, permissions: Dict[str, bool], timeout_s: int = 180, ) -> Dict[str, Any]: url = base_url.rstrip("/") + CREATE_PATH headers = make_headers(api_key) data = {k: bool_to_api(bool(v)) for k, v in permissions.items()} with open(pdf_path, "rb") as f: files = {"file": (os.path.basename(pdf_path), f, "application/pdf")} resp = requests.post(url, headers=headers, files=files, data=data, 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 Skill's declared functionality requires uploading a user-selected PDF and an API bearer token to the documented Solutions API. That transfer is necessary for the remote-processing design and is disclosed in `SKILL.md`. However, the implementation permits the destination to be replaced through either the `--base-url` command-line argument or the `SOLUTIONS_BASE_URL` environment variable. It does not validate the URL scheme, hostname, port, or expected path before attaching the bearer token and PDF to the request. Consequently, an attacker who can influence the invocation arguments or process environment can redirect the request to an arbitrary server. An `http://` destination would also send the data without ...[truncated 1497 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `--base-url` and `SOLUTIONS_BASE_URL` support if alternate service deployments are not a documented requirement. 2. Otherwise, parse the configured URL with `urllib.parse.urlparse` and enforce: - The `https` scheme. - The exact approved hostname. - The expected port. - The documented base path. - No embedded username or password. 3. Reject malformed URLs, plain HTTP, IP-literal substitutions, lookalike domains, unexpected ports, and URLs containing fragments. 4. Disable automatic redirects for authenticated uploads, or validate every redirect destination before resending sensitive content. 5. Attach the `Authorization` header only after destination validation. 6. Consider requiring an explicit, interactive confirmation before uploading a document to any non-default deployment. 7. Document clearly that PDFs are transferred to a third-party processor, including applicable retention and privacy implications. 8. Add tests confirming that attacker-controlled hosts and plaintext URLs are rejected before the file is opened or any credential is transmitted. ]]>
