T09 · Insecure Skill Coding Practices
Error
- Location
- nexus-tool-runner.ts:33
- Finding
- Bearer Token May Be Transmitted to an Arbitrary or Plaintext Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `nexus-tool-runner.ts`, lines 33-42 and 209-216 **Vulnerability Type**: Unvalidated credential destination **Risk Level**: High ### Vulnerable Code ```ts constructor(url: string, token: string) { const userAgent = `openclaw/1.0.0 node/${process.version.slice(1)} (${process.platform}; ${process.arch})`; this.transport = new StreamableHTTPClientTransport(new URL(url), { requestInit: { headers: { Authorization: `Bearer ${token}`, "User-Agent": userAgent, }, }, }); ``` ```ts const url = process.env.NEXUS_URL ?? "https://nexus.civic.com/hub/mcp"; const token = process.env.NEXUS_TOKEN; if (!token) { console.error("Error: NEXUS_TOKEN environment variable is required"); console.error("\nSet it with:"); console.error(' export NEXUS_TOKEN="your-token-here"'); process.exit(1); } ``` ### Technical Analysis The application obtains the server URL directly from the `NEXUS_URL` environment variable and constructs a transport from it without validating its protocol, hostname, port, or network destination. The `NEXUS_TOKEN` credential is then unconditionally inserted into the `Authorization` header. Consequently, a manipulated configuration can cause the token to be sent to an attacker-controlled endpoint. The code also accepts an `http://` URL, which can expose the bearer token to passive or active network interception. Destinations such as loopback, link-local, or private-network addresses are not rejected either. Exploitation requires the attacker to influence the environment or configuration that supplies `NEXUS_URL`, or to convince the user to configure a malicious endpoint. ### Attack Path 1. An attacker changes the configured `NEXUS_URL` or provides setup instructions containing an attacker-controlled URL. 2. The user or agent invokes `nexus-tool-runner.ts` with a valid `NEXUS_TOKEN`. 3. The script reads the malicious URL without validating its scheme or hostn ...[truncated 1050 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require `https:` for every endpoint that receives `NEXUS_TOKEN`; reject plaintext HTTP. 2. Allowlist the expected Civic Nexus hostname, such as `nexus.civic.com`, by default. 3. If custom MCP servers are a legitimate feature, require explicit user approval before sending credentials to a non-default hostname. 4. Bind credentials to approved origins and never reuse the Civic Nexus token for arbitrary custom endpoints. 5. Reject loopback, link-local, private-network, and otherwise restricted destinations unless a documented use case explicitly requires them. 6. Revalidate the destination after redirects and prevent credentials from being forwarded across origins. 7. Consider implementing a validation function similar to: ```ts function validateNexusUrl(rawUrl: string): URL { const url = new URL(rawUrl); if (url.protocol !== "https:") { throw new Error("NEXUS_URL must use HTTPS"); } if (url.hostname !== "nexus.civic.com") { throw new Error("NEXUS_URL must use the approved Nexus hostname"); } return url; } ``` 8. Use the validated `URL` object when creating the transport, and add automated tests covering HTTP URLs, deceptive subdomains, alternate ports, redirects, loopback addresses, and private-network destinations. ]]>
