- Location
- caixu-shared-core/packages/skill-runner/src/index.ts:2017
- Finding
- Configurable model endpoint can receive API credentials and sensitive document-derived content<![CDATA[
## Vulnerability Details
**File Location**: `caixu-shared-core/packages/skill-runner/src/index.ts:2017-2066, 2128-2158, 2924-2950, 3128-3155`
**Vulnerability Type**: Unrestricted outbound destination with credential and sensitive-data forwarding
**Risk Level**: High
### Vulnerable Code
```ts
const baseUrl =
input.baseUrl ?? "https://open.bigmodel.cn/api/paas/v4/chat/completions";
```
```ts
const response = await fetchWithRateLimitRetry({
scope,
url: baseUrl,
timeoutMs: timeoutMs ?? input.timeoutMs,
maxAttempts: httpMaxAttempts,
baseDelayMs: httpBaseDelayMs,
maxDelayMs: httpMaxDelayMs,
minIntervalMs,
onEvent: input.onEvent,
label: `Skill model request for ${skillName} (attempt ${attempt})`,
init: {
method: "POST",
headers: {
Authorization: `Bearer ${input.apiKey}`,
"Content-Type": "application/json",
...input.extraHeaders
},
body: JSON.stringify({
model: input.model,
temperature: 0,
...(typeof doSample === "boolean" ? { do_sample: doSample } : {}),
...(Number.isFinite(maxTokens) && (maxTokens ?? 0) > 0
? { max_tokens: Math.trunc(maxTokens ?? 0) }
: {}),
...(responseFormat ? { response_format: { type: responseFormat } } : {}),
...(thinkingMode ? { thinking: { type: thinkingMode } } : {}),
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: userPrompt }
]
})
}
});
```
```ts
const apiKey =
process.env.CAIXU_AGENT_API_KEY?.trim() || process.env.ZHIPU_API_KEY?.trim();
return createOpenAICompatibleSkillModelClient({
apiKey,
model: process.env.CAIXU_AGENT_MODEL?.trim() || "glm-4.6",
baseUrl: process.env.CAIXU_AGENT_BASE_URL?.trim(),
timeoutMs: Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 30000,
httpMaxAttempts:
Number.isFinite(httpMaxAttempts) && httpMaxAttempts > 0
? httpMaxAttempts
: 4,
httpBaseDelayMs:
Number.isFinite(httpBaseDelayMs) &&
...[truncated 3589 chars]
- Remediation
- <![CDATA[
## Remediation Suggestions
1. **Restrict model destinations**
- Parse the configured URL with the standard `URL` API.
- Require HTTPS outside explicitly identified local development mode.
- Maintain an allowlist of approved scheme, hostname, and port combinations.
- Reject URLs containing user information, fragments, unexpected ports, or malformed hostnames.
2. **Require explicit opt-in for custom providers**
- Disable custom `CAIXU_AGENT_BASE_URL` values by default.
- Require a separate flag such as `CAIXU_ALLOW_CUSTOM_AGENT_ENDPOINT=true`.
- Clearly display the selected destination before transmitting document-derived content.
3. **Separate credentials by destination**
- Remove the fallback from `CAIXU_AGENT_API_KEY` to `ZHIPU_API_KEY`.
- Require a destination-specific credential.
- Ensure a credential configured for one provider is never forwarded to another origin.
4. **Minimize transmitted personal data**
- Send only the minimum fields needed for each decision.
- Redact unnecessary names, local paths, identifiers, and document details.
- Prefer local deterministic processing where model inference is unnecessary.
- Obtain informed user consent before sending personal document content externally.
5. **Protect request headers**
- Do not allow `extraHeaders` to override `Authorization`, `Host`, or `Content-Type`.
- Merge only explicitly allowlisted additional headers.
6. **Harden redirects and network access**
- Disable automatic cross-origin redirects or validate every redirect destination.
- Reject loopback, private, link-local, multicast, and cloud metadata destinations unless explicitly required.
- Add tests proving that HTTP, unapproved domains, and credential forwarding across origins are rejected.
7. **Operational response**
- Rotate any credential that may have been used with an untrusted endpoint.
- Audit environment configuration and outbound request logs for unexpected model
...[truncated 19 chars]