T09 · Insecure Skill Coding Practices
- Location
SKILL.md:412- Finding
Unvalidated Proxy URL Can Expose the Wallet Bearer Token
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 412–429 and 515–516
Vulnerability Type: Improper validation of a security-sensitive network destination
Risk Level: HighVulnerable Code
javascript constructor(baseUrl, token) { this.#baseUrl = baseUrl.replace(/\/$/, ''); this.#token = token; } async #request(method, path, body = null) { const options = { method, headers: { 'Authorization': `Bearer ${this.#token}`, 'Content-Type': 'application/json', }, }; if (body) { options.body = JSON.stringify(body); } const response = await fetch(`${this.#baseUrl}${path}`, options); const result = await response.json(); if (!result.success) { throw new Error(result.error || 'Request failed'); } return result.data; }javascript const agent = new SparkProxyAgent( process.env.PROXY_URL, process.env.PROXY_TOKEN );Technical Analysis
The provided client obtains the proxy endpoint from the externally configured
PROXY_URLenvironment variable and sends the sensitivePROXY_TOKENto that endpoint in an HTTPAuthorizationheader. The constructor only removes a trailing slash; it does not parse or validate the URL, enforce HTTPS, reject embedded credentials, or restrict the destination to a trusted host.The documentation instructs users to use HTTPS, but this is advisory and is not enforced by the sample implementation. Consequently, a malformed, plaintext, or attacker-controlled proxy URL will receive the bearer token whenever any client method makes a request.
This credential grants wallet capabilities according to its assigned role. A
read-onlytoken exposes wallet information, whilepay-onlyoradmintokens can authorize financial operations. Server-side transaction and daily limits reduce potential loss but do not prevent credential disclosure or unauthorized use within those limits.The separately flagged L402 helper at lines 334–353 does not directly trans ...[truncated 1907 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the configured endpoint with
new URL(baseUrl)and reject invalid URLs. - Require
url.protocol === 'https:'; permit plaintext HTTP only through an explicit development-only option that cannot be enabled in production. - Maintain an explicit allowlist of trusted proxy hostnames or require the expected hostname to be supplied through a protected deployment configuration.
- Reject URLs containing embedded usernames or passwords.
- Normalize the validated origin rather than concatenating an unchecked string.
- Configure redirects manually or disable them. Never forward the
Authorizationheader when a redirect changes the origin. - Consider certificate or public-key pinning in controlled deployment environments where the runtime supports it.
- Use the narrowest token role and enforce low
maxTxSatsanddailyBudgetSatsvalues. - Avoid using administrative tokens in autonomous agents.
- Validate configuration during client construction and fail closed before making any request.
Example hardening:
javascript constructor(baseUrl, token, allowedHosts = []) { const url = new URL(baseUrl); if (url.protocol !== 'https:') { throw new Error('PROXY_URL must use HTTPS'); } if (url.username || url.password) { throw new Error('PROXY_URL must not contain credentials'); } if (allowedHosts.length > 0 && !allowedHosts.includes(url.hostname)) { throw new Error('Untrusted proxy host'); } this.#baseUrl = url.origin; this.#token = token; }The request implementation should additionally reject cross-origin redirects or reissue redirected requests without the bearer credential only after explicit trust validation.
- Parse the configured endpoint with
