T09 · Insecure Skill Coding Practices
Error
- Location
- npm/yntalk-openclaw-init/bin/yntalk-openclaw-init.js:660
- Finding
- Gateway Credential Disclosed Through Reversible Base64 and QR Output<![CDATA[ ## Vulnerability Details **File Location**: `npm/yntalk-openclaw-init/bin/yntalk-openclaw-init.js:68-69, 327-346, 660-686` **Vulnerability Type**: Sensitive credential exposure through standard output **Risk Level**: High ### Vulnerable Code ```js function payloadToBase64(payload) { return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64'); } ``` ```js const payload = normalizeOpenClawPayload({ OPENCLAW_URL: publicURL, OPENCLAW_TOKEN: openclawToken }); return { payload: { ...payload, OPENCLAW_LAN_URL: lanURL }, lanURL, publicURL, openAIBaseURL: openAIBaseURL(publicURL), openAIBaseLANURL: openAIBaseURL(lanURL), gatewayBind, gatewayPort, authMode: firstConfigValue(config, ['gateway.auth.mode']) || 'none', chatEnabled, publicReachable: isPublicGatewayBind(gatewayBind), publicIP }; ``` ```js async function main() { const opts = parseArgs(process.argv.slice(2)); if (opts.help) { process.stdout.write(usage()); return; } const result = await readOpenClawInfoFromLocalConfig(opts.verbose); const payload = result.payload; if (!payload) throw new Error('OpenClaw connection info is incomplete.'); const encoded = payloadToBase64(payload); const command = '/openclaw --init ' + encoded; const qr = makeQRCode(command); process.stdout.write('局域网访问地址:\n'); process.stdout.write(result.lanURL + '\n\n'); process.stdout.write('局域网 OpenAI Base URL:\n'); process.stdout.write(result.openAIBaseLANURL + '\n\n'); process.stdout.write('公网访问地址:\n'); process.stdout.write(result.publicURL + '\n\n'); process.stdout.write('公网 OpenAI Base URL:\n'); process.stdout.write(result.openAIBaseURL + '\n\n'); process.stdout.write('Gateway:\n'); process.stdout.write('bind: ' + result.gatewayBind + '\n'); process.stdout.write('port: ' + result.gatewayPort + '\n'); process.stdout.write('auth_mode: ' + result.authMode + '\n'); process.stdout.write('chatCompletions: ' + (result.chatEnabled ? ...[truncated 2369 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the reusable gateway token with a short-lived, single-use enrollment token scoped only to establishing the integration. 2. Do not print credential-bearing initialization material by default. Require an explicit option and interactive confirmation before revealing it. 3. Refuse to emit the credential when standard output is not attached to an interactive terminal, unless the user supplies an explicit override. 4. Prefer a protected local handoff or authenticated enrollment protocol instead of transferring a reusable secret through terminal output. 5. Clearly warn immediately before output that both the Base64 command and QR code contain the complete gateway credential. 6. Add token expiration, revocation, rotation, and least-privilege scopes on the gateway side. 7. Ensure generated credentials cannot authorize administrative operations that are unnecessary for chat integration. 8. Avoid storing or transmitting generated output in CI logs, support tickets, ordinary chat messages, or shell history. ]]>
