T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/git/repository.py:53
- Finding
- GitHub Token Disclosure to Attacker-Controlled Hosts Through Weak Host Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/git/repository.py:53-70` **Vulnerability Type**: Credential disclosure through improper URL validation **Risk Level**: Critical ### Complete Code Snippet ```python def _make_authenticated_url(self, repo_url: str) -> str: """Convert repo URL to use authentication if token is provided""" if not self.token or 'github.com' not in repo_url: return repo_url # Remove .git suffix for consistency repo_url = repo_url.rstrip('/') if repo_url.endswith('.git'): repo_url = repo_url[:-4] if '@' in repo_url and '://' in repo_url: parts = repo_url.split('://') # Re-add token return f"{parts[0]}://x-access-token:{self.token}@{parts[1].split('@')[1]}" if repo_url.startswith('https://'): return repo_url.replace('https://', f'https://x-access-token:{self.token}@') elif repo_url.startswith('http://'): return repo_url.replace('http://', f'https://x-access-token:{self.token}@') return repo_url ``` The credential-bearing URL is subsequently used as a Git remote: ```python auth_url = self._make_authenticated_url(repo_url) subprocess.run( ['git', 'remote', 'add', 'origin', auth_url], cwd=target_dir, capture_output=True, timeout=30 ) ``` ### Technical Analysis The code decides whether a repository is hosted by GitHub using the substring condition: ```python 'github.com' in repo_url ``` This does not validate the parsed network hostname. Attacker-controlled addresses such as the following pass the test: ```text https://github.com.attacker.example/repository https://attacker.example/path/github.com/repository ``` For an HTTPS input, the function inserts `GITHUB_TOKEN` into the URL before Git accesses it. Git may therefore transmit the token as HTTP authentication data to an attacker-controlled server. The arbitrary repository URL is accepted directly from the command line without a trusted-host al ...[truncated 1149 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse repository URLs with `urllib.parse.urlsplit()` rather than using substring matching. 2. Require the scheme to be exactly `https`. 3. Require the normalized hostname to be exactly `github.com`, or use a narrowly configured allowlist for trusted GitHub Enterprise hosts. 4. Reject URLs containing unexpected user information, malformed ports, encoded hostname components, fragments, or ambiguous parsing constructs. 5. Prevent authentication headers from being forwarded across redirects to different hosts. 6. Do not inject the credential into the remote URL. Use a restricted, temporary `GIT_ASKPASS` helper or a scoped Git HTTP authorization configuration. 7. Use fine-grained, read-only tokens restricted to the specific repository. 8. Add security tests for lookalike hosts, including `github.com.attacker.example`, `attacker-github.com`, and URLs containing `github.com` only in their path. ]]>
