T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/collect_from_session.py:66
- Finding
- Authenticated session cookie can be transmitted to arbitrary caller-controlled destinations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/collect_from_session.py:66-81, 143-149, 607-626`; related argument forwarding in `scripts/run_digest_pipeline.py:59, 79-85`, `scripts/run_stream_pipeline.py:60, 87-93`, and `scripts/run_browser_bootstrap.py:123-128` **Vulnerability Type**: Unrestricted authenticated network destination / credential exfiltration **Risk Level**: High ### Vulnerable Code ```python def build_request(url: str, token_info: dict): headers = { "Cookie": f"{token_info['cookie_name']}={token_info['cookie_value']}", "User-Agent": token_info.get("user_agent") or DEFAULT_USER_AGENT, "Accept": "application/json, text/plain, */*", "Referer": "https://wx.zsxq.com/", "Origin": "https://wx.zsxq.com", } return urllib.request.Request(url, headers=headers, method="GET") def fetch_url(url: str, token_info: dict, timeout: int): request = build_request(url, token_info) context = ssl.create_default_context() try: with urllib.request.urlopen(request, timeout=timeout, context=context) as response: status_code = getattr(response, "status", 200) body = response.read().decode("utf-8", errors="replace") content_type = response.headers.get("Content-Type", "") return status_code, content_type, body ``` ```python def api_get(path: str, token_info: dict, timeout: int, api_base: str, retries: int = DEFAULT_API_RETRIES, retry_delay: float = DEFAULT_API_RETRY_DELAY): url = urllib.parse.urljoin(api_base.rstrip("/") + "/", path.lstrip("/")) last_error: Optional[SessionError] = None attempts = max(1, retries) for attempt in range(attempts): try: status_code, content_type, body = fetch_url(url, token_info, timeout) ``` ```python parser.add_argument("--token-file", required=True, help="Path to state/session.token.json") parser.add_argument("--mode", choices=["probe", "groups", "group-topics", "multi ...[truncated 3739 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Enforce an explicit destination allowlist** - Permit API requests only to `https://api.zsxq.com`. - If probe functionality is retained, allow only explicitly approved HTTPS ZSXQ hosts such as `api.zsxq.com` and `wx.zsxq.com`. - Compare normalized hostnames exactly; do not use suffix checks that would accept domains such as `zsxq.com.attacker.example`. 2. **Validate the complete URL** - Require the `https` scheme. - Reject user-information components. - Reject unexpected ports. - Normalize internationalized domain names before comparison. - Reject malformed, relative, or protocol-relative URLs. 3. **Control redirects** - Disable automatic redirects for authenticated requests, or validate every redirect destination. - Never forward the cookie when the origin changes. - Apply a strict redirect-count limit. 4. **Reduce the public interface** - Remove authenticated arbitrary-URL probe mode from normal workflows. - Remove or restrict `--api-base`, `--verify-url`, and equivalent options. - If a custom API base is required for development, place it behind an explicit unsafe-development flag and refuse to attach production credentials. 5. **Bind credentials to their expected domain** - Validate the token file’s domain against an approved ZSXQ domain. - Construct authenticated requests through a dedicated ZSXQ client rather than a general-purpose URL fetcher. 6. **Add regression tests** - Confirm that attacker domains, subdomain tricks, HTTP URLs, custom ports, user-information URLs, and cross-origin redirects are rejected before any request is sent. ]]>
