T09 · Insecure Skill Coding Practices
- Location
run.js:16- Finding
Configurable Billing Endpoint Can Disclose the SkillPay Credential
- Content
View full analysis
Vulnerability Details
File Location:
run.js, lines 16–32
Vulnerability Type: Unvalidated credential-bearing HTTP destination
Risk Level: HighVulnerable Code
js const endpoint = process.env.SKILLPAY_ENDPOINT || "https://api.skillpay.me/v1/charges"; const payload = { skillId: SKILLPAY_ID, amount: PRICE_USDT, currency: "USDT", unit: "call", input: { topic: String(input.topic || "").slice(0, 120) }, timestamp: new Date().toISOString() }; await axios.post(endpoint, payload, { headers: { Authorization: `Bearer ${skillPayKey}`, "Content-Type": "application/json" }, timeout: 10000 });Technical Analysis
The undocumented
SKILLPAY_ENDPOINTenvironment variable completely controls the destination of a request carrying theSKILLPAY_KEYbearer credential. The implementation does not enforce HTTPS, validate the destination hostname against an allowlist, restrict ports, or otherwise ensure that the credential is sent only to the legitimate SkillPay API.Anyone able to influence the Skill's environment can set the endpoint to an attacker-controlled server. When the Skill runs, Axios sends both the bearer credential and the billing payload—including up to 120 characters of the user's topic—to that server. An internal URL could also cause the runtime to issue a credential-bearing request to an internal HTTP service.
Attack Path
- An attacker obtains the ability to configure or influence the Skill's environment.
- The attacker sets
SKILLPAY_ENDPOINTto an attacker-controlled URL, such ashttps://attacker.example/collect, or to an internal HTTP endpoint. - A user invokes the Skill with a valid topic.
chargeSkillPay()reads the malicious endpoint without validating its scheme or hostname.- Axios sends
Authorization: Bearer <SKILLPAY_KEY>and the topic-bearing billing payload to the selected destination. - The attacker captures the credential and may attempt unauthorized actions ...[truncated 646 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove
SKILLPAY_ENDPOINTconfigurability from production builds and use a fixed trusted endpoint:js const endpoint = "https://api.skillpay.me/v1/charges"; -
If endpoint configurability is operationally necessary, parse the URL and require an exact approved HTTPS origin:
js const endpoint = new URL( process.env.SKILLPAY_ENDPOINT || "https://api.skillpay.me/v1/charges" ); if ( endpoint.protocol !== "https:" || endpoint.hostname !== "api.skillpay.me" || endpoint.port ) { throw new Error("Invalid SkillPay endpoint"); } -
Prefer an exact origin-and-path allowlist rather than suffix matching, which may accept attacker-controlled domains.
-
Prevent credentials from being forwarded across redirects. Disable redirects for this request or validate every redirect destination before forwarding the
Authorizationheader. -
Restrict access to deployment environment variables using least-privilege configuration controls, and monitor changes to billing-related settings.
-
Rotate the
SKILLPAY_KEYimmediately if the Skill has ever run with an untrusted endpoint. -
Apply outbound network controls so the process can contact only the required public API hosts and cannot reach internal or link-local services.
-
