T09 · Insecure Skill Coding Practices
Error
- Location
- assets/templates/openclaw_autopilot.py:381
- Finding
- GitHub Token Disclosure to an Arbitrary HTTPS Host<![CDATA[ ## Vulnerability Details **File Location**: `assets/templates/openclaw_autopilot.py:381-385`, with credential-bearing Git operations at `assets/templates/openclaw_autopilot.py:446-477` and `assets/templates/openclaw_autopilot.py:910-1002` **Vulnerability Type**: Insufficient destination validation before transmitting credentials **Risk Level**: High ### Vulnerable Code ```python def inject_token_to_https_url(repo_url: str, token: str) -> str: if not repo_url.startswith("https://"): raise ValueError("Only https:// GitHub URLs are supported for token auth.") safe_token = quote(token, safe="") return repo_url.replace("https://", f"https://x-access-token:{safe_token}@", 1) ``` The resulting credential-bearing URL is used for Git operations: ```python def ensure_repo_synced(cfg: RuntimeConfig, token: str, logger: EventLogger) -> Tuple[bool, Path, str]: cfg.working_root.mkdir(parents=True, exist_ok=True) repo_dir = cfg.working_root / repo_name_from_url(cfg.repo_url) auth_url = inject_token_to_https_url(cfg.repo_url, token) if not (repo_dir / ".git").exists(): code, out = run_cmd(["git", "clone", auth_url, str(repo_dir)], timeout=600) logger.log("repo.clone", ok=(code == 0), output=out[-800:]) if code != 0: return False, repo_dir, "clone_failed" # Remove token from local git config remote. run_cmd(["git", "remote", "set-url", "origin", cfg.repo_url], cwd=repo_dir) ``` It is also used when pushing changes: ```python def commit_and_push( repo_dir: Path, cfg: RuntimeConfig, token: str, audit: AuditResult, logger: EventLogger, ) -> Tuple[bool, str, Optional[str]]: auth_url = inject_token_to_https_url(cfg.repo_url, token) # ... code, out = run_cmd(["git", "push", auth_url, f"{cfg.branch}:{cfg.branch}"], cwd=repo_dir, timeout=300) logger.log("git.push", ok=(code == 0), output=out[-1000:]) ``` Runtime startup only rejects placeholder v ...[truncated 2618 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse repository URLs using `urllib.parse.urlsplit()` rather than string-prefix checks. 2. Require all of the following before any credential is used: - Scheme is exactly `https`. - Hostname is exactly `github.com`. - No preexisting username or password is present. - No unexpected port, fragment, or malformed path is present. - The path conforms to an expected GitHub `owner/repository.git` structure. 3. Apply this validation in the runtime immediately after loading command-line overrides. Do not rely on the optional doctor script. 4. Avoid embedding tokens in URLs. Prefer an ephemeral `GIT_ASKPASS` helper, a properly configured credential helper, or another mechanism that does not expose the token in command arguments or error output. 5. Use a fine-grained GitHub token limited to the target repository, required contents permission, and intended branch workflow. 6. Ensure clone, fetch, and push all use the same validated GitHub destination. 7. Add negative tests for attacker-controlled hosts, deceptive subdomains such as `github.com.attacker.example`, userinfo-based URLs, unexpected ports, and malformed URLs. 8. Rotate any token that may already have been used with an untrusted repository URL. ]]>
