T09 · Insecure Skill Coding Practices
Warning
- Location
- auto_model_switch.js:149
- Finding
- Gateway bearer token may be transmitted over unencrypted HTTP<![CDATA[ ## Vulnerability Details **File Location**: `auto_model_switch.js:32-33, 149-159, 181-191` **Vulnerability Type**: Plaintext transmission of an authentication credential **Risk Level**: Medium ### Technical Analysis The gateway URL defaults to an unencrypted HTTP endpoint, and the implementation permits any caller-supplied `http://` gateway URL: ```javascript this.gatewayUrl = process.env.OPENCLAW_GATEWAY_URL || 'http://localhost:3000'; this.gatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN || ''; ``` The token is placed directly into the HTTP `Authorization` header when retrieving status: ```javascript const url = new URL('/api/status', this.gatewayUrl); const client = url.protocol === 'https:' ? https : http; const req = client.get(url, { headers: { 'Authorization': `Bearer ${this.gatewayToken}`, 'Content-Type': 'application/json' } }, (res) => { ``` The same credential is transmitted when changing the configured model: ```javascript const options = { method: 'POST', headers: { 'Authorization': `Bearer ${this.gatewayToken}`, 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } }; const req = client.request(url, options, (res) => { ``` The documentation explicitly demonstrates `OPENCLAW_GATEWAY_URL="http://localhost:3000"`. While loopback traffic has less exposure than traffic crossing a network, the code does not enforce loopback-only use for HTTP. An operator can configure a remote or shared-network HTTP endpoint, causing the bearer token and gateway responses to travel without transport encryption. Bearer tokens are replayable credentials. HTTP provides no confidentiality or server authentication, so an on-path party may observe the token or impersonate the gateway. The implementation also does not issue a warning when a non-loopback HTTP URL is used. ### Attack Path 1. An operator follows the documented configuration pattern but sets `OPENCLAW_GATEWAY_URL` to an `http://` addr ...[truncated 1431 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require HTTPS whenever a gateway token is configured: - Reject `http:` URLs unless the hostname is strictly loopback (`localhost`, `127.0.0.1`, or `::1`). - Fail closed rather than silently sending credentials over an insecure remote connection. 2. Emit a prominent warning or require an explicit opt-in such as `ALLOW_INSECURE_LOOPBACK_HTTP=true` for local development. 3. Update `SKILL.md` and `QUICKSTART.md` to use an `https://` example for non-local gateways and explain the loopback-only exception. 4. Validate TLS certificates using Node.js defaults. Do not introduce options such as `rejectUnauthorized: false`. 5. Use a narrowly scoped gateway token that permits only status retrieval and model switching. 6. Support token rotation and document immediate revocation procedures for potentially exposed credentials. 7. Consider Unix-domain sockets or another authenticated local IPC mechanism when the gateway and skill run on the same host. 8. Add tests confirming that: - Remote `http://` gateway URLs are rejected when a token is present. - Loopback HTTP requires explicit authorization. - HTTPS remains accepted. ]]>
