diff --git a/scripts/01-generate-keypairs.js b/scripts/01-generate-keypairs.js index 31c7d19..c03d5b7 100644 --- a/scripts/01-generate-keypairs.js +++ b/scripts/01-generate-keypairs.js @@ -7,13 +7,19 @@ * - PUBLISHER1/2: Test publisher accounts * - BUYER1: Test buyer account * - * ⚠️ IMPORTANT: Save output in a password manager immediately! - * Store securely—never commit to git. + * ⚠️ IMPORTANT: Save output securely! + * Never commit keypairs to git. Use --output to write to a protected file. * * Usage: - * node scripts/01-generate-keypairs.js + * node scripts/01-generate-keypairs.js [--output ] + * + * Options: + * --output Write keypairs to file (mode 0600) instead of stdout + * Prevents secrets from appearing in CI logs */ import { Keypair } from "@stellar/stellar-sdk"; +import fs from "fs"; +import path from "path"; function gen(label) { try { @@ -33,17 +39,55 @@ const wallets = [ gen("BUYER1 (test buyer wallet)"), ]; -console.log("\n╔══════════════════════════════════════════════════════╗"); -console.log("║ SynapsVault Testnet Keypairs — SAVE THESE NOW ║"); -console.log("╚══════════════════════════════════════════════════════╝\n"); +function formatOutput(wallets) { + const lines = []; + lines.push("\n╔══════════════════════════════════════════════════════╗"); + lines.push("║ SynapsVault Testnet Keypairs — SAVE THESE NOW ║"); + lines.push("╚══════════════════════════════════════════════════════╝\n"); + + for (const w of wallets) { + lines.push(`▸ ${w.label}`); + lines.push(` Public : ${w.pub}`); + lines.push(` Secret : ${w.sec}\n`); + } + + lines.push("═".repeat(56)); + lines.push("Next → fund each account:"); + lines.push(" node scripts/02-fund-accounts.js"); + lines.push(" (or use https://laboratory.stellar.org/#account-creator?network=test)\n"); -for (const w of wallets) { - console.log(`▸ ${w.label}`); - console.log(` Public : ${w.pub}`); - console.log(` Secret : ${w.sec}\n`); + return lines.join("\n"); +} + +// Parse command-line arguments +let outputFile = null; +for (let i = 2; i < process.argv.length; i++) { + if (process.argv[i] === "--output" || process.argv[i] === "-o") { + if (i + 1 >= process.argv.length) { + console.error("❌ --output requires a file path"); + process.exit(1); + } + outputFile = process.argv[++i]; + } } -console.log("═".repeat(56)); -console.log("Next → fund each account:"); -console.log(" node scripts/02-fund-accounts.js"); -console.log(" (or use https://laboratory.stellar.org/#account-creator?network=test)\n"); +const output = formatOutput(wallets); + +if (outputFile) { + // Write to file with restricted permissions (mode 0600: rw-------) + // This prevents the secrets from being readable by other users or appearing in CI logs + try { + fs.writeFileSync(outputFile, output, { mode: 0o600 }); + console.log(`✅ Keypairs written to: ${path.resolve(outputFile)}`); + console.log(`⚠️ File permissions set to 0600 (owner read/write only)`); + console.log(`📋 Import the keypairs manually into your secure password manager.\n`); + } catch (error) { + console.error(`❌ Failed to write to ${outputFile}: ${error.message}`); + process.exit(1); + } +} else { + // Print to stdout (for manual use, not CI) + console.log("⚠️ WARNING: Outputting secrets to stdout!"); + console.log(" Use --output to write securely to a file instead.\n"); + console.log(output); +} diff --git a/scripts/rollback-contracts.cjs b/scripts/rollback-contracts.cjs index c8b589f..e000984 100644 --- a/scripts/rollback-contracts.cjs +++ b/scripts/rollback-contracts.cjs @@ -57,8 +57,12 @@ function parseEnvFile(contents) { const result = {}; const lines = contents.split(/\r?\n/); for (const rawLine of lines) { - const line = rawLine.trim(); + let line = rawLine.trim(); if (!line || line.startsWith('#')) continue; + // Strip leading 'export ' prefix (handles bash-style export KEY=value) + if (line.startsWith('export ')) { + line = line.slice(7).trim(); + } const eq = line.indexOf('='); if (eq === -1) continue; const key = line.slice(0, eq).trim();