feat: add secret detection with Secretlint (v0.8.0)

Add critical security feature to detect 350+ types of hardcoded secrets
using industry-standard Secretlint library.

Features:
- Detect AWS keys, GitHub tokens, NPM tokens, SSH keys, API keys, etc.
- All secrets marked as CRITICAL severity
- Context-aware remediation suggestions per secret type
- New SecretDetector using @secretlint/node
- New SecretViolation value object (100% test coverage)
- CLI output with "🔐 Secrets" section
- Async pipeline support for secret detection

Tests:
- Added 47 new tests (566 total, 100% pass rate)
- Coverage: 93.3% statements, 83.74% branches
- SecretViolation: 23 tests, 100% coverage
- SecretDetector: 24 tests

Dependencies:
- @secretlint/node: 11.2.5
- @secretlint/core: 11.2.5
- @secretlint/types: 11.2.5
- @secretlint/secretlint-rule-preset-recommend: 11.2.5
This commit is contained in:
imfozilbek
2025-11-25 18:24:22 +05:00
parent 8d400c9517
commit 0b1cc5a79a
18 changed files with 1186 additions and 11 deletions

View File

@@ -9,6 +9,7 @@ import type {
HardcodeViolation,
NamingConventionViolation,
RepositoryPatternViolation,
SecretViolation,
} from "../../application/use-cases/AnalyzeProject"
import { SEVERITY_DISPLAY_LABELS, SEVERITY_SECTION_HEADERS } from "../constants"
import { ViolationGrouper } from "../groupers/ViolationGrouper"
@@ -177,6 +178,22 @@ export class OutputFormatter {
console.log("")
}
formatSecretViolation(sv: SecretViolation, index: number): void {
const location = `${sv.file}:${String(sv.line)}:${String(sv.column)}`
console.log(`${String(index + 1)}. ${location}`)
console.log(` Severity: ${SEVERITY_LABELS[sv.severity]} ⚠️`)
console.log(` Secret Type: ${sv.secretType}`)
console.log(` ${sv.message}`)
console.log(" 🔐 CRITICAL: Rotate this secret immediately!")
console.log(" 💡 Suggestion:")
sv.suggestion.split("\n").forEach((line) => {
if (line.trim()) {
console.log(` ${line}`)
}
})
console.log("")
}
formatHardcodeViolation(hc: HardcodeViolation, index: number): void {
console.log(`${String(index + 1)}. ${hc.file}:${String(hc.line)}:${String(hc.column)}`)
console.log(` Severity: ${SEVERITY_LABELS[hc.severity]}`)

View File

@@ -92,6 +92,7 @@ program
dependencyDirectionViolations,
repositoryPatternViolations,
aggregateBoundaryViolations,
secretViolations,
} = result
const minSeverity: SeverityLevel | undefined = options.onlyCritical
@@ -132,6 +133,7 @@ program
aggregateBoundaryViolations,
minSeverity,
)
secretViolations = grouper.filterBySeverity(secretViolations, minSeverity)
statsFormatter.displaySeverityFilterMessage(
options.onlyCritical,
@@ -245,6 +247,19 @@ program
)
}
if (secretViolations.length > 0) {
console.log(
`\n🔐 Found ${String(secretViolations.length)} hardcoded secret(s) - CRITICAL SECURITY RISK`,
)
outputFormatter.displayGroupedViolations(
secretViolations,
(sv, i) => {
outputFormatter.formatSecretViolation(sv, i)
},
limit,
)
}
if (options.hardcode && hardcodeViolations.length > 0) {
console.log(
`\n${CLI_MESSAGES.HARDCODE_VIOLATIONS_HEADER} ${String(hardcodeViolations.length)} ${CLI_LABELS.HARDCODE_VIOLATIONS}`,
@@ -267,7 +282,8 @@ program
entityExposureViolations.length +
dependencyDirectionViolations.length +
repositoryPatternViolations.length +
aggregateBoundaryViolations.length
aggregateBoundaryViolations.length +
secretViolations.length
statsFormatter.displaySummary(totalIssues, options.verbose)
} catch (error) {