UNPKG

@samiyev/guardian

Version:

Research-backed code quality guardian for AI-assisted development. Detects hardcodes, secrets, circular deps, framework leaks, entity exposure, and 9 architecture violations. Enforces Clean Architecture/DDD principles. Works with GitHub Copilot, Cursor, W

164 lines 7.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SecretDetector = void 0; const node_1 = require("@secretlint/node"); const SecretViolation_1 = require("../../domain/value-objects/SecretViolation"); const SecretExamples_1 = require("../../domain/constants/SecretExamples"); const rules_1 = require("../../shared/constants/rules"); /** * Detects hardcoded secrets in TypeScript/JavaScript code * * Uses industry-standard Secretlint library to detect 350+ types of secrets * including AWS keys, GitHub tokens, NPM tokens, SSH keys, API keys, and more. * * All detected secrets are marked as CRITICAL severity because they represent * serious security risks that could lead to unauthorized access or data breaches. * * @example * ```typescript * const detector = new SecretDetector() * const code = `const AWS_KEY = "AKIA1234567890ABCDEF"` * const violations = await detector.detectAll(code, 'config.ts') * // Returns array of SecretViolation objects with CRITICAL severity * ``` */ class SecretDetector { secretlintConfig = { rules: [ { id: rules_1.EXTERNAL_PACKAGES.SECRETLINT_PRESET, }, ], }; /** * Detects all types of hardcoded secrets in the provided code * * @param code - Source code to analyze * @param filePath - Path to the file being analyzed * @returns Promise resolving to array of secret violations */ async detectAll(code, filePath) { try { const engine = await (0, node_1.createEngine)({ cwd: process.cwd(), configFileJSON: this.secretlintConfig, formatter: "stylish", color: false, }); const result = await engine.executeOnContent({ content: code, filePath, }); return this.parseOutputToViolations(result.output, filePath); } catch (_error) { return []; } } parseOutputToViolations(output, filePath) { const violations = []; if (!output || output.trim() === "") { return violations; } const lines = output.split("\n"); for (const line of lines) { const match = /^\s*(\d+):(\d+)\s+(error|warning)\s+(.+?)\s+(.+)$/.exec(line); if (match) { const [, lineNum, column, , message, ruleId] = match; const secretType = this.extractSecretType(message, ruleId); const violation = SecretViolation_1.SecretViolation.create(filePath, parseInt(lineNum, 10), parseInt(column, 10), secretType, message); violations.push(violation); } } return violations; } extractSecretType(message, ruleId) { const lowerMessage = message.toLowerCase(); const ruleBasedType = this.extractByRuleId(ruleId, lowerMessage); if (ruleBasedType) { return ruleBasedType; } return this.extractByMessage(lowerMessage); } extractByRuleId(ruleId, lowerMessage) { if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.AWS)) { return this.extractAwsType(lowerMessage); } if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.GITHUB)) { return this.extractGithubType(lowerMessage); } if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.NPM)) { return SecretExamples_1.SECRET_TYPE_NAMES.NPM_TOKEN; } if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.GCP) || ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.GOOGLE)) { return SecretExamples_1.SECRET_TYPE_NAMES.GCP_SERVICE_ACCOUNT_KEY; } if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.PRIVATEKEY) || ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.SSH)) { return this.extractSshType(lowerMessage); } if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.SLACK)) { return this.extractSlackType(lowerMessage); } if (ruleId.includes(SecretExamples_1.SECRET_KEYWORDS.BASICAUTH)) { return SecretExamples_1.SECRET_TYPE_NAMES.BASIC_AUTH_CREDENTIALS; } return null; } extractAwsType(lowerMessage) { if (lowerMessage.includes(SecretExamples_1.SECRET_KEYWORDS.ACCESS_KEY)) { return SecretExamples_1.SECRET_TYPE_NAMES.AWS_ACCESS_KEY; } if (lowerMessage.includes(SecretExamples_1.SECRET_KEYWORDS.SECRET)) { return SecretExamples_1.SECRET_TYPE_NAMES.AWS_SECRET_KEY; } return SecretExamples_1.SECRET_TYPE_NAMES.AWS_CREDENTIAL; } extractGithubType(lowerMessage) { if (lowerMessage.includes(SecretExamples_1.SECRET_KEYWORDS.PERSONAL_ACCESS_TOKEN)) { return SecretExamples_1.SECRET_TYPE_NAMES.GITHUB_PERSONAL_ACCESS_TOKEN; } if (lowerMessage.includes(SecretExamples_1.SECRET_KEYWORDS.OAUTH)) { return SecretExamples_1.SECRET_TYPE_NAMES.GITHUB_OAUTH_TOKEN; } return SecretExamples_1.SECRET_TYPE_NAMES.GITHUB_TOKEN; } extractSshType(lowerMessage) { const sshTypeMap = [ [SecretExamples_1.SECRET_KEYWORDS.RSA, SecretExamples_1.SECRET_TYPE_NAMES.SSH_RSA_PRIVATE_KEY], [SecretExamples_1.SECRET_KEYWORDS.DSA, SecretExamples_1.SECRET_TYPE_NAMES.SSH_DSA_PRIVATE_KEY], [SecretExamples_1.SECRET_KEYWORDS.ECDSA, SecretExamples_1.SECRET_TYPE_NAMES.SSH_ECDSA_PRIVATE_KEY], [SecretExamples_1.SECRET_KEYWORDS.ED25519, SecretExamples_1.SECRET_TYPE_NAMES.SSH_ED25519_PRIVATE_KEY], ]; for (const [keyword, typeName] of sshTypeMap) { if (lowerMessage.includes(keyword)) { return typeName; } } return SecretExamples_1.SECRET_TYPE_NAMES.SSH_PRIVATE_KEY; } extractSlackType(lowerMessage) { if (lowerMessage.includes(SecretExamples_1.SECRET_KEYWORDS.BOT)) { return SecretExamples_1.SECRET_TYPE_NAMES.SLACK_BOT_TOKEN; } if (lowerMessage.includes(SecretExamples_1.SECRET_KEYWORDS.USER)) { return SecretExamples_1.SECRET_TYPE_NAMES.SLACK_USER_TOKEN; } return SecretExamples_1.SECRET_TYPE_NAMES.SLACK_TOKEN; } extractByMessage(lowerMessage) { const messageTypeMap = [ [SecretExamples_1.SECRET_KEYWORDS.API_KEY, SecretExamples_1.SECRET_TYPE_NAMES.API_KEY], [SecretExamples_1.SECRET_KEYWORDS.TOKEN, SecretExamples_1.SECRET_TYPE_NAMES.AUTHENTICATION_TOKEN], [SecretExamples_1.SECRET_KEYWORDS.PASSWORD, SecretExamples_1.SECRET_TYPE_NAMES.PASSWORD], [SecretExamples_1.SECRET_KEYWORDS.SECRET, SecretExamples_1.SECRET_TYPE_NAMES.SECRET], ]; for (const [keyword, typeName] of messageTypeMap) { if (lowerMessage.includes(keyword)) { return typeName; } } return SecretExamples_1.SECRET_TYPE_NAMES.SENSITIVE_DATA; } } exports.SecretDetector = SecretDetector; //# sourceMappingURL=SecretDetector.js.map