T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/mopng_agent.py:20
- Finding
- API Key Disclosure Through an Unrestricted Configurable Base URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mopng_agent.py`, lines 20–55 **Vulnerability Type**: Unrestricted credential-bearing network destination **Risk Level**: High ### Vulnerable Code ```python class AgentClient: def __init__(self, base_url: str, api_key: str, timeout: float = 90) -> None: self.base_url = base_url.rstrip("/") self.api_key = api_key self.timeout = timeout def call(self, method: str, path: str, body: dict | None = None) -> dict: headers = {"Accept": "application/json", "X-API-Key": self.api_key} data = None if body is not None: data = json.dumps(body, ensure_ascii=False).encode("utf-8") headers["Content-Type"] = "application/json" req = request.Request( f"{self.base_url}{API_PREFIX}{path}", data=data, headers=headers, method=method, ) try: with request.urlopen(req, timeout=self.timeout) as response: # nosec B310 — base URL is operator configuration raw = response.read().decode("utf-8") except error.HTTPError as exc: detail = exc.read().decode("utf-8", "replace") raise RuntimeError(f"motu-agent HTTP {exc.code}: {detail}") from exc except error.URLError as exc: raise RuntimeError(f"motu-agent unavailable: {exc.reason}") from exc if not raw: return {} try: return json.loads(raw) except json.JSONDecodeError as exc: raise RuntimeError("motu-agent returned non-JSON data") from exc def _client(args: argparse.Namespace) -> AgentClient: key = os.getenv("MOPNG_API_KEY") if not key: raise ValueError("MOPNG_API_KEY is required") return AgentClient(os.getenv("MOPNG_AGENT_BASE_URL", DEFAULT_BASE_URL), key, args.timeout) ``` ### Technical Analysis The client obtains `MOPNG_AGENT_BASE_URL` directly from the environment and u ...[truncated 1765 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse `MOPNG_AGENT_BASE_URL` before constructing the client. 2. Require the `https` scheme in production. 3. Reject URLs containing a username, password, query string, or fragment. 4. Allowlist `agent-api.mopng.cn` by default. 5. If custom deployments are required, introduce an explicit allowlist such as `MOPNG_ALLOWED_AGENT_HOSTS`. 6. Reject loopback, private, reserved, multicast, link-local, and cloud metadata addresses. 7. Resolve hostnames and validate every resolved address to prevent private-address resolution. 8. Ensure redirects are either disabled or revalidated before forwarding authentication headers. 9. Never forward `X-API-Key` across an origin-changing redirect. 10. Add tests covering HTTP URLs, arbitrary external hosts, embedded credentials, private IPs, metadata endpoints, and redirects. ]]>
