T09 · Insecure Skill Coding Practices
- Location
scripts/zhixi-files.js:55- Finding
Unrestricted Fetch of an API-Supplied URL Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/zhixi-files.js, lines 55-58
Vulnerability Type: Server-Side Request Forgery through an unvalidated remote URL
Risk Level: MediumVulnerable Code
javascript async getContent(fileId) { const api = `${CONFIG.baseUrl}/v1/file/details?file_guid=${fileId}`; const result = await this._fetch(api); if (result.code !== 0) return result; // console.debug(result.data?.content_url); const response = await fetch(result.data?.content_url); return response.json(); }Technical Analysis
The
getContentmethod obtainscontent_urlfrom an API response and passes it directly tofetch. It does not validate the URL's protocol, hostname, port, resolved IP address, or redirect destination.Node's
fetchfollows HTTP redirects by default. Consequently, validating only the initial URL would also be insufficient unless every redirect target is checked. If an attacker can influence a file record or the upstream API response, the URL could point to a loopback address, private network service, link-local endpoint, cloud instance metadata service, or another destination accessible from the host running this skill.Exploitation depends on the attacker gaining influence over
result.data.content_url, such as through malicious cloud-file metadata, an upstream service compromise, or another flaw in the remote service. The audited code does not independently establish that ordinary users can modify this field.Attack Path
- An attacker gains the ability to influence the
content_urlreturned for a requested file. - The attacker supplies a URL targeting an internal resource, such as a loopback service, private-network endpoint, or metadata service. Alternatively, the URL points to an attacker-controlled server that redirects to such a resource.
- A user or agent invokes
content <file_guid>for the affected file. - The skill requests th ...[truncated 1198 chars]
- An attacker gains the ability to influence the
- Remediation
View remediation
Remediation Suggestions
- Parse
content_urlwith the standardURLclass and reject malformed values. - Require HTTPS and enforce an explicit allowlist of documented Zhixi content-delivery hostnames.
- Resolve the destination and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges.
- Disable automatic redirects with
redirect: "manual", or validate the destination of every redirect before following it. - Protect against DNS rebinding by validating the address actually used for the connection, not only a preliminary DNS lookup.
- Apply connection timeouts and strict response-size limits.
- Require an expected content type before parsing the response as JSON.
- Reject a missing
content_urlwith an explicit error rather than passing it tofetch.
Example validation policy:
javascript function validateContentUrl(value) { const url = new URL(value); const allowedHosts = new Set([ // Populate with the provider's documented content hosts. 'approved-content-host.example' ]); if (url.protocol !== 'https:' || !allowedHosts.has(url.hostname)) { throw new Error('Untrusted content URL'); } return url.toString(); } const contentUrl = validateContentUrl(result.data?.content_url); const response = await fetch(contentUrl, { redirect: 'manual', signal: AbortSignal.timeout(10_000) });- Parse
