T09 · Insecure Skill Coding Practices
- Location
scripts/_common.py:20- Finding
Unrestricted API Base URL Can Expose Bearer Credentials and Sensitive Request Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/_common.py, lines 20-43 and 59-76
Vulnerability Type: Unvalidated network destination and insecure credential transmission
Risk Level: MediumVulnerable Code
python def get_base_url() -> str: return require_env("JUSTAI_OPENAPI_BASE_URL").rstrip("/") def get_api_key() -> str: return require_env("JUSTAI_OPENAPI_API_KEY") def build_request(path: str, payload: dict, api_key: str) -> urllib.request.Request: return urllib.request.Request( url=f"{get_base_url()}{path}", data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, method="POST", ) def open_json(request: urllib.request.Request, timeout: int) -> dict: try: with urllib.request.urlopen(request, timeout=timeout) as response: body = response.read().decode("utf-8")python def submit_chat( message: str, conversation_id: str = "", timeout: int = DEFAULT_TIMEOUT, project_ids: list[str] | None = None, skill_ids: list[str] | None = None, ) -> dict: api_key = get_api_key() submit_payload = {"message": message} if conversation_id: submit_payload["conversation_id"] = conversation_id if project_ids: submit_payload["project_id"] = [item for item in project_ids if item] if skill_ids: submit_payload["skill_id"] = [item for item in skill_ids if item] submit_request = build_request("/openapi/agent/chat_submit", submit_payload, api_key) return open_json(submit_request, timeout=timeout)Technical Analysis
The base URL is taken directly from the
JUSTAI_OPENAPI_BASE_URLenvironment variable without validating its scheme, hostname, port, or origin. The request builder then sends the `J ...[truncated 2035 chars]- Remediation
View remediation
Remediation Suggestions
- Parse the configured URL with
urllib.parse.urlsplitand reject malformed values. - Require the
httpsscheme in normal operation. Permit plaintext HTTP only through an explicit development-only option that never uses production credentials. - Maintain an explicit allowlist of approved JustAI hostnames and ports.
- Reject URLs containing embedded credentials, fragments, unexpected paths, or unapproved ports.
- Implement a redirect handler that blocks redirects or only permits same-origin HTTPS redirects.
- Bind API keys to the narrowest possible server-side permissions, tenant, source network, and expiration period.
- Clearly document that messages and identifiers are transmitted to the configured remote service.
- Add automated tests confirming that HTTP URLs, foreign hosts, cross-origin redirects, and malformed URLs are rejected before the authorization header is sent.
- Parse the configured URL with
