T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/ark_web_search.py:44
- Finding
- ARK API Credential Can Be Sent to an Arbitrary Configurable Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ark_web_search.py:44-52`, `scripts/ark_web_search.py:154-164`, and `scripts/ark_web_search.py:438-443` **Vulnerability Type**: Unrestricted credential-bearing network destination **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument( "--base-url", default=os.getenv("ARK_BASE_URL", DEFAULT_BASE_URL), help="ARK base URL. Defaults to ARK_BASE_URL or %(default)s.", ) parser.add_argument( "--api-key", default=os.getenv("ARK_API_KEY"), help="ARK API key. Defaults to ARK_API_KEY.", ) ``` ```python def create_request(url: str, api_key: str, payload: dict[str, Any], stream: bool) -> urllib.request.Request: headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } if stream: headers["Accept"] = "text/event-stream" return urllib.request.Request( url=url, data=json.dumps(payload).encode("utf-8"), headers=headers, method="POST", ) ``` ```python def execute_request(args: argparse.Namespace, payload: dict[str, Any]) -> tuple[dict[str, Any], bool]: endpoint = args.base_url.rstrip("/") + "/responses" request = create_request(endpoint, args.api_key, payload, args.stream) if args.stream: return stream_response(request, args.timeout, args.format) return non_stream_response(request, args.timeout), False ``` ### Technical Analysis The Skill legitimately needs network access and must send the user’s search query to the Volcengine ARK Responses API. Sending the API key to the documented default endpoint, `https://ark.cn-beijing.volces.com/api/v3/responses`, is therefore necessary for its declared functionality. However, the destination is fully configurable through the `--base-url` argument or the `ARK_BASE_URL` environment variable. The supplied value is used without validating its scheme or hostname. The same request unconditionally includes th ...[truncated 1890 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove arbitrary endpoint overrides if they are not required.** Always use the documented Volcengine endpoint for normal operation. 2. **Allowlist approved destinations if endpoint customization is necessary.** Parse the URL with `urllib.parse.urlparse()` and require: - The `https` scheme. - An exact approved Volcengine hostname, such as `ark.cn-beijing.volces.com`. - An expected port or no explicit port. - No embedded username or password. - An expected API path prefix. 3. **Fail closed on invalid URLs.** Do not silently normalize or send credentials to an unrecognized destination. 4. **Separate development behavior from production behavior.** If custom endpoints are needed for local testing, require an explicit unsafe-development flag and avoid attaching a real API key by default. 5. **Protect credential-bearing requests.** Ensure that requests cannot be redirected or otherwise forwarded to an unapproved host while retaining the authorization header. 6. **Document the data boundary.** Clearly state that search queries are transmitted to Volcengine and advise users not to include secrets or private data unless permitted by their organization’s data-handling policy. 7. **Add automated security tests.** Verify that HTTP URLs, unapproved domains, malformed URLs, embedded credentials, and unexpected ports are rejected before request construction. ]]>
