T09 · Insecure Skill Coding Practices
- Location
scripts/stepfun_audio_chat.py:86- Finding
Unrestricted API Base URL Can Expose Credentials and User Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/stepfun_audio_chat.py:86-89, 284-305, 313-334, 404, 433
Vulnerability Type: Unvalidated destination override causing credential and sensitive-data disclosure
Risk Level: HighVulnerable Code
python parser.add_argument( "--api-base-url", default=os.environ.get("STEP_API_BASE_URL", DEFAULT_API_BASE_URL), help=f"API base URL. Default: {DEFAULT_API_BASE_URL}.", )python def post_json(url: str, api_key: str, payload: Dict[str, Any]) -> Dict[str, Any]: body = json.dumps(payload).encode("utf-8") req = request.Request( url, data=body, method="POST", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", "Accept": "application/json", }, ) try: with request.urlopen(req) as response: raw = response.read().decode("utf-8")python def get_json(url: str, api_key: str) -> Dict[str, Any]: req = request.Request( url, method="GET", headers={ "Authorization": f"Bearer {api_key}", "Accept": "application/json", }, ) try: with request.urlopen(req) as response: raw = response.read().decode("utf-8")python voices = get_json(list_voices_url(args.api_base_url, args.voice_limit), api_key)python response = post_json(api_url(args.api_base_url), api_key, payload)Technical Analysis
The script permits the request destination to be overridden through either the
--api-base-urlcommand-line argument or theSTEP_API_BASE_URLenvironment variable. It does not validate the URL scheme, hostname, port, embedded credentials, or path.Both network request functions unconditionally attach the StepFun API key as a bearer token. The chat request also sends the complete JSON payload, which can contain the user's prompt, an optional system instruction, a ...[truncated 2427 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove the custom API-base override if it is not essential to the declared functionality, and always use:
python DEFAULT_API_BASE_URL = "https://api.stepfun.com" -
If an override is operationally necessary, parse and validate it before any credential is resolved or request is created:
- Require the
httpsscheme. - Allowlist
api.stepfun.com. - Reject embedded usernames or passwords.
- Reject fragments and unexpected query strings.
- Reject unexpected ports.
- Reject non-root path prefixes that could alter endpoint construction.
- Normalize the hostname before comparing it with the allowlist.
- Require the
-
Keep authorization scoped to trusted destinations. Before adding the bearer header, independently verify that the final request URL remains on an approved HTTPS origin.
-
If private enterprise endpoints must be supported, require an explicit high-friction opt-in and use separate endpoint-specific credentials rather than forwarding the StepFun key.
-
Avoid following cross-origin redirects while retaining the authorization header. Explicitly reject redirects to origins other than the validated API origin.
-
Add automated security tests covering:
- Plain HTTP URLs.
- Unapproved hosts and deceptive subdomains.
- Embedded credentials.
- Alternate ports.
- Cross-origin redirects.
- Environment-variable overrides.
- Both chat and voice-list requests.
-
Clearly warn users that prompts and selected audio are transmitted to an external service, while retaining
--dry-runas the non-network inspection option.
-
