T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/affinity_get.sh:20
- Finding
- Affinity API Key Disclosure Through Unrestricted API Base Override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/affinity_get.sh:20-37` **Related Documentation**: `SKILL.md:34` **Vulnerability Type**: Unrestricted credential transmission destination **Risk Level**: High ### Vulnerable Code ```bash base="${AFFINITY_API_BASE:-https://api.affinity.co}" if [[ "$endpoint" != /* ]]; then echo "Endpoint must start with / (example: /companies)" >&2 exit 2 fi # Prevent accidental non-GET by only supporting this script + curl GET invocation. url="${base}${endpoint}" if [[ -n "$query" ]]; then url+="?${query}" fi # Use Bearer token auth for Affinity API. # Do not echo command with key. resp="$(curl -fsS --get \ -H "Accept: application/json" \ -H "Authorization: Bearer ${AFFINITY_API_KEY}" \ "$url")" ``` The override is explicitly documented in `SKILL.md:34`: ```markdown - Base URL defaults to `https://api.affinity.co` and can be overridden with `AFFINITY_API_BASE` ``` ### Technical Analysis The script obtains the request destination from the environment variable `AFFINITY_API_BASE` without validating its scheme, hostname, or port. It then attaches `AFFINITY_API_KEY` as a Bearer token to a request sent to that destination. Although transmitting the token to the official Affinity API is necessary for the declared functionality, allowing an unrestricted destination is not. A malicious or compromised environment can redirect the request to an attacker-controlled server. The comments and documentation promise that the key will not be printed or logged, but they do not prevent it from being disclosed over the network. The endpoint check only verifies that the endpoint begins with `/`; it does not ensure that the completed URL belongs to `api.affinity.co`. Consequently, the credential’s trust boundary is controlled by mutable process configuration rather than a fixed or allowlisted service identity. ### Attack Path 1. An attacker gains the ability to influence the Skill’s environment, launch configura ...[truncated 1391 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `AFFINITY_API_BASE` support and use a fixed destination whenever production access is intended: ```bash readonly base="https://api.affinity.co" ``` 2. If an override is required for testing, parse and validate it before attaching credentials: - Require HTTPS. - Allowlist exact trusted hostnames. - Reject user-information components, fragments, unexpected ports, and nonstandard URL forms. - Reject values beginning with `-`. - Use separate, non-production credentials for test environments. 3. Disable redirects so the authorization header cannot be forwarded or accidentally exposed through destination changes. Continue avoiding `curl -L` unless every redirect target is independently validated. 4. Consider validating the complete URL with a dedicated URL parser rather than shell pattern matching. 5. Restrict the Affinity token itself to the smallest available read-only scope and rotate the existing token if the Skill has run in an environment where `AFFINITY_API_BASE` could have been manipulated. 6. Update `SKILL.md` to remove the unrestricted override guidance and explicitly document the allowed API hostname and credential trust boundary. ]]>
