T09 · Insecure Skill Coding Practices
- Location
SKILL.md:44- Finding
Bearer API Key Can Be Sent to an Untrusted Configurable Endpoint
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:8-9, 44-45, 56-89, 97-110
Vulnerability Type: Unrestricted credential destination
Risk Level: MediumThe Skill defines the API destination through an environment variable and then sends the Zen+ Health bearer credential to that destination without requiring validation of its scheme, host, port, or embedded credentials.
yaml base_url_env: ZEN_API_BASE_URL api_key_env: ZEN_API_KEYThe vulnerable pattern appears in all documented API commands, including:
bash curl -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/me/notifications?limit=10"bash curl -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/me/timeline?days=7"bash curl -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/catalog"bash curl -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/me"The response-processing examples repeat the same behavior:
bash # Get notification titles curl -s -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/me/notifications" | jq -r '.notifications[].title' # Count timeline events curl -s -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/me/timeline" | jq '.events | length' # List catalogue categories curl -s -H "Authorization: Bearer ${ZEN_API_KEY}" \ "${ZEN_API_BASE_URL}/v1/catalog" | jq -r '.tasks[].category' | sort -uTechnical Analysis
ZEN_API_BASE_URLis externally configurable and is interpolated directly into eachcurldestination. The Skill does not require the agent or a wrapper to verify that the parsed URL:- Uses HTTPS.
- Has the exact approved hostname
api.zenplus.health. - Uses an approved port.
- Contains no embedded credentials or malformed URL components.
As a result, configuration tampering or setup error ...[truncated 1828 chars]
- Remediation
View remediation
Remediation Suggestions
- Hardcode
https://api.zenplus.healthas the API origin if alternative environments are not strictly required. - If configurability is necessary, place all requests behind a wrapper that parses and validates the URL before adding the authorization header.
- Require:
- The
httpsscheme. - An exact hostname allowlist, such as
api.zenplus.health. - An approved port, normally
443. - No username or password component.
- No ambiguous or malformed hostname encoding.
- The
- Fail closed if validation fails; do not fall back to the supplied URL.
- Perform structured URL parsing rather than prefix or substring checks. For example, a value such as
https://api.zenplus.health.attacker.examplemust not pass validation. - Add the bearer header only after destination validation.
- Prevent commands, debug traces, error handling, and API response logs from exposing the credential.
- Use a dedicated, revocable key with only the scopes required by enabled Skill features.
- Consider separating public catalogue access from authenticated personal-data operations so credentials are not attached where authentication is unnecessary.
- Update
SECURITY.mdto distinguish recommended configuration from enforced controls and document the destination-validation requirement.
- Hardcode
