T09 · Insecure Skill Coding Practices
- Location
references/cluster.js:35- Finding
Private Note Corpus and Gateway Credential Can Be Sent to an Arbitrary Host over Plaintext HTTP
- Content
View full analysis
Vulnerability Details
File Location:
references/cluster.js:35-45, 49-68, 99-144
Vulnerability Type: Plaintext transmission of sensitive data to a configurable remote host
Risk Level: HighVulnerable Code
javascript const host = creds.host || '127.0.0.1'; if (host !== '127.0.0.1' && host !== 'localhost') { console.warn( `[SBV] Warning: gateway host is "${host}". ` + 'This will send your atom corpus to a remote host. ' + 'Set host to 127.0.0.1 in openclaw-gateway.json to keep data local.' ); } return { host, port: creds.port || 18789, key: creds.key };javascript function callLLM(gatewayKey, gatewayHost, gatewayPort, prompt) { return new Promise((resolve, reject) => { const body = JSON.stringify({ model: MODEL, max_tokens: 4096, temperature: 0.3, messages: [{ role: 'user', content: prompt }], }); const req = require('http').request({ hostname: gatewayHost, port: gatewayPort, path: '/v1/chat/completions', method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${gatewayKey}`, 'Content-Length': Buffer.byteLength(body), }, }, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const parsed = JSON.parse(data); if (parsed.error) return reject(new Error(JSON.stringify(parsed.error))); const text = parsed.choices?.[0]?.message?.content ?? ''; resolve(text); } catch (e) { reject(new Error('Failed to parse response: ' + data.slice(0, 200))); } }); }); req.on('error', reject); req.write(body); req.end(); }); }javascript const corpus = atoms.map(a => `[${a.id}] (${a.date?.slice(0, 10) ?? '?'}) ${a.raw}` ).join('\ ...[truncated 2636 chars]- Remediation
View remediation
Remediation Suggestions
- Enforce loopback-only operation by default using validated IP resolution, not only string comparison.
- Reject non-loopback hosts unless the user enables an explicit remote-gateway option.
- Require HTTPS for every non-loopback endpoint and use Node.js's
httpsmodule. - Validate
hostandporttypes and acceptable ranges before opening a connection. - Consider certificate or public-key pinning for administratively controlled remote gateways.
- Use a narrowly scoped, revocable gateway credential dedicated to this Skill.
- Provide a confirmation step that identifies exactly which host will receive the corpus.
- Update documentation to explain that downstream LLM routing is controlled by OpenClaw and may involve external providers.
- Avoid categorical claims such as “never sent externally” unless they are technically enforced.
- Rotate the gateway credential if it has ever been sent over an untrusted network.
