T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/preny-handler.js:6
- Finding
- Bearer Credentials Can Be Redirected to an Arbitrary Network Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/preny-handler.js:6-7, 98-138`; `scripts/preny-cli.sh:7-9, 27-40`; `scripts/preny-stats.sh:7-8, 56-65`; `scripts/preny-tags.sh:7-8, 42-49`; `scripts/preny-conversations.sh:10-12, 28-33, 48-53, 90-97` **Vulnerability Type**: Unvalidated API endpoint override with credential forwarding **Risk Level**: High ### Vulnerable Code ```javascript const PRENY_API_BASE = process.env.PRENY_API_URL || 'https://api-production.prenychatbot.ai/api/v1'; const PRENY_TOKEN = process.env.PRENY_TOKEN; async function callAPI(from, to, limit = 30) { const url = `${PRENY_API_BASE}/statistics/stats?from=${from}&to=${to}&skip=0&limit=${limit}&sort=-1&type=interact`; const response = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${PRENY_TOKEN}`, 'Content-Type': 'application/json' } }); return response.json(); } ``` The equivalent shell implementation is: ```bash API_URL="${PRENY_API_URL:-https://api.preny.ai/v1}" API_KEY="${PRENY_API_KEY}" WORKSPACE_ID="${PRENY_WORKSPACE_ID}" api_call() { local method="$1" local endpoint="$2" local data="$3" local url="${API_URL}${endpoint}" local args=(-s -X "$method" -H "Authorization: Bearer ${API_KEY}" -H "X-Workspace-ID: ${WORKSPACE_ID}" -H "Content-Type: application/json") if [ -n "$data" ]; then args+=(-d "$data") fi curl "${args[@]}" "$url" } ``` ### Technical Analysis The scripts accept `PRENY_API_URL` directly from the process environment and attach a sensitive bearer credential to requests sent to the resulting URL. No validation restricts the URL scheme, hostname, port, or destination. Sending a bearer token to the official Preny API is necessary for the declared analytics functionality. Allowing the destination to be changed to an arbitrary origin while forwarding the same token is not required for normal operation and violates least-pri ...[truncated 1808 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `PRENY_API_URL` overrides unless custom endpoints are an explicit operational requirement. 2. If overrides are required, parse and validate the URL before creating any credential-bearing request: - Require `https:`. - Enforce an exact allowlist of documented Preny API hostnames. - Reject embedded credentials, unexpected ports, IP literals, and subdomain-suffix bypasses. 3. Compare the final request origin against the allowlist immediately before adding the `Authorization` header. 4. Disable redirects or ensure authorization headers are never forwarded to a different origin. 5. Add safe transport options to shell calls, such as `--fail-with-body`, `--proto '=https'`, and an explicit redirect policy. 6. Use narrowly scoped, read-only analytics tokens rather than browser session tokens or credentials that can access conversations. 7. Document every external hostname contacted by the Skill and fail closed when the destination is not recognized. ]]>
