UNPKG

@codecot/pw-checker

Version:

A comprehensive CLI tool to audit passwords locally using HIBP and import from Chrome/Bitwarden

206 lines 9.33 kB
// filepath: /home/volo/projects/pw-checker/src/queryDb.ts import sqlite3 from "sqlite3"; import { open } from "sqlite"; import path from "path"; import { fileURLToPath } from "url"; import chalk from "chalk"; // ESM replacement for __dirname const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const dbPath = path.resolve(__dirname, "../db/pw_entries.sqlite"); async function showTable(filter) { const db = await open({ filename: dbPath, driver: sqlite3.Database, }); let query = "SELECT id, name, url, username, compromised, last_checked_at, breach_info, risk_score, risk_label, risk_factors, category, folder_name, source FROM pw_entries"; // Add filter if provided if (filter === "compromised") { query += " WHERE compromised = 1"; } else if (filter === "safe") { query += " WHERE compromised = 0"; } else if (filter === "unchecked") { query += " WHERE compromised IS NULL"; } else if (filter === "breached") { query += " WHERE breach_info IS NOT NULL AND breach_info LIKE '%\"breached\":true%'"; } else if (filter === "breached-detailed") { query += " WHERE breach_info IS NOT NULL AND breach_info LIKE '%\"breached\":true%'"; } else if (filter === "chrome") { query += " WHERE source = 'chrome'"; } else if (filter === "chrome-compromised") { query += " WHERE source = 'chrome' AND compromised = 1"; } else if (filter === "bitwarden") { query += " WHERE source = 'bitwarden'"; } else if (filter === "risk-critical") { query += " WHERE risk_label = 'Critical'"; } else if (filter === "risk-high") { query += " WHERE risk_label = 'High'"; } else if (filter === "risk-medium") { query += " WHERE risk_label = 'Medium'"; } else if (filter === "risk-low") { query += " WHERE risk_label = 'Low'"; } else if (filter === "by-risk") { query += " WHERE risk_score IS NOT NULL ORDER BY risk_score DESC, name ASC"; } const rows = await db.all(query); if (rows.length === 0) { console.log(chalk.yellow("⚠️ No entries found in pw_entries table.")); } else { const filterText = filter ? ` (${filter})` : ""; console.log(chalk.blue.bold(`📋 Found ${rows.length} entries${filterText} in database:\n`)); for (const row of rows) { const status = row.compromised === null ? chalk.yellow("⚠️ UNCHECKED") : row.compromised === 1 ? chalk.red("⚠️ COMPROMISED") : chalk.green("✅ Safe"); // Check for breach info let breachText = ""; if (row.breach_info) { try { const breachInfo = JSON.parse(row.breach_info); if (breachInfo.breached) { breachText = chalk.red(` 🚨 Found in ${breachInfo.count} data breaches`); } else if (breachInfo.checked) { breachText = chalk.green(" ✅ No data breaches found"); } } catch (e) { // Invalid JSON } } // Check for risk info let riskText = ""; if (row.risk_score !== null && row.risk_label) { const riskColor = row.risk_label === "Critical" ? chalk.red.bold : row.risk_label === "High" ? chalk.red : row.risk_label === "Medium" ? chalk.yellow : chalk.green; riskText = ` | Risk: ${riskColor(row.risk_label)} (${row.risk_score})`; } // Check for Bitwarden-specific info let bitwardenText = ""; if (row.source === "bitwarden") { const categoryText = row.category && row.category !== "other" ? ` [${row.category}]` : ""; const folderText = row.folder_name ? ` 📁${row.folder_name}` : ""; bitwardenText = chalk.blue(`${categoryText}${folderText}`); } console.log(`${chalk.bold(row.id)} | ${chalk.cyan(row.name)} | ${chalk.gray(row.url)} | ${chalk.magenta(row.username)} | ${status} | ${row.last_checked_at || "never checked"}${breachText}${riskText} ${bitwardenText}`); // Show detailed breach info if requested and available if ((filter === "breached" || filter === "breached-detailed") && row.breach_info) { try { const breachInfo = JSON.parse(row.breach_info); if (breachInfo.breached && breachInfo.breaches) { // Sort breaches by date (newest first) const sortedBreaches = [...breachInfo.breaches].sort((a, b) => { const dateA = new Date(a.date || a.breachDate || "1970-01-01"); const dateB = new Date(b.date || b.breachDate || "1970-01-01"); return dateB.getTime() - dateA.getTime(); }); const maxBreaches = filter === "breached-detailed" ? sortedBreaches.length : 3; sortedBreaches.slice(0, maxBreaches).forEach((breach) => { const breachDate = breach.date || breach.breachDate || "Unknown date"; console.log(chalk.red(` - ${breach.title || breach.name} (${breach.domain}) - ${breachDate}`)); if (breach.dataTypes && breach.dataTypes.length > 0) { console.log(chalk.yellow(` Data exposed: ${breach.dataTypes.join(", ")}`)); } if (breach.description && filter === "breached-detailed") { console.log(chalk.gray(` ${breach.description.slice(0, 200)}${breach.description.length > 200 ? "..." : ""}`)); } if (filter === "breached-detailed" && breach.pwnCount) { console.log(chalk.blue(` Accounts affected: ${breach.pwnCount.toLocaleString()}`)); } }); if (filter === "breached" && breachInfo.breaches.length > 3) { console.log(chalk.gray(` ... and ${breachInfo.breaches.length - 3} more breaches`)); } console.log(""); // Add spacing } } catch (e) { // Invalid JSON } } } } await db.close(); } // Process command line arguments const args = process.argv.slice(2); let filter; if (args.includes("--help") || args.includes("-h")) { console.log(chalk.blue.bold("📋 pw-checker Query Tool\n")); console.log("Usage: npm run view [FILTER]\n"); console.log("Available filters:"); console.log(" --compromised Show only compromised passwords"); console.log(" --safe Show only safe passwords"); console.log(" --unchecked Show only unchecked passwords"); console.log(" --breached Show only accounts found in data breaches (top 3 per account)"); console.log(" --breached-detailed Show all breach details with full information"); console.log(" --chrome Show only Chrome-imported entries"); console.log(" --chrome-compromised Show only Chrome entries marked as compromised"); console.log(" --bitwarden Show only Bitwarden-imported entries"); console.log(" --risk-critical Show only critical risk accounts"); console.log(" --risk-high Show only high risk accounts"); console.log(" --risk-medium Show only medium risk accounts"); console.log(" --risk-low Show only low risk accounts"); console.log(" --by-risk Show all accounts sorted by risk score"); console.log(" --help, -h Show this help message"); process.exit(0); } if (args.includes("--compromised")) { filter = "compromised"; } else if (args.includes("--safe")) { filter = "safe"; } else if (args.includes("--unchecked")) { filter = "unchecked"; } else if (args.includes("--breached-detailed")) { filter = "breached-detailed"; } else if (args.includes("--breached")) { filter = "breached"; } else if (args.includes("--chrome")) { filter = "chrome"; } else if (args.includes("--chrome-compromised")) { filter = "chrome-compromised"; } else if (args.includes("--bitwarden")) { filter = "bitwarden"; } // Handle EPIPE errors gracefully when output is piped process.stdout.on("error", (err) => { if (err.code === "EPIPE") { // This is expected when piping to commands like head, tail, etc. process.exit(0); } throw err; }); showTable(filter).catch((err) => { console.error(chalk.red("❌ Failed to query database:"), err.message); }); //# sourceMappingURL=queryDb.js.map