T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/rumor_scanner.py:143
- Finding
- Environment-Controlled API Endpoint Can Disclose the AISA API Key## Vulnerability Details **File Location**: `scripts/rumor_scanner.py`, lines 143–150 and 164–170 **Vulnerability Type**: Unrestricted authenticated API destination override **Risk Level**: High ### Vulnerable Code ```python def get_client() -> OpenAI: api_key = os.environ.get("AISA_API_KEY") if not api_key: print("❌ Error: AISA_API_KEY environment variable is not set.", file=sys.stderr) print(" Set it with: export AISA_API_KEY=your_key_here", file=sys.stderr) sys.exit(1) base_url = os.environ.get("AISA_BASE_URL", "https://api.aisa.one/v1") return OpenAI(api_key=api_key, base_url=base_url) ``` The resulting client sends an authenticated request here: ```python try: response = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": prompt}, ], temperature=0.2, ) ``` ### Technical Analysis The Skill legitimately requires `AISA_API_KEY` to authenticate with its declared AISA service. However, `get_client()` also reads the undocumented `AISA_BASE_URL` environment variable and accepts its value without validating the scheme, hostname, port, or trust relationship. The `OpenAI` client is initialized with both the legitimate API key and this unrestricted destination. Consequently, a process launcher, compromised parent process, poisoned execution environment, or surrounding automation capable of setting `AISA_BASE_URL` can redirect the authenticated completion request to an attacker-controlled server. Sending the key to the default AISA endpoint is necessary for the declared functionality. Allowing an arbitrary destination is not required for rumor scanning and expands the Skill's trust boundary beyond minimum privilege. ### Attack Path 1. An attacker gains influence over the environment used to launch the Skill, such a ...[truncated 1512 chars]
- Remediation
- ## Remediation Suggestions 1. Remove the `AISA_BASE_URL` override and use the declared service directly if alternate endpoints are not essential: ```python AISA_BASE_URL = "https://api.aisa.one/v1" return OpenAI(api_key=api_key, base_url=AISA_BASE_URL) ``` 2. If endpoint customization is a required feature, parse the URL and enforce an explicit allowlist: - Require HTTPS. - Permit only approved AISA hostnames. - Reject embedded user information. - Reject unapproved ports. - Reject malformed URLs and IP-literal bypasses. - Normalize and validate the hostname before comparison. 3. Prevent credentials from being forwarded across redirects to a different origin. Configure the HTTP client to reject cross-origin redirects for authenticated requests or disable redirects entirely. 4. Document any supported endpoint override in `SKILL.md`, including the security implications. Require explicit user confirmation before sending credentials to any non-default approved host. 5. Use a narrowly scoped, revocable API key with spending and quota limits. Rotate the key immediately if it may have been used while `AISA_BASE_URL` pointed to an untrusted destination. 6. Add automated tests verifying that non-HTTPS URLs, arbitrary domains, deceptive subdomains, user-info URLs, and unapproved ports are rejected before client initialization.
