T09 · Insecure Skill Coding Practices
- Location
scripts/posthog_sync.sh:6- Finding
Unvalidated API Host Can Receive the PostHog Personal API Key
- Content
View full analysis
Vulnerability Details
File Location:
scripts/posthog_sync.sh, lines 6–8 and 14–18
Vulnerability Type: Unrestricted credential-bearing API destination
Risk Level: Highbash : "${POSTHOG_PERSONAL_API_KEY:?Set POSTHOG_PERSONAL_API_KEY}" POSTHOG_HOST="${POSTHOG_HOST:-us.i.posthog.com}" POSTHOG_UI_HOST="${POSTHOG_UI_HOST:-us.posthog.com}" API_BASE="https://${POSTHOG_HOST}/api/projects/@current" api() { local method="$1" endpoint="$2"; shift 2 curl -sS -X "$method" "${API_BASE}${endpoint}" \ -H "Authorization: Bearer ${POSTHOG_PERSONAL_API_KEY}" \ -H "Content-Type: application/json" "$@" }Technical Analysis
The script constructs
API_BASEdirectly from the environment-controlledPOSTHOG_HOSTvalue without validating it against trusted PostHog endpoints. Theapifunction then includesPOSTHOG_PERSONAL_API_KEYas a bearer token in every request sent to that destination.Although HTTPS protects transport confidentiality, it does not establish that the selected server belongs to PostHog. An attacker-controlled host with a valid TLS certificate can receive the authorization header. This issue becomes exploitable when an attacker can influence the script's environment, such as through a wrapper script, CI/CD configuration, task configuration, shell profile, or agent-provided environment variables.
Attack Path
- The victim configures a valid read/write
POSTHOG_PERSONAL_API_KEY. - An attacker or compromised execution environment sets
POSTHOG_HOSTto an attacker-controlled HTTPS hostname. - The victim or automation invokes any command that performs an API request, such as
create,sync,update, orexport. API_BASEis constructed using the attacker-controlled hostname.curlconnects to that hostname and sendsAuthorization: Bearer ${POSTHOG_PERSONAL_API_KEY}.- The attacker records the credential and can use it directly against the legitimate PostHog API, subject to the key's assigned permiss ...[truncated 567 chars]
- The victim configures a valid read/write
- Remediation
View remediation
Remediation Suggestions
- Validate
POSTHOG_HOSTbefore constructingAPI_BASE. - For PostHog Cloud, allow only exact trusted API hosts:
us.i.posthog.comeu.i.posthog.com
- Reject values containing schemes, paths, user information, ports, query strings, fragments, wildcard suffixes, or unapproved subdomains.
- If self-hosted PostHog must be supported, require an explicit opt-in configuration and maintain a deployment-specific allowlist rather than accepting arbitrary environment values.
- Separate cloud and custom-host modes so a custom destination cannot be selected accidentally.
- Use API keys with the minimum required scopes and rotate the key immediately if it may have been exposed.
- Add automated tests confirming that attacker-controlled, lookalike, malformed, and non-allowlisted hostnames are rejected before any credential-bearing request occurs.
Example hardening for cloud-only operation:
bash POSTHOG_HOST="${POSTHOG_HOST:-us.i.posthog.com}" case "$POSTHOG_HOST" in us.i.posthog.com|eu.i.posthog.com) ;; *) echo "Error: Untrusted POSTHOG_HOST: $POSTHOG_HOST" >&2 exit 1 ;; esac API_BASE="https://${POSTHOG_HOST}/api/projects/@current"- Validate
