T09 · Insecure Skill Coding Practices
Error
- Location
- index.js:110
- Finding
- Wallet API Credential Exfiltration Through an Unvalidated Signing Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `index.js:110-111`, `index.js:133-150` **Vulnerability Type**: Unvalidated credential destination / sensitive information disclosure **Risk Level**: High ### Vulnerable Code ```js const SIGN_URL = process.env.SIGN_URL || 'sign.goodwallet.dev'; const RELAY_URL = 'relay.' + SIGN_URL; ``` ```js async function signTransaction(config, unsignedSerializedTx) { const hash = keccak256(unsignedSerializedTx); const hashBytes = Buffer.from(hash.slice(2), 'hex'); const resp = await fetch(`https://${SIGN_URL}/agent/sign/ecdsa`, { method: 'POST', headers: { 'X-API-KEY': config.apiKey }, body: JSON.stringify({ hash: Buffer.from(hashBytes).toString('hex') }), }); if (!resp.ok) { const err = await resp.text(); throw new Error(`Sign API error (${resp.status}): ${err}`); } const { roomUuid } = await resp.json(); const ecdsa = new Ecdsa(RELAY_URL); const signature = await ecdsa.sign( roomUuid, config.share, new MessageHash(hashBytes), DERIVATION_PATH ); ``` ### Technical Analysis The signing service hostname is taken directly from the `SIGN_URL` environment variable without an allowlist or hostname validation. The wallet API key loaded from `~/.config/goodwallet/config.json` is subsequently placed in the `X-API-KEY` header and sent to that selected host. Although a configurable signing service is documented, transmitting an existing wallet credential to any environment-selected host exceeds least privilege. Environment variables can be influenced by shell profiles, CI configuration, wrapper scripts, compromised parent processes, or misleading invocation instructions. The same value is used to derive the MPC relay hostname. The wallet share is passed to the native signing SDK together with that relay address. The native SDK is outside this audit artifact, so its treatment of the share and network protocol cannot be verified here. ### Attack Path 1. An attacker causes the com ...[truncated 1399 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove arbitrary `SIGN_URL` overrides from normal operation and pin the production signing endpoint. 2. If custom signing infrastructure is required, enforce an exact allowlist of approved hostnames. 3. Parse endpoints with the standard `URL` class and reject: - Non-HTTPS schemes - Embedded credentials - Unexpected ports - IP literals - Unapproved subdomains - Path, query, or fragment components - Hostname suffix tricks 4. Do not reuse production API credentials with custom endpoints. Require separate credentials explicitly issued for each approved service. 5. Derive the API and relay URLs from separate trusted configuration entries rather than string concatenation. 6. Require explicit user confirmation before switching away from the default signing infrastructure. 7. Apply server-side credential scoping, expiration, revocation, transaction limits, and destination restrictions. 8. Document the native SDK's network behavior and verify that the wallet share never leaves the local process in recoverable form. ]]>
