T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/build_swagger_skill.py:191
- Finding
- Documentation credentials can be disclosed to attacker-controlled discovery URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_swagger_skill.py:191-231, 263-286`; `scripts/swagger_client.py:127-157` **Vulnerability Type**: Cross-origin credential disclosure during Swagger specification discovery **Risk Level**: High ### Vulnerable Code ```python def candidate_urls(page_url: str, html: str) -> list[str]: """Extract possible spec URLs from a Swagger UI page.""" candidates: list[str] = [] patterns = [ r"\burl\s*:\s*['\"]([^'\"]+)['\"]", r"\burl\s*=\s*['\"]([^'\"]+)['\"]", r"['\"]url['\"]\s*:\s*['\"]([^'\"]+)['\"]", r"['\"]([^'\"]*(?:v2|v3)/api-docs[^'\"]*)['\"]", r"['\"]([^'\"]*swagger[^'\"]*\.(?:json|yaml|yml))['\"]", r"['\"]([^'\"]*openapi[^'\"]*\.(?:json|yaml|yml))['\"]", ] for pattern in patterns: for match in re.findall(pattern, html, flags=re.IGNORECASE): candidates.append(urljoin(page_url, match)) ``` ```python def expand_swagger_resources( resources: Any, page_url: str, ) -> list[str]: """Convert /swagger-resources payload into candidate spec URLs.""" if not isinstance(resources, list): return [] urls: list[str] = [] for item in resources: if isinstance(item, dict) and item.get("url"): urls.append(urljoin(page_url, str(item["url"]))) return urls ``` ```python auth = source.get("doc_auth") or defaults.get("doc_auth") or DEFAULT_DOC_AUTH timeout = int(source.get("timeout") or defaults.get("timeout") or 30) text, final_url = fetch_text(str(url), auth, timeout) parsed = parse_spec_text(text, final_url) if looks_like_spec(parsed): return parsed, final_url candidates = candidate_urls(final_url, text) for candidate in candidates: try: candidate_text, candidate_final_url = fetch_text(candidate, auth, timeout) except Exception: continue ``` ```python def make_session(auth_config: dict[str, Any] | None = None) -> requests.Session: """Create ...[truncated 2988 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Record the normalized origin of the explicitly configured source URL. 2. Before every authenticated request, compare the destination scheme, host, and effective port with the configured origin. 3. Attach documentation credentials only when the destination is same-origin. 4. Reject cross-origin candidates by default. If cross-origin specifications are required, use an explicit per-source allowlist and do not automatically reuse credentials. 5. Require HTTPS whenever a non-empty username or password is configured. 6. Reject HTTPS-to-HTTP redirects and validate the final response URL. 7. Separate unauthenticated discovery from authenticated retrieval: first validate the destination, then create a credential-bearing session only for an approved URL. 8. Add tests covering absolute URLs in Swagger HTML, cross-origin Swagger resources, redirects, alternate ports, and scheme changes. ]]>
