T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/qb.py:41
- Finding
- API Key Disclosure Through an Unrestricted API Base URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/qb.py:41-61` **Additional References**: `scripts/qb.py:428-429`, `SKILL.md:30-31`, `README.md:17-20` **Vulnerability Type**: Credential disclosure through an unvalidated network destination **Risk Level**: High ### Vulnerable Code ```python def cfg(args): base = (getattr(args, "base", None) or os.environ.get("QB_API_BASE") or DEFAULT_BASE).rstrip("/") key = getattr(args, "key", None) or os.environ.get("QB_API_KEY") or "" timeout = getattr(args, "timeout", None) or int(os.environ.get("QB_TIMEOUT", "30")) return base, key, timeout def post(base, key, timeout, path, payload=None, raw=False, out_path=None, dry_run=False): url = base + path body = json.dumps(payload or {}).encode("utf-8") if dry_run or DRY: print(f"[dry-run] POST {url}\n body={payload}", file=sys.stderr) return None req = urllib.request.Request(url, data=body, method="POST") req.add_header("Content-Type", "application/json") if key: req.add_header("X-API-Key", key) last = None for attempt in range(3): try: with urllib.request.urlopen(req, timeout=timeout) as r: ``` The unrestricted configuration is exposed through these arguments: ```python common.add_argument("--base") common.add_argument("--key") ``` ### Technical Analysis The client permits `QB_API_BASE` or `--base` to specify an arbitrary URL. The value is only processed with `rstrip("/")`; it is not parsed or validated for: - An HTTPS scheme - The expected vendor hostname - An approved port - Embedded username or password components - Unexpected path components - Redirects to a different origin The `post()` function then appends a fixed API path and attaches the user's `X-API-Key` header to the resulting request. Consequently, anyone who controls or influences the base URL controls the destination that receives the API credential and request body. Sending the API key to ...[truncated 1956 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the base URL with `urllib.parse.urlsplit()` rather than concatenating an unchecked string. 2. Require `scheme == "https"` and reject HTTP or unsupported schemes. 3. Pin the default production hostname, such as `api.xuekubao.com`. 4. If alternative gateways are operationally required, use an explicit hostname allowlist rather than accepting arbitrary destinations. 5. Reject URLs containing user-information, fragments, query strings, or unexpected base paths. 6. Restrict ports to approved TLS ports unless a trusted administrator explicitly configures otherwise. 7. Require an explicit confirmation before sending credentials to any non-default approved gateway. 8. Disable cross-origin redirects or verify every redirect destination before forwarding `X-API-Key`. 9. Construct endpoint URLs using safe URL-parsing and joining logic. 10. Add tests proving that HTTP URLs, attacker-controlled hosts, embedded credentials, and redirect-based host changes are rejected. ]]>
