T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/snapbyte_digest.py:12
- Finding
- Bearer API Credential Can Be Redirected to an Arbitrary Host<![CDATA[ ## Vulnerability Details **File Location**: `scripts/snapbyte_digest.py:12-31` **Vulnerability Type**: Unvalidated credential destination **Risk Level**: High ### Vulnerable Code ```python BASE_URL = os.environ.get("SNAPBYTE_BASE_URL", "https://api.snapbyte.dev") def build_url(path: str, query: dict[str, Any] | None = None) -> str: base = BASE_URL.rstrip("/") if not query: return f"{base}{path}" filtered = {k: v for k, v in query.items() if v is not None} return f"{base}{path}?{urllib.parse.urlencode(filtered)}" def api_request(path: str, query: dict[str, Any] | None = None) -> Any: api_key = os.environ.get("SNAPBYTE_API_KEY") if not api_key: print("Missing SNAPBYTE_API_KEY", file=sys.stderr) sys.exit(2) request = urllib.request.Request(build_url(path, query), method="GET") request.add_header("Authorization", f"Bearer {api_key}") request.add_header("Accept", "application/json") try: with urllib.request.urlopen(request, timeout=20) as response: ``` ### Technical Analysis The Skill documentation declares `https://api.snapbyte.dev` as the API origin, but the implementation permits the origin to be replaced through the `SNAPBYTE_BASE_URL` environment variable. The code does not validate the resulting URL's scheme, hostname, port, or embedded user information before attaching the bearer credential. Consequently, any process, configuration layer, launcher, or attacker that can influence this environment variable can cause the helper to send `SNAPBYTE_API_KEY` to an unintended server. The override also accepts plaintext HTTP, which can expose the credential through network interception. Sending the bearer token to the genuine Snapbyte endpoint is necessary for the declared functionality. Allowing that token to be sent to arbitrary origins exceeds the minimum privileges required. ### Attack Path 1. An attacker gains the ability to influence the Skill process environment or i ...[truncated 1228 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the `SNAPBYTE_BASE_URL` override if alternate origins are not required. 2. If an override is operationally necessary, parse the destination with `urllib.parse.urlsplit()` and enforce all of the following before constructing a request: - The scheme must be exactly `https`. - The normalized hostname must be exactly `api.snapbyte.dev`. - User information must not be present. - The port must be absent or explicitly approved. 3. Refuse to attach `SNAPBYTE_API_KEY` when the destination does not match the trusted origin. 4. If development endpoints are needed, require a separate explicit development mode and a separate non-production credential. 5. Avoid following redirects that cross origins while carrying the authorization header, or explicitly verify the final destination. 6. Add tests proving that HTTP URLs, deceptive subdomains, userinfo URLs, unexpected ports, and non-Snapbyte hosts are rejected. 7. Document any supported endpoint override and its security constraints in `SKILL.md`. ]]>
