T09 · Insecure Skill Coding Practices
Error
- Location
- src/setup.ts:20
- Finding
- Client Key Can Be Transmitted to an Arbitrary Plaintext HTTP Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `src/setup.ts:20-30`, `src/monitor.ts:25-27`, `src/tools.ts:45-54`, `openclaw.plugin.json:21-26` **Vulnerability Type**: Insufficient transport security and unrestricted credential destination **Risk Level**: High ### Vulnerable Code ```ts // src/setup.ts:20-30 validateInput: ({ accountId, input }) => { if (input.useEnv && accountId !== DEFAULT_ACCOUNT_ID) { return "Olvid env vars can only be used for the default account."; } const clientKey = input.botToken ?? input.token; const daemonUrl = input.url ?? input.httpUrl; if (!input.useEnv && (!clientKey || !daemonUrl)) { return "Olvid requires --bot-token and --http-url (or --use-env)."; } if (!daemonUrl?.startsWith("https://") && !daemonUrl?.startsWith("http://")) { return "Olvid --url must include a valid base URL."; } return null; }, ``` ```ts // src/monitor.ts:25-27 constructor(account: ResolvedOlvidAccount, opts: MonitorOlvidOpts, cfg: CoreConfig) { super({ serverUrl: account.daemonUrl, clientKey: account.clientKey }); this.opts = opts; ``` ```ts // src/tools.ts:45-54 export function getOlvidClient(olvidChannelAccountId?: string): OlvidClient { const runtime = getOlvidRuntime(); const config = runtime.config.loadConfig(); // Retrieve the configuration/credentials for the specific olvidChannelAccountId, or fallback to default let olvidAccount: ResolvedOlvidAccount = resolveOlvidAccount({cfg: config as CoreConfig, accountId: olvidChannelAccountId ?? "default"}); if (!olvidAccount || !olvidAccount.daemonUrl || !olvidAccount.clientKey) { olvidAccount = resolveOlvidAccount({cfg: config as CoreConfig, accountId: "default"}); } return new OlvidClient({clientKey: olvidAccount.clientKey, serverUrl: olvidAccount.daemonUrl}); } ``` ```json // openclaw.plugin.json:21-26 "properties": { "daemonUrl": { "type": "string", "default": "http://localhost:50051" }, "clientKey": { "type" ...[truncated 2569 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the endpoint with the standard `URL` constructor instead of checking string prefixes. 2. Require `https:` for every non-loopback endpoint. 3. Permit plaintext HTTP only when the parsed hostname is a validated loopback address such as `localhost`, `127.0.0.0/8`, or `::1`. 4. Reject embedded username/password components, malformed ports, fragments, and unsupported protocols. 5. Consider an explicit daemon-host allowlist where deployments have a known endpoint. 6. Ensure TLS certificate validation remains enabled; consider certificate pinning for high-assurance deployments. 7. Warn users before changing an existing endpoint because the client key will be presented to the new destination. 8. Prefer environment variables or a platform secret store for the client key rather than ordinary configuration storage. ]]>
