Add hard-coded password detection rule for Kotlin - #33
claudiacodacy wants to merge 1 commit into
Conversation
Codacy already ships a custom hard-coded-password rule (variable name matches password/secret/pwd/key, value is a string literal) for Java, JavaScript/TypeScript, C#, Scala, and Bash, but not for Kotlin. Kotlin only had a narrow rule scoped to build.gradle files, so a plain `val password = "..."` in Kotlin source went undetected. This adds codacy.kotlin.security.hard-coded-password, mirroring the existing Java/JS rule shape (same message, metadata, and name regex), plus multiple-tests fixtures under docs/multiple-tests/codacy-rules-kotlin following the existing Java/JS fixture convention. Validated locally against the pinned opengrep v1.26.0 binary (matching the Dockerfile's OPENGREP_VERSION), go run ./cmd/docgen, go test, and a full docker build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Pull Request Overview
The PR successfully introduces a new security rule for Kotlin, but several implementation gaps exist that limit its effectiveness compared to its Java and JavaScript counterparts. Specifically, the rule currently misses const val declarations and triple-quoted string literals, which are idiomatic in Kotlin for defining constants and secrets.
Additionally, there is a discrepancy between the rule's defined message and the test results fixture, which may lead to test failures in CI. While Codacy analysis reports the PR is up to standards, these logic gaps should be addressed to ensure the rule provides the intended level of security coverage.
About this PR
- The rule implementation is currently limited to variable declarations (
val/var). Hardcoded sensitive values passed directly as function arguments (e.g.,login("hardcoded_password")) will not be detected by this rule.
Test suggestions
- Detect hardcoded password in a 'val' declaration without explicit type.
- Detect hardcoded password in a 'var' declaration without explicit type.
- Detect hardcoded password in a declaration with explicit ': String' type.
- Identify multiple keyword variations (e.g., apiKey, apiSecret) case-insensitively.
- Detect hardcoded secrets assigned using
const valdeclarations - Detect hardcoded secrets in triple-quoted string literals (
"""...""") - Detect hardcoded values passed directly as function arguments
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Detect hardcoded secrets assigned using `const val` declarations
2. Detect hardcoded secrets in triple-quoted string literals (`"""..."""`)
3. Detect hardcoded values passed directly as function arguments
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| - pattern-either: | ||
| - pattern: 'val $PASSWORD = "$VALUE"' | ||
| - pattern: 'var $PASSWORD = "$VALUE"' | ||
| - pattern: 'val $PASSWORD: String = "$VALUE"' | ||
| - pattern: 'var $PASSWORD: String = "$VALUE"' |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: The current patterns do not detect secrets assigned using const val or those stored in triple-quoted string literals ("""..."""), both of which are common in Kotlin projects. It is recommended to update the rule to include these patterns for more robust detection.
| - pattern: 'var $PASSWORD: String = "$VALUE"' | ||
| - metavariable-regex: | ||
| metavariable: "$PASSWORD" | ||
| regex: "(?i).*(password|motdepasse|heslo|adgangskode|wachtwoord|salasana|passwort|passord|senha|geslo|clave|losenord|clave|parola|secret|pwd|(api|secret|private|access|aws|ssh|auth|session|encryption|decryption|gcp)[_-]?key).*" |
There was a problem hiding this comment.
⚪ LOW RISK
Nitpick: The regular expression contains redundant entries. Specifically, the keyword 'clave' is duplicated, and 'secret' is potentially redundant within the current structure.
| regex: "(?i).*(password|motdepasse|heslo|adgangskode|wachtwoord|salasana|passwort|passord|senha|geslo|clave|losenord|clave|parola|secret|pwd|(api|secret|private|access|aws|ssh|auth|session|encryption|decryption|gcp)[_-]?key).*" | |
| regex: "(?i).*(password|motdepasse|heslo|adgangskode|wachtwoord|salasana|passwort|passord|senha|geslo|clave|losenord|parola|secret|pwd|(api|secret|private|access|aws|ssh|auth|session|encryption|decryption|gcp)[_-]?key).*" |
Summary
codacy.<lang>.security.hard-coded-password— a custom rule that flags a plain string literal assigned to a variable named likepassword/secret/pwd/key— for Java, JavaScript/TypeScript, C#, Scala, and Bash. Kotlin had no equivalent; the only Kotlin-specific password rule is scoped tobuild.gradlefiles.codacy.kotlin.security.hard-coded-password, mirroring the existing Java/JS rule (same message, metadata, and name-matching regex), coveringval/vardeclarations with and without an explicitStringtype.docs/multiple-tests/codacy-rules-kotlin/fixtures (patterns.xml,results.xml,src/Program.kt), following the same structure ascodacy-rules-java/codacy-rules-javascript.Test plan
go run ./cmd/docgencompletes with no panic/errors related to the new rule (ran in agolang:1.23-alpine3.21container matching the Dockerfile builder stage)go test $(go list ./... | grep -v /docs/)passesdocker build --build-arg TOOL_VERSION=$(cat .tool_version) -t codacy-opengrep:latest .succeeds end-to-endopengrep v1.26.0binary (same version as the Dockerfile'sOPENGREP_VERSIONarg) directly against the new fixture — all 3 expected findings fire at the expected linesplugins_testjob (validatesdocs/multiple-tests/codacy-rules-kotlin/end-to-end) — pending, will monitor after opening this PR🤖 Generated with Claude Code