T09 · Insecure Skill Coding Practices
- Location
scripts/batch_clone.py:26- Finding
API Tokens Can Be Transmitted to Arbitrary or Plaintext HTTP Hosts
- Content
View full analysis
dict | list: """发送 GET 请求,返回解析后的 JSON auth_type: 'bearer'(GitHub/GitLab/Gitea/Bitbucket)或 'basic'(Azure DevOps) """ headers = {"Accept": accept, "User-Agent": "git-manager-skill/1.0"} if token: if auth_type == "basic": # Azure DevOps: Basic Base64(":PAT") encoded = base64.b64encode(f":{token}".encode()).decode() headers["Authorization"] = f"Basic {encoded}" else: headers["Authorization"] = f"Bearer {token}" headers["PRIVATE-TOKEN"] = token # GitLab 兼容 req = Request(url, headers=headers) try: with urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode()) ``` The destination host is constructed from a user-controlled argument without scheme or origin validation: ```python elif args.platform == "gitlab": host = args.host.rstrip("/") if args.host else "https://gitlab.com" elif args.platform == "gitea": if not args.host: print("[ERROR] Gitea 需要指定 --host 参数") sys.exit(1) host = args.host.rstrip("/") ``` ### Technical Analysis GitLab and Gitea legitimately support self-hosted instances, so accepting a configurable host is consistent with the declared functionality. However, the implementation attaches the supplied API token to requests without requiring HTTPS or validating the normalized destination. A caller can therefore select a plaintext `http://` endpoint or an unrelated attacker-controlled HTTPS host. The request then includes the token in `Authorization` and, for non-Basic authentication, also in `PRIVATE-TOKEN`. Sending both headers to every bea ...[truncated 2089 chars]- Remediation
View remediation
