T09 · Insecure Skill Coding Practices
- Location
launch.ts:116- Finding
Arbitrary Image URL Fetching Enables SSRF and Potential Data Disclosure
- Content
View full analysis
{ if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) { const res = await fetch(imagePath); if (!res.ok) throw new Error(`Failed to fetch image: ${res.status}`); return await res.blob(); } const resolved = path.resolve(imagePath); if (!fs.existsSync(resolved)) throw new Error(`Image not found: ${resolved}`); const buffer = fs.readFileSync(resolved); const ext = path.extname(resolved).toLowerCase(); const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : "image/jpeg"; return new Blob([buffer], { type: mime }); } ``` The function is invoked in dry-run mode: ```ts if (dryRun === "true") { console.log("✅ Dry run complete — parameters validated."); console.log(" Remove --dry-run to launch for real."); // Still validate image loads try { const blob = await loadImage(image); console.log(` Image loaded: ${blob.size} bytes (${blob.type})`); } catch (e: any) { console.error(` ❌ Image error: ${e.message}`); } return; } ``` In live mode, the downloaded response is passed to the external SDK: ```ts // Load image console.log("Uploading metadata to IPFS..."); const imageBlob = await loadImage(image); // Create SDK and launch const sdk = new PumpFunSDK(provider); const mintKeypair = Keypair.generate(); console.log(`Mint address: ${mintKeypair.publicKey.toBase58()}`); console.log("Sending transaction..."); try { const result = await sdk.createAndBuy( wallet, mintKeypair, { name, symbol, description, file: imageBlob, }, BigInt(Math.floor(buyAmountSol * LAMPORTS_PER_SOL)), slippageBps, ...[truncated 3616 chars]- Remediation
View remediation
