T09 · Insecure Skill Coding Practices
- Location
lib/tts-hosted.js:84- Finding
Hosted TTS Discloses Complete Text Before User Approval
- Content
View full analysis
short-bucket text. const tier = config.hostedVoice?.tier || "base"; const url = `${config.forgemeshVoiceBaseUrl || paths.DEFAULT_BASE_URL}/v1/tts/${tier}`; const body = { text }; if (config.hostedVoice?.voice) body.voice = config.hostedVoice.voice; if (config.hostedVoice?.language) body.lang = config.hostedVoice.language; if (config.hostedVoice?.preset) body.preset = config.hostedVoice.preset; if (config.hostedVoice?.mix) body.mix = config.hostedVoice.mix; if (config.hostedVoice?.expression) body.expression = config.hostedVoice.expression; if (config.hostedVoice?.expressionLevel != null) body.expressionLevel = config.hostedVoice.expressionLevel; if (config.hostedVoice?.expressionControls && Object.keys(config.hostedVoice.expressionControls).length) { body.knobs = config.hostedVoice.expressionControls; } const requestInit = { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), signal: AbortSignal.timeout(120000), }; try { let res = await fetch(url, requestInit); let amountUsd = 0; if (res.status === 402) { const body = await res.json().catch(() => undefined); const paymentRequired = parsePaymentRequired(res, body); amountUsd = acceptedAmountUsd(paymentRequired); const wallet = loadWallet(); const beforeBalance = await tryBalances(wallet.address); printPaymentPreview({ wallet, amountUsd, beforeBalance, url }); const caps = checkCaps(amountUsd, config.x402Policy); if (!caps.ok) return { ok: false, engine: "hos ...[truncated 3724 chars]- Remediation
View remediation
