T09 · Insecure Skill Coding Practices
Error
- Location
- runtime.py:139
- Finding
- Article Frontmatter Can Redirect Credential-Bearing Image Generation Requests<![CDATA[ ## Vulnerability Details **File Location**: `runtime.py:31-43`, `runtime.py:139-164`, and `runtime.py:184-218` **Vulnerability Type**: Unvalidated externally controlled API endpoint **Risk Level**: High ### Vulnerable Code ```python def run_json_command( args: list[str], *, cwd: Path | None = None, env_overrides: dict[str, str] | None = None, ) -> dict[str, Any]: env = os.environ.copy() if env_overrides: env.update({key: value for key, value in env_overrides.items() if str(value or "").strip()}) result = subprocess.run( args, check=False, capture_output=True, text=True, cwd=str(cwd) if cwd else None, env=env, ) ``` ```python def resolve_image_backend( *, article_path: Path, image_provider: str | None = None, image_api_base: str | None = None, image_model: str | None = None, ) -> dict[str, str]: defaults = default_image_backend() frontmatter = load_article_frontmatter(article_path) frontmatter_provider = clean_optional_value(frontmatter.get("image_provider")) frontmatter_api_base = clean_optional_value(frontmatter.get("image_api_base")) frontmatter_model = clean_optional_value(frontmatter.get("image_model")) requested_provider = clean_optional_value(image_provider) requested_api_base = clean_optional_value(image_api_base) requested_model = clean_optional_value(image_model) provider = requested_provider or frontmatter_provider or defaults["provider"] api_base = requested_api_base or frontmatter_api_base or defaults["apiBase"] model = requested_model or frontmatter_model or defaults["model"] ``` ```python image_backend = resolve_image_backend( article_path=article_path, image_provider=image_provider, image_api_base=image_api_base, image_model=image_model, ) command = [ "md2wechat", "generate_image", "--preset", preset, ...[truncated 3494 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not allow article frontmatter to select an arbitrary API base. Treat endpoint configuration as trusted administrator configuration rather than article content. 2. If per-article endpoints are required, enforce an explicit allowlist of approved HTTPS hostnames and ports. 3. Parse and canonicalize the URL before use. Reject: - Non-HTTPS schemes - Embedded credentials - Loopback, private, link-local, multicast, and unspecified addresses - Cloud metadata endpoints - Unexpected ports 4. Resolve the hostname and validate every resolved address. Repeat destination validation after redirects to reduce DNS rebinding and redirect-based bypasses. 5. Pass a minimal subprocess environment instead of `os.environ.copy()`. Include only variables required for execution. 6. Scope provider credentials to one approved provider and endpoint where possible. Avoid forwarding a credential when a non-default endpoint is selected. 7. Separate trusted runtime overrides from article-controlled metadata and record endpoint-selection decisions in security logs without logging secrets. 8. Add tests proving that malicious frontmatter values such as loopback URLs, `file:` URLs, internal IP addresses, and unapproved domains are rejected. ]]>
