UNPKG

gitrecon

Version:

This CLI tool is designed to retrieve exposed email addresses from a GitHub user’s public activity and to identify a GitHub username associated with a given email address. It is intended strictly for educational use and ethical security research. Please u

234 lines (196 loc) 10.3 kB
// Console output formatting functions - imported display logic const ColorUtils = require('../utils/colors'); const Validators = require('../utils/validators'); class ConsoleFormatter { // Display banner - orijinal koddan static displayBanner() { console.log(ColorUtils.green(` ## # ## # ## ## # ## ## ## ## ## ## ## ## # ## ## ## ## # #### # ## ## ### ## ################# ## ### ## ######## ### ######## ### ######### ###### ######### ######### ###### ######### ######## ## ######## ################ GitRecon v0.0.5 https://github.com/atiilla This tool is intended for educational and ethical security research purposes only. For awareness information security and education purposes only. `)); } // Display user reconnaissance results - adapted static displayUserResults(data) { console.log(`\n${ColorUtils.green('Reconnaissance completed:')}`); console.log(ColorUtils.green(`User: ${ColorUtils.yellow(`${data.username} (${data.name || 'No name'})`)}`)); if (data.web_url) { console.log(ColorUtils.green(`URL: ${ColorUtils.cyan(data.web_url)}`)); } else { const platform = data.login ? 'github.com' : 'gitlab.com'; console.log(ColorUtils.green(`URL: ${ColorUtils.cyan(`https://${platform}/${data.username}`)}`)); } console.log(ColorUtils.green(`Organizations: ${ColorUtils.yellow(data.organizations && data.organizations.length > 0 ? data.organizations.join(', ') : 'None')}`)); console.log(ColorUtils.green(`Public Keys: ${ColorUtils.yellow(data.keys ? data.keys.length : 0)}`)); console.log(ColorUtils.green(`Leaked Emails: ${ColorUtils.yellow(data.leaked_emails ? data.leaked_emails.length : 0)}`)); } // Display organization reconnaissance results - adapted static displayOrgResults(data) { console.log(`\n${ColorUtils.green('Reconnaissance completed:')}`); console.log(ColorUtils.green(`Organization: ${ColorUtils.yellow(`${data.organization || data.group} (${data.name || 'No name'})`)}`)); console.log(ColorUtils.green(`URL: ${ColorUtils.cyan(data.web_url)}`)); console.log(ColorUtils.green(`Members: ${ColorUtils.yellow(data.members ? data.members.length : 0)}`)); console.log(ColorUtils.green(`Repositories: ${ColorUtils.yellow(data.repositories ? data.repositories.length : 0)}`)); console.log(ColorUtils.green(`Leaked Emails: ${ColorUtils.yellow(data.leaked_emails ? data.leaked_emails.length : 0)}`)); } // Display SSH keys - orijinal koddan static displayKeys(keys) { if (!keys || keys.length === 0) return; console.log(`\n${ColorUtils.yellow('Public SSH Keys:')}`); keys.forEach((key, index) => { console.log(ColorUtils.cyan(`Key #${index + 1}:`)); if (key.title) { console.log(`Title: ${key.title}`); } console.log(`${key.key.substring(0, 40)}...`); if (key.created_at) { console.log(`Created: ${key.created_at}`); } if (key.expires_at) { console.log(`Expires: ${key.expires_at}`); } }); } // Display leaked emails with table - orijinal koddan static displayLeakedEmails(emailDetails, maskEmails = false) { if (!emailDetails || emailDetails.length === 0) return; console.log(`\n${ColorUtils.yellow('Leaked Emails:')}`); // Create a more organized table format for output const emailTable = emailDetails.map(detail => { const email = maskEmails ? Validators.maskEmail(detail.email) : detail.email; const names = Array.from(detail.names).join(', '); return { email: email, names: names.substring(0, 30) + (names.length > 30 ? '...' : ''), username: detail.github_username || 'Unknown', sources: Array.from(detail.sources || []).length }; }); console.table(emailTable); } // Display organizations list - adapted static displayOrganizations(orgs, verbose = false) { if (!orgs || orgs.length === 0) return; console.log(`\n${ColorUtils.yellow('Organizations:')}`); if (verbose && Array.isArray(orgs) && orgs[0] && typeof orgs[0] === 'object') { // Detailed organization info orgs.forEach((org, index) => { console.log(ColorUtils.cyan(`${index + 1}. ${ColorUtils.yellow(org.login || org.name)} (${ColorUtils.yellow(org.type || 'Organization')})`)); }); } else { // Simple organization list const orgNames = Array.isArray(orgs) ? orgs : [orgs]; console.log(ColorUtils.cyan(orgNames.join(', '))); } } // Display repositories list static displayRepositories(repos, verbose = false) { if (!repos || repos.length === 0) return; console.log(`\n${ColorUtils.yellow('Repositories:')}`); if (verbose) { repos.slice(0, 10).forEach((repo, index) => { console.log(ColorUtils.cyan(`${index + 1}. ${ColorUtils.yellow(repo.name)} - ${ColorUtils.dim(repo.description || 'No description')}`)); }); if (repos.length > 10) { console.log(ColorUtils.cyan(`... and ${repos.length - 10} more repositories`)); } } else { console.log(ColorUtils.cyan(`Found ${repos.length} repositories`)); } } // Display members list static displayMembers(members, verbose = false) { if (!members || members.length === 0) return; console.log(`\n${ColorUtils.yellow('Members:')}`); if (verbose) { members.forEach((member, index) => { console.log(ColorUtils.cyan(`${index + 1}. ${ColorUtils.yellow(member.username || member.login)} (${ColorUtils.yellow(member.name || member.type || 'Member')})`)); }); } else { console.log(ColorUtils.cyan(`Found ${members.length} members`)); } } // Display scan progress static displayProgress(current, total, item) { const percentage = Math.round((current / total) * 100); const progressBar = '█'.repeat(Math.floor(percentage / 5)) + '░'.repeat(20 - Math.floor(percentage / 5)); process.stdout.write(`\r${ColorUtils.green(`Progress: [${progressBar}] ${percentage}% - ${ColorUtils.cyan(item)}`)}`); if (current === total) { process.stdout.write('\n'); } } // Display legal disclaimer static displayLegalDisclaimer() { console.log(`\n${ColorUtils.yellow('=== Legal Disclaimer ===')}`); console.log(ColorUtils.dim('This tool is provided for legitimate security research purposes only.')); console.log(ColorUtils.dim('Only analyze profiles for which you have proper authorization or that are publicly accessible.')); console.log(ColorUtils.dim('Usage must comply with GitHub/GitLab\'s terms of service and applicable laws.')); } // Display error message static displayError(message, details = null) { console.error(ColorUtils.red(`Error: ${message}`)); if (details) { console.error(ColorUtils.dim(details)); } } // Display warning message static displayWarning(message) { console.warn(ColorUtils.yellow(`Warning: ${message}`)); } // Display success message static displaySuccess(message) { console.log(ColorUtils.green(message)); } // Display info message static displayInfo(message) { console.info(ColorUtils.cyan(message)); } // Display summary statistics static displaySummary(data) { console.log(`\n${ColorUtils.bright('=== SCAN SUMMARY ===')}`); console.log(ColorUtils.green(`Target: ${data.username || data.organization || data.group}`)); console.log(ColorUtils.green(`Platform: ${data.web_url && data.web_url.includes('gitlab') ? 'GitLab' : 'GitHub'}`)); console.log(ColorUtils.green(`Scan Duration: ${data.scan_started_at && data.scan_completed_at ? Math.round((new Date(data.scan_completed_at) - new Date(data.scan_started_at)) / 1000) + ' seconds' : 'N/A'}`)); console.log(ColorUtils.green(`Organizations: ${data.organizations ? data.organizations.length : 0}`)); console.log(ColorUtils.green(`Public Keys: ${data.keys ? data.keys.length : 0}`)); console.log(ColorUtils.green(`Leaked Emails: ${data.leaked_emails ? data.leaked_emails.length : 0}`)); console.log(ColorUtils.green(`Repositories: ${data.repositories ? data.repositories.length : 0}`)); } // Display complete results with all sections static displayComplete(data, options = {}) { const { verbose = false, maskEmails = false } = options; // Determine result type and display accordingly if (data.organization || data.group) { this.displayOrgResults(data); if (verbose) { this.displayMembers(data.members, verbose); this.displayRepositories(data.repositories, verbose); } } else { this.displayUserResults(data); if (verbose) { this.displayOrganizations(data.organizations, verbose); } } // Display common sections this.displayKeys(data.keys); this.displayLeakedEmails(data.email_details, maskEmails); if (verbose) { this.displaySummary(data); } } } module.exports = ConsoleFormatter;