T09 · Insecure Skill Coding Practices
- Location
skill.py:168- Finding
Unrestricted API Base Override Enables Credential and User-Data Exfiltration
- Content
View full analysis
Vulnerability Details
File Location:
skill.py:35-50,skill.py:53-98, andskill.py:168-178
Vulnerability Type: Unvalidated network destination for sensitive authenticated requests
Risk Level: HighThe
DAM_API_BASEenvironment variable controls the destination of authenticated API requests without any validation or allowlisting. Both requests send theYOUCLOUD_API_KEYin theAuthorizationheader. The chat request also sends the user's question, user ID, and team ID.Vulnerable Code
python def _get_identity(base: str, api_key: str) -> Tuple[int, str]: """Call userInfo:get to retrieve user_id / team_id.""" url = f"{base}/api/rpc/user/v1/user/userInfo:get" req = urllib.request.Request( url, headers={"Authorization": f"YC_API_KEY {api_key}"} ) try: with urllib.request.urlopen( req, timeout=30, context=_SSL_CONTEXT ) as resp: data = json.loads(resp.read().decode("utf-8")) except urllib.error.HTTPError as e: raise DamClawError( f"userInfo:get failed status={e.code} " f"body={e.read().decode('utf-8', errors='replace')}" ) except urllib.error.URLError as e: raise DamClawError(f"userInfo:get network error: {e.reason}") return int(data["user_id"]), str(data["team_id"])python def cmclaw_chat( question: str, user_id: int, team_id: str, api_key: str, base: str = DEFAULT_BASE, session_id: Optional[str] = None, chat_mode: Optional[int] = None, ) -> Tuple[str, str]: body = {"input": question, "user_id": user_id, "team_id": team_id} url = f"{base}/api/rpc/ai/claw/v1/chat" payload = json.dumps(body).encode("utf-8") req = urllib.request.Request( url, data=payload, headers={ "Authorization": f"YC_API_KEY {api_key}", "Conte ...[truncated 3950 chars]- Remediation
View remediation
Remediation Suggestions
- Remove the
DAM_API_BASEoverride from production builds and always use the fixed official HTTPS origin when alternate environments are not required. - If multiple environments are required, select among a hardcoded allowlist of exact origins rather than accepting an arbitrary URL. For example, permit only explicitly approved YouCloud production and staging hosts.
- Parse the configured value with
urllib.parse.urlsplitand enforce all of the following:- The scheme must be
https. - The normalized hostname must exactly match an approved hostname.
- Embedded usernames and passwords must be rejected.
- Unexpected ports, query strings, and fragments must be rejected.
- The path must be empty or match the expected deployment prefix.
- The scheme must be
- Disable automatic redirects for authenticated requests, or validate every redirect target and never forward the
Authorizationheader across origins. - Build API URLs from a validated origin and fixed path constants. Do not concatenate an untrusted value directly into an authenticated request URL.
- Remove the unconditional identity log at
skill.py:176. If diagnostic logging is necessary, make it explicitly opt-in and redact account and tenant identifiers. - Treat environment configuration as security-sensitive deployment input. Restrict who can edit service manifests, CI variables, container environment values, and process launch configuration.
- Add tests confirming that HTTP URLs, unknown hosts, embedded credentials, alternate ports, and cross-origin redirects are rejected before any request containing the API key is sent.
- Remove the
