UNPKG

@bytehide/secrets-scanner

Version:

AI-powered secrets scanner for JavaScript/TypeScript. Detects and protects API keys, tokens, and credentials in source code and build artifacts. Features automatic fixing, built-in secrets manager, and zero-knowledge privacy. Superior alternative to gitle

1,719 lines (1,637 loc) 72.2 kB
// node_modules/tsup/assets/esm_shims.js import { fileURLToPath } from "url"; import path from "path"; var getFilename = () => fileURLToPath(import.meta.url); var getDirname = () => path.dirname(getFilename()); var __dirname = /* @__PURE__ */ getDirname(); // src/core/analysisBuilder.ts import dayjs from "dayjs"; import path2 from "path"; import os from "os"; function createAnalysis(secrets, appName, engine, startTime, endTime, actions) { const totalTime = (endTime - startTime) / 1e3; const detections = secrets.map((s) => { return { id: s.key, // o un ID que generes name: s.name, confidence: s.confidence, location: s.filePath + ` on line ${s.line}`, // un ejemplo path: shortifyPath(s.filePath) + `:${s.line}`, file: s.filePath, discover: s.discoveredBy, // "pattern", "plugins", etc. code: s.snippet, // si tienes snippet highlight: s.snippetLineNumber }; }); const now = dayjs().format(); return { application: appName, date: now, // string ISO time: totalTime, engine, detections, actions: actions || {} }; } function shortifyPath(absolutePath, maxSegments = 4) { const homeDir = os.homedir(); let shortPath = absolutePath; const normalizedAbsolute = path2.normalize(absolutePath); const normalizedHome = path2.normalize(homeDir); if (normalizedAbsolute.startsWith(normalizedHome)) { shortPath = normalizedAbsolute.slice(normalizedHome.length); if (!shortPath.startsWith(path2.sep)) { shortPath = path2.sep + shortPath; } } const parts = shortPath.split(path2.sep).filter(Boolean); if (parts.length > maxSegments) { const lastSegments = parts.slice(parts.length - maxSegments); return ".../" + lastSegments.join(path2.sep); } else { return shortPath; } } // src/core/mainScanner.ts import path5 from "path"; // src/core/extractors/stringExtractorUniversal.ts import fs2 from "fs"; import path3 from "path"; import Parser from "tree-sitter"; import JavaScript from "tree-sitter-javascript"; import TSParser from "tree-sitter-typescript"; import Python from "tree-sitter-python"; import Java from "tree-sitter-java"; import CSharp from "tree-sitter-c-sharp"; import CPP from "tree-sitter-cpp"; import TSParser2 from "tree-sitter-php"; import Swift from "tree-sitter-swift"; import Kotlin from "tree-sitter-kotlin"; import Go from "tree-sitter-go"; import Rust from "tree-sitter-rust"; import Ruby from "tree-sitter-ruby"; import Scala from "tree-sitter-scala"; // src/core/extractors/stringExtractor.ts import fs from "fs"; import { parse } from "@babel/parser"; import traverse from "@babel/traverse"; import * as t from "@babel/types"; function getSnippet(content, line, column, options = { linesBefore: 3, linesAfter: 3 }) { const lines = content.split("\n"); const startLine = Math.max(line - (options.linesBefore ?? 3), 1); const endLine = Math.min(line + (options.linesAfter ?? 3), lines.length); const snippetLines = lines.slice(startLine - 1, endLine); const snippet = snippetLines.join("\n"); let highlight = 0; let snippetLineNumber = line - startLine + 1; if (line >= startLine && line <= endLine) { const currentLineIndex = snippetLineNumber - 1; highlight = snippetLines.slice(0, currentLineIndex).reduce((acc, ln) => acc + ln.length + 1, 0); highlight += column; } return { snippet, highlight, snippetLineNumber }; } // src/core/extractors/stringExtractorUniversal.ts var { typescript: TypeScript, tsx: TSX } = TSParser; var { php: PHP } = TSParser2; var LANG_MAP = { // JavaScript / Node ".js": JavaScript, ".jsx": JavaScript, ".mjs": JavaScript, ".cjs": JavaScript, // TypeScript ".ts": TypeScript, ".tsx": TSX, ".cts": TypeScript, ".mts": TypeScript, // Python ".py": Python, ".pyw": Python, // Java ".java": Java, // C# ".cs": CSharp, ".csx": CSharp, ".razor": CSharp, ".cshtml": CSharp, // C++ ".cpp": CPP, ".cxx": CPP, ".cc": CPP, ".hpp": CPP, ".hh": CPP, ".hxx": CPP, ".h": CPP, // PHP / Laravel Blade ".php": PHP, ".phtml": PHP, ".php3": PHP, ".php4": PHP, ".php5": PHP, ".phar": PHP, ".inc": PHP, ".blade.php": void 0, // Swift ".swift": Swift, // Kotlin ".kt": Kotlin, ".kts": Kotlin, // Go ".go": Go, // Rust ".rs": Rust, // Ruby ".rb": Ruby, // Scala ".scala": Scala, ".sc": Scala // Dart //'.dart': Dart, // Shell scripts //'.sh': Shell, //'.bash': Shell, //'.zsh': Shell, // Perl //'.pl': Perl, //'.pm': Perl, //'.t': Perl, // Lua //'.lua': Lua, // MATLAB //'.m': Matlab, // Fortran //'.f': Fortran, //'.for': Fortran, //'.f90': Fortran, }; var STRING_NODE_TYPES = /* @__PURE__ */ new Set([ // Generic string literals "string_literal", "string", "template_string", // Go "interpreted_string_literal", "raw_string_literal", // PHP "encapsed_string", "string_content", // JSX "jsx_text", // C# "interpolated_string_expression", "interpolated_regular_string_literal", "interpolated_verbatim_string_literal", // Swift "string_literal", // Swift grammar uses same node type // Perl "string", // Perl grammar calls them “string” //Swift "line_string_literal", "line_str_text", // Others (Rust, Kotlin, Java, etc.) "string_literal" ]); function extractStringsFromFile(filePath, includeSnippet = false) { const ext = path3.extname(filePath).toLowerCase(); let Grammar = LANG_MAP[ext]; if (filePath.endsWith(".blade.php")) Grammar = void 0; const content = fs2.readFileSync(filePath, "utf-8"); const results = []; if (Grammar) { let walk2 = function(node) { if (STRING_NODE_TYPES.has(node.type) && !(node.parent && STRING_NODE_TYPES.has(node.parent.type))) { const start = node.startPosition; const raw = content.slice(node.startIndex, node.endIndex); const value = raw.replace(/^(['"`])|(\1)$/g, ""); const metadata = { value, filePath, line: start.row + 1, column: start.column }; const varName = getVariableName(node); if (varName) metadata.variableName = varName; if (includeSnippet) { const snippetData = getSnippet(content, metadata.line, metadata.column); Object.assign(metadata, snippetData); } results.push(metadata); } node.children.forEach(walk2); }; var walk = walk2; const parser = new Parser(); parser.setLanguage(Grammar); const tree = parser.parse(content); walk2(tree.rootNode); } else { const regex = /(['"`])((?:\\.|(?!\1).)*?)\1/g; for (const [idx, line] of content.split("\n").entries()) { let match; while (match = regex.exec(line)) { const [, , val] = match; const metadata = { value: val, filePath, line: idx + 1, column: match.index }; if (includeSnippet) { const snippetData = getSnippet(content, metadata.line, metadata.column); Object.assign(metadata, snippetData); } results.push(metadata); } } } return results; } function getVariableName(node) { let curr = node; while (curr) { const parent = curr.parent; if (!parent) break; if (parent.type === "variable_declarator" || parent.type === "assignment_expression" || parent.type === "assignment") { const id = parent.child(0); if (id?.type === "identifier") return id.text; } if (parent.type === "assignment") { const id = parent.child(0); if (id?.type === "identifier") return id.text; } if (parent.type === "pair") { const key = parent.child(0); if (key?.type === "identifier") return key.text; if (key?.type === "string") return key.text.replace(/^['"`]|['"`]$/g, ""); } if (parent.type === "parameter" || parent.type === "parameter_definition") { const id = parent.child(0); if (id?.type === "identifier") return id.text; } curr = parent; } return void 0; } function extractStringsFromFiles(files, includeSnippet = false) { return files.flatMap((fp) => extractStringsFromFile(path3.resolve(fp), includeSnippet)); } // src/core/patternLoader.ts import fs3 from "fs"; import yaml from "js-yaml"; function loadPatterns(filePath) { if (!fs3.existsSync(filePath)) { throw new Error(`Can't read patterns data. File not found: ${filePath}`); } const content = fs3.readFileSync(filePath, "utf-8"); const data = yaml.load(content); if (!data || !data.patterns) { throw new Error(`Invalid YAML structure. Missing 'patterns' key in ${filePath}`); } const patterns = []; for (const item of data.patterns) { if (!item.pattern) continue; patterns.push({ name: item.pattern.name, regex: item.pattern.regex, confidence: item.pattern.confidence }); } return patterns; } // src/core/helpers/secretKeyGenerator.ts import crypto from "crypto"; import path4 from "path"; var patternToDescription = { "api_?key": "api_key", "auth_?key": "auth_key", "service_?key": "service_key", "account_?key": "account_key", "db_?key": "database_key", "database_?key": "database_key", "priv_?key": "private_key", "private_?key": "private_key", "client_?key": "client_key", "db_?pass": "database_password", "database_?pass": "database_password", "key_?pass": "key_password", "password": "password", "passwd": "password", "pwd": "password", "secret": "secret", "contrase\xF1a": "password_spanish", "contrasena": "password_spanish", ".*api[-_]?key.*": "api_key", ".*auth[-_]?key.*": "auth_key", ".*service[-_]?key.*": "service_key", ".*account[-_]?key.*": "account_key", ".*db[-_]?key.*": "database_key", ".*database[-_]?key.*": "database_key", ".*priv[-_]?key.*": "private_key", ".*private[-_]?key.*": "private_key", ".*client[-_]?key.*": "client_key", ".*db[-_]?pass.*": "database_password", ".*database[-_]?pass.*": "database_password", ".*key[-_]?pass.*": "key_password", ".*password.*": "password", ".*passwd.*": "password", ".*pwd.*": "password", ".*secret.*": "secret", ".*contrase\xF1a.*": "password", ".*contrasena.*": "password", ".*token.*": "token", ".*session[-_]?id.*": "session_id", ".*access[-_]?token.*": "access_token", ".*refresh[-_]?token.*": "refresh_token", ".*credential.*": "credential", ".*signature.*": "signature", ".*encrypt.*": "encryption_key", ".*decrypt.*": "decryption_key", ".*certificate.*": "certificate", ".*login.*": "login", ".*user[-_]?name.*": "username", ".*username.*": "username", ".*user[-_]?id.*": "user_id", ".*userid.*": "userid" }; var SecretKeyGenerator = class { static { // Propiedades equivalentes a _prefix, _appName, _appVersion this.prefix = "auto_"; } static { this.appName = ""; } static { this.appVersion = ""; } /** * Genera un "key name" descriptivo basándose en variableName, * usando patternToDescription para encontrar un tipo. */ static generateKeyName(variableName) { const descriptivePart2 = this.extractDescriptivePart(variableName); for (const [regexStr, desc] of Object.entries(patternToDescription)) { const regex = new RegExp(regexStr, "i"); if (regex.test(variableName)) { const descriptivePart = this.extractDescriptivePartWithPattern(variableName, regexStr); const finalDescPart = descriptivePart.length > 0 ? descriptivePart : descriptivePart2; return finalDescPart.length > 0 ? `${finalDescPart}-${desc}` : desc; } } return descriptivePart2.length > 0 ? descriptivePart2 : "sensitive-data"; } /** * Extrae la parte descriptiva anterior al patrón detectado. */ static extractDescriptivePartWithPattern(variableName, pattern) { const regex = new RegExp(pattern, "i"); const parts = variableName.split(regex); if (parts.length > 1) { return parts[0].replace(/_/g, ""); } return ""; } /** * Extrae la parte descriptiva de variableName separando por _ o espacios, * omitiendo la primera parte que suele ser la keyword (ej: "db_pass" -> "pass"). */ static extractDescriptivePart(variableName) { const parts = variableName.split(/[_\s]/); if (parts.length > 1) { return parts.slice(1).join("_"); } return ""; } /** * Extrae la "pista de localización" a partir del nombre de archivo * sin extensión (equivalente a Path.GetFileNameWithoutExtension). */ static extractLocationHint(filePathStr) { if (!filePathStr) return ""; const base = path4.basename(filePathStr, path4.extname(filePathStr)); return base.toLowerCase(); } /** * Genera un ID único usando SHA256 sobre hash, fullMethod, _appName, _appVersion. */ static generateID(hash, fullMethod) { const inputData = `${hash}_${fullMethod}_${this.appName}_${this.appVersion}`; const sha256Hash = crypto.createHash("sha256").update(inputData, "utf8").digest("hex"); return sha256Hash; } /** * Genera la key final combinando: * - prefix * - detectionMethod (keyword/entropy/..) * - detectionName * - variableName => se usa generateKeyName * - locationHint * - un hash corto de secretValue */ static generateKey(detectionMethod, detectionName, filePath, variableName, secretValue) { let keyBuilder = this.sanitizeKeyPart(this.prefix); switch (detectionMethod.toLowerCase()) { case "keyword": if (variableName) { keyBuilder += this.sanitizeKeyPart(this.generateKeyName(variableName)); } else if (detectionName) { keyBuilder += this.sanitizeKeyPart(detectionName); } break; case "entropy": keyBuilder += "sensitive-data"; break; default: keyBuilder += this.sanitizeKeyPart(detectionName); break; } const locationHint = this.sanitizeKeyPart(this.extractLocationHint(filePath)); if (locationHint) { keyBuilder += `-${locationHint}`; } keyBuilder += `-${this.sanitizeKeyPart(this.generateHash(secretValue))}`; let result = keyBuilder.replace(/-+/g, "-").replace(/^-|-$/g, ""); if (result.length > 200) { result = result.substring(0, 200); } return result; } /** * Limpia la cadena de caracteres no alfanuméricos, * reemplazándolos por guiones y pasando a minúsculas. */ static sanitizeKeyPart(input) { if (!input) return input; let sanitized = input.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase(); sanitized = sanitized.replace(/-+/g, "-"); return sanitized; } /** * Genera un hash SHA256 del input y se queda con los primeros 6 caracteres, * similar al GenerateHash() en .NET */ static generateHash(input) { const hash = crypto.createHash("sha256").update(input, "utf8").digest("hex"); return hash.substring(0, 6); } }; // src/core/detectors/patternScanner.ts function scanWithPatterns(strings, patterns) { const results = []; const highConfidence = patterns.filter((p) => p.confidence === "high"); for (const pat of highConfidence) { const regex = new RegExp(pat.regex, "i"); for (const str of strings) { if (regex.test(str.value)) { const key = SecretKeyGenerator.generateKey( "pattern", // detectionMethod pat.name, // detectionName str.filePath, // filePath str.variableName ?? "", // variableName (si existe) str.value // secretValue ); if (!results.some((r) => r.value === str.value && r.filePath === str.filePath && r.line === str.line)) { results.push({ value: str.value, key, name: pat.name, confidence: pat.confidence, discoveredBy: "pattern", filePath: str.filePath, line: str.line, snippet: str.snippet, highlight: str.highlight, snippetLineNumber: str.snippetLineNumber, variableName: str.variableName }); } } } } return results; } // src/core/detectors/plugins/RegexBaseDetector.ts var RegexBasedDetector = class { /** * Implementa la lógica de containsSecret usando la tokenRegex. */ containsSecret(input) { return this.tokenRegex.test(input); } }; // src/core/detectors/plugins/database/MongoDbDetector.ts var MongoDbDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "MongoDB Connection String"; this.tokenRegex = new RegExp( [ // MongoDB SRV URI (Atlas/cloud) "mongodb\\+srv:\\/\\/[a-zA-Z0-9._%+-]+:[^@\\s]+@[^\\/\\s]+\\.[^\\/\\s]+\\/[a-zA-Z0-9_-]+", // MongoDB URI (self-hosted or local) "mongodb:\\/\\/[a-zA-Z0-9._%+-]+:[^@\\s]+@[^\\/\\s]+(:\\d+)?\\/[a-zA-Z0-9_-]+", // In env or config `MONGODB_URI\\s*[:=]\\s*['"]?mongodb[^'"\\s]+['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/PostgreSQLDetector.ts var PostgreSQLDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "PostgreSQL Connection String"; this.tokenRegex = new RegExp( [ // PostgreSQL URI "postgres:\\/\\/[a-zA-Z0-9._%+-]+:[^@\\s]+@[^\\/\\s]+(:\\d+)?\\/[a-zA-Z0-9_-]+", // Environment variable style `POSTGRES_(URL|URI|PASSWORD)\\s*[:=]\\s*['"]?.+['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/MySQLDetector.ts var MySQLDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "MySQL Connection String"; this.tokenRegex = new RegExp( [ // MySQL URI "mysql:\\/\\/[a-zA-Z0-9._%+-]+:[^@\\s]+@[^\\/\\s]+(:\\d+)?\\/[a-zA-Z0-9_-]+", // Env variable style `MYSQL_(URL|URI|PASSWORD)\\s*[:=]\\s*['"]?.+['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/RedisDetector.ts var RedisDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Redis Connection String"; this.tokenRegex = new RegExp( [ // Redis URI with password "redis:\\/\\:[^@\\s]+@[^\\/\\s]+(:\\d+)?", // Environment variable style `REDIS_URL\\s*[:=]\\s*['"]?redis:\\/\\/[^'"\\s]+['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/ElasticsearchDetector.ts var ElasticsearchDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Elasticsearch Credentials"; this.tokenRegex = new RegExp( [ // Elasticsearch URL with basic auth "https?:\\/\\/[a-zA-Z0-9._%+-]+:[^@\\s]+@[^\\/\\s]+(:\\d+)?\\/?", // Environment variable style `ELASTICSEARCH_(URL|PASSWORD)\\s*[:=]\\s*['"]?.+['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/FirebaseDetector.ts var FirebaseDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Firebase API Key"; this.tokenRegex = new RegExp( [ // Firebase API Key (General format) "AIza[0-9A-Za-z-_]{35}", // Firebase Admin SDK Service Account `FIREBASE_AUTH\\s*[:=]\\s*['"]?AIza[0-9A-Za-z-_]{35}['"]?`, // Firebase Realtime Database URL (with API keys) "[a-zA-Z0-9_-]+\\.firebaseio\\.com/.+/.+/.+/.+", // Firebase credentials `GOOGLE_APPLICATION_CREDENTIALS\\s*[:=]\\s*['"]?firebase-adminsdk-[a-z0-9]{16}\\@[a-z0-9]+\\.iam\\.gserviceaccount\\.com['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/SupabaseDetector.ts var SupabaseDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Supabase Credentials"; this.tokenRegex = new RegExp( [ // Supabase URL `SUPABASE_URL\\s*[:=]\\s*['"]?https:\\/\\/[a-z0-9]{20,40}\\.supabase\\.co['"]?`, // Supabase anon key `SUPABASE_ANON_KEY\\s*[:=]\\s*['"]?[a-zA-Z0-9-_]{40,100}['"]?`, // Supabase service role key `SUPABASE_SERVICE_ROLE_KEY\\s*[:=]\\s*['"]?[a-zA-Z0-9-_]{40,100}['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/GoogleCloudStorageDetector.ts var GoogleCloudStorageDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Google Cloud Storage Key"; this.tokenRegex = new RegExp( [ // Service account JSON key fields '"type"\\s*:\\s*"service_account"', '"project_id"\\s*:\\s*"[a-z0-9-]+"', '"private_key_id"\\s*:\\s*"[a-f0-9]+"', '"private_key"\\s*:\\s*"-----BEGIN PRIVATE KEY-----[^"]+-----END PRIVATE KEY-----"', // Environment variable style `GOOGLE_APPLICATION_CREDENTIALS\\s*[:=]\\s*['"]?.+\\.json['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/database/CloudantDetector.ts var CloudantDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Cloudant Credentials"; this.tokenRegex = new RegExp( [ // Cloudant URL with API Key (basic format) "https?:\\/\\/[a-zA-Z0-9]+:[a-zA-Z0-9_-]+@[^\\/]+\\.cloudant\\.com", // Cloudant credentials with API Key (no base URL) `cloudant\\.(key|password|token)\\s*[:=]\\s*['"]?[a-zA-Z0-9_-]{32}['"]?`, // Cloudant credentials for service accounts `CLOUDANT_API_KEY\\s*[:=]\\s*['"]?[a-zA-Z0-9_-]{32}['"]?`, // Cloudant URL with basic auth and no user/password "https?:\\/\\/[a-zA-Z0-9]+@[^\\/]+\\.cloudant\\.com" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/SendGridDetector.ts var SendGridDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "SendGrid API Key"; this.tokenRegex = new RegExp( [ "SG.[a-zA-Z0-9_-]{22}.[a-zA-Z0-9_-]{43}", `SENDGRID_API_KEYs*[:=]s*["']?SG.[a-zA-Z0-9_-]{22}.[a-zA-Z0-9_-]{43}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/SlackDetector.ts var SlackDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Slack Token or Webhook"; this.tokenRegex = new RegExp( [ "xox(?:a|b|p|o|s|r)-(?:d+-)+[a-z0-9]+", "https://hooks.slack.com/services/T[a-zA-Z0-9_]+/B[a-zA-Z0-9_]+/[a-zA-Z0-9_]+" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/WhatsAppCloudDetector.ts var WhatsAppCloudDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "WhatsApp Cloud API Token"; this.tokenRegex = new RegExp( [ "EAACEdEose0cBA[0-9A-Za-z]{32,}", `WHATSAPP_TOKENs*[:=]s*["']?EAACEdEose0cBA[0-9A-Za-z]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/VonageDetector.ts var VonageDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Vonage (Nexmo) API Credentials"; this.tokenRegex = new RegExp( [ `VONAGE_API_KEYs*[:=]s*["']?[a-zA-Z0-9]{8}["']?`, `VONAGE_API_SECRETs*[:=]s*["']?[a-zA-Z0-9]{16,}["']?`, `NEXMO_(API_KEY|API_SECRET)s*[:=]s*["']?[a-zA-Z0-9]{8,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/PlivoDetector.ts var PlivoDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Plivo API Credentials"; this.tokenRegex = new RegExp( [ `PLIVO_AUTH_IDs*[:=]s*["']?[A-Z0-9]{20}["']?`, `PLIVO_AUTH_TOKENs*[:=]s*["']?[A-Za-z0-9]{32}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/MailchimpDetector.ts var MailchimpDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Mailchimp Access Key"; this.tokenRegex = new RegExp( [ "[0-9a-z]{32}-us[0-9]{1,2}", `MAILCHIMP_API_KEYs*[:=]s*["']?[0-9a-z]{32}-us[0-9]{1,2}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/PostmarkDetector.ts var PostmarkDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Postmark Server Token"; this.tokenRegex = new RegExp( [ `POSTMARK_API_TOKENs*[:=]s*["']?[a-zA-Z0-9]{36}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/ZoomApiDetector.ts var ZoomApiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Zoom JWT or SDK Secret"; this.tokenRegex = new RegExp( [ `zoom_jwt_tokens*[:=]s*["']?[a-zA-Z0-9_-]{20,}["']?`, `ZOOM_(JWT|SDK)_SECRETs*[:=]s*["']?[a-zA-Z0-9_-]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/SmtpGenericDetector.ts var SmtpGenericDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Generic SMTP Password"; this.tokenRegex = new RegExp( [ `(SMTP|EMAIL|MAIL)(_|)?(PASS|PASSWORD|AUTH)s*[:=]s*["']?.{8,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/DiscordBotTokenDetector.ts var DiscordBotTokenDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Discord Bot Token"; this.tokenRegex = new RegExp( [ "[MNOPQ][a-zA-Zd_-]{23,25}.[a-zA-Zd_-]{6}.[a-zA-Zd_-]{27}" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/messages/MailgunDetector.ts var MailgunDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Mailgun API Key"; this.tokenRegex = new RegExp( [ "key-[a-f0-9]{32}", `MAILGUN_API_KEYs*[:=]s*["']?key-[a-f0-9]{32}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/identity/FirebaseAuthDetector.ts var FirebaseAuthDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Firebase Auth Keys"; this.tokenRegex = new RegExp( [ `FIREBASE_API_KEYs*[:=]s*["']?[A-Za-z0-9-_]{39,}["']?`, `FIREBASE_AUTH_DOMAINs*[:=]s*["']?[a-z0-9-]+.firebaseapp.com["']?`, `FIREBASE_PROJECT_IDs*[:=]s*["']?[a-z0-9-]{6,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/identity/OktaDetector.ts var OktaDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Okta API Key"; this.tokenRegex = new RegExp( [ `OKTA_CLIENT_TOKENs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?`, `OKTA_API_KEYs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?`, "https://[a-zA-Z0-9_-]+.okta.com" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/identity/ClerkDetector.ts var ClerkDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Clerk.dev API Keys"; this.tokenRegex = new RegExp( [ `CLERK_API_KEYs*[:=]s*["']?[a-zA-Z0-9]{40,}["']?`, `CLERK_SECRET_KEYs*[:=]s*["']?[a-zA-Z0-9]{40,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/identity/SuperTokensDetector.ts var SuperTokensDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "SuperTokens API Key"; this.tokenRegex = new RegExp( [ `SUPERTOKENS_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{30,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/identity/Auth0Detector.ts var Auth0Detector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Auth0 Credentials"; this.tokenRegex = new RegExp( [ `AUTH0_DOMAINs*[:=]s*["']?[a-zA-Z0-9_-]+.auth0.com["']?`, `AUTH0_CLIENT_SECRETs*[:=]s*["']?[a-zA-Z0-9_-]{32,}["']?`, `AUTH0_API_TOKENs*[:=]s*["']?[a-zA-Z0-9_-]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/NpmTokenDetector.ts var NpmTokenDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "NPM Token"; /** * Detects NPM tokens in `.npmrc` or env-like strings. * Example: * //registry.npmjs.org/:_authToken=npm_abcd1234... * //my-registry/:_authToken=31dd103e-017c-4f0a-bd9d-9fa970bd24a4 */ this.tokenRegex = new RegExp( String.raw`\/\/.+\/:_authToken=\s*((npm_[a-zA-Z0-9]+)|([A-Fa-f0-9-]{36}))`, "gi" ); } // Opcional: podrías agregar isFormallyValid o verifySecret si decides extenderlo. }; // src/core/detectors/plugins/security/JenkinsDetector.ts var JenkinsDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Jenkins Credentials"; this.tokenRegex = new RegExp( [ `JENKINS_(USER|API_TOKEN|AUTH)s*[:=]s*["']?[a-zA-Z0-9@:_-]{8,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/GitHubActionsDetector.ts var GitHubActionsDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "GitHub Actions Secrets"; this.tokenRegex = new RegExp( [ `GITHUB_TOKENs*[:=]s*["']?[a-zA-Z0-9_]{20,}["']?`, `ACTIONS_RUNTIME_TOKENs*[:=]s*["']?[a-zA-Z0-9_-]{30,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/TerraformCloudDetector.ts var TerraformCloudDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Terraform Cloud Token"; this.tokenRegex = new RegExp( [ "tfp_[a-zA-Z0-9]{30,}", `TERRAFORM_TOKENs*[:=]s*["']?tfp_[a-zA-Z0-9]{30,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/DroneCiDetector.ts var DroneCiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Drone CI Secrets"; this.tokenRegex = new RegExp( [ `DRONE_TOKENs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?`, `DRONE_SECRETs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/PulumiDetector.ts var PulumiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Pulumi Access Token"; this.tokenRegex = new RegExp( [ "pul-[a-f0-9]{32}", `PULUMI_ACCESS_TOKENs*[:=]s*["']?pul-[a-f0-9]{32}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/BuddyCiDetector.ts var BuddyCiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Buddy API Token"; this.tokenRegex = new RegExp( [ `BUDDY_API_TOKENs*[:=]s*["']?[a-zA-Z0-9-_]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/GitLabCiDetector.ts var GitLabCiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "GitLab CI/CD Tokens"; this.tokenRegex = new RegExp( [ "glpat-[A-Za-z0-9_-]{20,50}", `CI_JOB_TOKENs*[:=]s*["']?[a-zA-Z0-9_-]{20,}["']?`, `GL_SECRETs*[:=]s*["']?.{16,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/CodefreshDetector.ts var CodefreshDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Codefresh API Token"; this.tokenRegex = new RegExp( [ `CODEFRESH_TOKENs*[:=]s*["']?[a-zA-Z0-9-_]{30,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/TravisCiDetector.ts var TravisCiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Travis CI Token"; this.tokenRegex = new RegExp( [ `TRAVIS_TOKENs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/CircleCiDetector.ts var CircleCiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "CircleCI Tokens"; this.tokenRegex = new RegExp( [ `CIRCLE_TOKENs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?`, `CIRCLECI_TOKENs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/security/BitbucketCiDetector.ts var BitbucketCiDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Bitbucket Pipelines Tokens"; this.tokenRegex = new RegExp( [ "bbp-[a-f0-9]{40,}", `BITBUCKET_SECRETs*[:=]s*["']?[a-zA-Z0-9-]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/TwilioKeyDetector.ts var TwilioKeyDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Twilio API Key"; /** * Detects: * - Account SID: ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * - Secret Key: SKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * - Optional: AK/RK keys used by SDKs * - Contextual: TWILIO_AUTH_TOKEN=... */ this.tokenRegex = new RegExp( [ // Account SID "AC[a-z0-9]{32}", // Secret Key "SK[a-z0-9]{32}", // Optional SDK keys "AK[a-z0-9]{32}", "RK[a-z0-9]{32}", // In context (env var style) `TWILIO_(AUTH|API)?_?TOKEN\\s*[:=]\\s*['"]?[a-z0-9]{32}['"]?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/JwtTokenDetector.ts var JwtTokenDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "JSON Web Token"; /** * Regex para detectar tokens JWT (header.payload.signature), incluyendo firmados o incompletos. */ this.tokenRegex = new RegExp( "eyJ[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.?[A-Za-z0-9-_.+/=]*?", "gi" ); } /** * Verifica si el token tiene una estructura válida y decodificable (header y payload con JSON). */ async isFormallyValid(token) { const parts = token.split("."); if (parts.length < 2) return false; for (let i = 0; i < 2; i++) { const part = parts[i]; try { const padded = this.addPadding(part); const decoded = Buffer.from(padded, "base64").toString("utf-8"); JSON.parse(decoded); } catch { return false; } } return true; } addPadding(input) { const mod = input.length % 4; if (mod === 2) return input + "=="; if (mod === 3) return input + "="; if (mod === 1) throw new Error("Invalid JWT base64 padding"); return input; } }; // src/core/detectors/plugins/IbmDetector.ts var IbmDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "IBM Cloud Credentials"; /** * Detects: * - IAM API keys (44-char alphanumeric) * - COS HMAC secret keys (48-char hex) */ this.tokenRegex = new RegExp( [ // 1. IBM IAM API key in context: ibm_cloud_api_key=... `(?:ibm[_\\-]?cloud[_\\-]?iam|cloud[_\\-]?iam|ibm[_\\-]?cloud|ibm[_\\-]?iam|ibm|iam|cloud)?[_\\-]?(api)?[_\\-]?(key|pwd|password|pass|token)[_\\-]?["']?([a-zA-Z0-9_\\-]{44})(?![a-zA-Z0-9_\\-])`, // 2. COS HMAC secret keys (contextual): ibm-cos-secret-key `(?:ibm[-_]?cos[-_]?hmac|cos[-_]?hmac|ibm[-_]?cos|ibm[-_]?hmac|hmac|cos)?[-_]?secret[-_]?key["']?([a-f0-9]{48})(?![a-f0-9])` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/AWSDetector.ts var AWSDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "AWS Secrets"; /** * Conjunto de expresiones para múltiples tipos de secretos AWS. */ this.tokenRegex = new RegExp( [ // 1. AWS Access Key ID (AKIA, ASIA, etc.) "(?<![A-Z0-9])[A3T][A-Z0-9]{16}(?![A-Z0-9])", // A3T-style "(?<![A-Z0-9])(AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}(?![A-Z0-9])", // Classic patterns // 2. AWS Secret Access Key (base64-like, 40 chars) "(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])", // 3. AWS credentials with context (key|secret|token) `(aws|amazon)?[^a-zA-Z0-9]?(key|pwd|pw|password|pass|token)[^a-zA-Z0-9]{0,3}["']([A-Za-z0-9/+=]{40,})["']`, // 4. AWS CLI config format "\\[default\\]\\s*aws_access_key_id\\s*=\\s*[A-Z0-9]{20}\\s*aws_secret_access_key\\s*=\\s*[A-Za-z0-9/+=]{40}", // 5. AWS KMS Key IDs (UUIDs prefixed with alias/ or key/) "arn:aws:kms:[a-z0-9-]+:\\d{12}:key/[a-f0-9-]{36}", "alias/[A-Za-z0-9/_+=.@-]+", // 6. AWS ARNs (S3, Lambda, SES, etc.) `arn:aws:[a-z0-9-]+:[a-z0-9-]*:\\d{12}:[^\\s'"]+`, // 7. AWS session token (variable name + base64) `(aws_session_token|aws_security_token)[\\s:='"]+([A-Za-z0-9/+=]{16,})` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/logs/NewRelicDetector.ts var NewRelicDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "New Relic API Keys"; this.tokenRegex = new RegExp( [ `NEW_RELIC_LICENSE_KEYs*[:=]s*["']?[a-zA-Z0-9]{40}["']?`, `NEW_RELIC_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{30,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/logs/SentryDetector.ts var SentryDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Sentry Credentials"; this.tokenRegex = new RegExp( [ `SENTRY_DSNs*[:=]s*["']?https://[a-zA-Z0-9]+@[a-zA-Z0-9.-]+/[0-9]+["']?`, `SENTRY_AUTH_TOKENs*[:=]s*["']?[a-zA-Z0-9-_]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/logs/MixpanelDetector.ts var MixpanelDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Mixpanel Token"; this.tokenRegex = new RegExp( [ `MIXPANEL_TOKENs*[:=]s*["']?[a-zA-Z0-9]{32}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/logs/AmplitudeDetector.ts var AmplitudeDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Amplitude API Key"; this.tokenRegex = new RegExp( [ `AMPLITUDE_API_KEYs*[:=]s*["']?[a-zA-Z0-9]{32}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/logs/LogtailDetector.ts var LogtailDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Logtail / Betterstack Token"; this.tokenRegex = new RegExp( [ `LOGTAIL_TOKENs*[:=]s*["']?[a-zA-Z0-9]{30,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/logs/DatadogDetector.ts var DatadogDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Datadog API Keys"; this.tokenRegex = new RegExp( [ `DATADOG_API_KEYs*[:=]s*["']?[a-z0-9]{32}["']?`, `DD_API_KEYs*[:=]s*["']?[a-z0-9]{32}["']?`, `DD_APP_KEYs*[:=]s*["']?[a-z0-9]{32}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/ReplicateDetector.ts var ReplicateDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Replicate API Token"; this.tokenRegex = new RegExp( [ `REPLICATE_API_TOKENs*[:=]s*["']?[a-z0-9_-]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/VespaDetector.ts var VespaDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Vespa Cloud API Token"; this.tokenRegex = new RegExp( [ `VESPA_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/VertexAIDetector.ts var VertexAIDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Google Vertex AI Credentials"; this.tokenRegex = new RegExp( [ "AIza[0-9A-Za-z-_]{35}", `GOOGLE_VERTEX_API_KEYs*[:=]s*["']?AIza[0-9A-Za-z-_]{35}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/BasetenDetector.ts var BasetenDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Baseten API Key"; this.tokenRegex = new RegExp( [ `BASETEN_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/AnthropicDetector.ts var AnthropicDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Anthropic API Key"; this.tokenRegex = new RegExp( [ "cla-[a-zA-Z0-9]{40,}", `ANTHROPIC_API_KEYs*[:=]s*["']?cla-[a-zA-Z0-9]{40,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/StabilityAIDetector.ts var StabilityAIDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Stability AI Token"; this.tokenRegex = new RegExp( [ "stability-[a-zA-Z0-9]{40,}", `STABILITY_API_KEYs*[:=]s*["']?stability-[a-zA-Z0-9]{40,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/WeaviateDetector.ts var WeaviateDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Weaviate API Key"; this.tokenRegex = new RegExp( [ `WEAVIATE_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{32,}["']?`, "Authorization:s*Bearers*[a-zA-Z0-9-_]{20,}" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/LangSmithDetector.ts var LangSmithDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "LangSmith API Key"; this.tokenRegex = new RegExp( [ `LANGSMITH_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/OpenAIDetector.ts var OpenAIDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "OpenAI API Key"; this.tokenRegex = new RegExp( [ "sk-[a-zA-Z0-9]{48}", `OPENAI_API_KEYs*[:=]s*["']?sk-[a-zA-Z0-9]{48}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/ChromaDetector.ts var ChromaDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Chroma API Token"; this.tokenRegex = new RegExp( [ `CHROMA_API_TOKENs*[:=]s*["']?[a-zA-Z0-9]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/HuggingFaceDetector.ts var HuggingFaceDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "HuggingFace Access Token"; this.tokenRegex = new RegExp( [ "hf_[a-zA-Z0-9]{32,}", `HUGGINGFACEHUB_API_TOKENs*[:=]s*["']?hf_[a-zA-Z0-9]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/LangChainDetector.ts var LangChainDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "LangChain API Key"; this.tokenRegex = new RegExp( [ `LANGCHAIN_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{20,}["']?`, "langchain-js.vercel.app" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/MistralDetector.ts var MistralDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Mistral API Key"; this.tokenRegex = new RegExp( [ "mistral-[a-zA-Z0-9]{40,}", `MISTRAL_API_KEYs*[:=]s*["']?mistral-[a-zA-Z0-9]{40,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/PineconeDetector.ts var PineconeDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Pinecone API Key"; this.tokenRegex = new RegExp( [ `PINECONE_API_KEYs*[:=]s*["']?[a-z0-9-]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/QdrantDetector.ts var QdrantDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Qdrant API Key"; this.tokenRegex = new RegExp( [ `QDRANT_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/CohereDetector.ts var CohereDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Cohere API Key"; this.tokenRegex = new RegExp( [ "cohere-[a-zA-Z0-9]{32,}", `COHERE_API_KEYs*[:=]s*["']?cohere-[a-zA-Z0-9]{32,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/ai/PerplexityDetector.ts var PerplexityDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Perplexity API Token"; this.tokenRegex = new RegExp( [ `PERPLEXITY_API_KEYs*[:=]s*["']?[a-zA-Z0-9-_]{40,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/deployment/BitbucketTokenDetector.ts var BitbucketTokenDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Bitbucket Token"; this.tokenRegex = new RegExp( [ `bitbucket_(client_id|secret)s*[:=]s*["']?[A-Za-z0-9-_]{20,}["']?`, `BITBUCKET_(CLIENT|SECRET)_KEYs*[:=]s*["']?[A-Za-z0-9-_]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/deployment/CircleCITokenDetector.ts var CircleCITokenDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "CircleCI Token"; this.tokenRegex = new RegExp( [ `CIRCLECI_API_TOKENs*[:=]s*["']?[A-Za-z0-9]{20,}["']?`, `circleci_tokens*[:=]s*["']?[A-Za-z0-9]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/deployment/AzureDevOpsDetector.ts var AzureDevOpsDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Azure DevOps Token"; this.tokenRegex = new RegExp( [ `AZURE_DEVOPS_(TOKEN|PAT)s*[:=]s*["']?[a-zA-Z0-9]{20,}["']?`, `ado_tokens*[:=]s*["']?[a-zA-Z0-9]{20,}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/cloud/NetlifyDetector.ts var NetlifyDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Netlify Personal Access Token"; this.tokenRegex = new RegExp( [ `NETLIFY_AUTH_TOKENs*[:=]s*["']?[a-zA-Z0-9]{40}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/cloud/VercelDetector.ts var VercelDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Vercel Token"; this.tokenRegex = new RegExp( [ `VERCEL_TOKENs*[:=]s*["']?[a-zA-Z0-9_-]{64,}["']?`, "vercel.com.*token=[a-zA-Z0-9_-]{64,}" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/cloud/DigitalOceanDetector.ts var DigitalOceanDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "DigitalOcean Personal Access Token"; this.tokenRegex = new RegExp( [ `do_(prod|dev)?_?tokens*[:=]s*["']?[a-f0-9]{64}["']?`, `DIGITALOCEAN_ACCESS_TOKENs*[:=]s*["']?[a-f0-9]{64}["']?` ].join("|"), "gi" ); } }; // src/core/detectors/plugins/cloud/GcpKeyDetector.ts var GcpKeyDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "GCP Service Account Key"; this.tokenRegex = new RegExp( [ '\\"type\\":\\s*\\"service_account\\"', '\\"project_id\\":\\s*\\"[a-z0-9\\-]+\\"', '\\"private_key_id\\":\\s*\\"[a-f0-9]{40}\\"', '\\"private_key\\":\\s*\\"-----BEGIN PRIVATE KEY-----[\\s\\S]+?-----END PRIVATE KEY-----\\"' ].join("|"), "gi" ); } }; // src/core/detectors/plugins/cloud/HerokuDetector.ts var HerokuDetector = class extends RegexBasedDetector { constructor() { super(...arguments); this.secretType = "Heroku API Key"; this.tokenRegex = new RegExp( [ `HEROKU_API_KEYs*[:=]s*["']?[a-f0-9]{32}["']?`, "Authorization:s*Bearers*[a-f0-9]{32}" ].join("|"), "gi" ); } }; // src/core/detectors/plugins/cloud/CloudflareDetector.ts var CloudflareDetector = class extends RegexBasedDetector { construct