diff --git a/core-codemods/src/main/java/io/codemodder/codemods/DefaultCodemods.java b/core-codemods/src/main/java/io/codemodder/codemods/DefaultCodemods.java index 1740b38a1..e2d6039b4 100644 --- a/core-codemods/src/main/java/io/codemodder/codemods/DefaultCodemods.java +++ b/core-codemods/src/main/java/io/codemodder/codemods/DefaultCodemods.java @@ -74,6 +74,7 @@ public static List> asList() { SemgrepOverlyPermissiveFilePermissionsCodemod.class, SimplifyRestControllerAnnotationsCodemod.class, SubstituteReplaceAllCodemod.class, + SonarJNDIInjectionCodemod.class, SonarRemoveUnthrowableExceptionCodemod.class, SonarXXECodemod.class, SonarSQLInjectionCodemod.class, diff --git a/core-codemods/src/main/java/io/codemodder/codemods/SonarJNDIInjectionCodemod.java b/core-codemods/src/main/java/io/codemodder/codemods/SonarJNDIInjectionCodemod.java new file mode 100644 index 000000000..be2a52aef --- /dev/null +++ b/core-codemods/src/main/java/io/codemodder/codemods/SonarJNDIInjectionCodemod.java @@ -0,0 +1,58 @@ +package io.codemodder.codemods; + +import com.github.javaparser.ast.CompilationUnit; +import io.codemodder.*; +import io.codemodder.codetf.DetectorRule; +import io.codemodder.providers.sonar.ProvidedSonarScan; +import io.codemodder.providers.sonar.RuleIssue; +import io.codemodder.providers.sonar.SonarRemediatingJavaParserChanger; +import io.codemodder.remediation.GenericRemediationMetadata; +import io.codemodder.remediation.jndiinjection.JNDIInjectionRemediator; +import io.codemodder.sonar.model.Issue; +import io.codemodder.sonar.model.SonarFinding; +import java.util.List; +import java.util.Objects; +import javax.inject.Inject; + +/** This codemod knows how to fix JNDI vulnerabilities found by sonar. */ +@Codemod( + id = "sonar:java/jndi-injection-s2078", + reviewGuidance = ReviewGuidance.MERGE_AFTER_CURSORY_REVIEW, + executionPriority = CodemodExecutionPriority.HIGH, + importance = Importance.HIGH) +public final class SonarJNDIInjectionCodemod extends SonarRemediatingJavaParserChanger { + + private final JNDIInjectionRemediator remediator; + private final RuleIssue issues; + + @Inject + public SonarJNDIInjectionCodemod( + @ProvidedSonarScan(ruleId = "javasecurity:S2078") final RuleIssue issues) { + super(GenericRemediationMetadata.JNDI.reporter(), issues); + this.issues = Objects.requireNonNull(issues); + this.remediator = JNDIInjectionRemediator.DEFAULT; + } + + @Override + public DetectorRule detectorRule() { + return new DetectorRule( + "javasecurity:S2078", + "LDAP queries should not be vulnerable to injection attacks", + "https://rules.sonarsource.com/java/RSPEC-2078/"); + } + + @Override + public CodemodFileScanningResult visit( + final CodemodInvocationContext context, final CompilationUnit cu) { + List issuesForFile = issues.getResultsByPath(context.path()); + return remediator.remediateAll( + cu, + context.path().toString(), + detectorRule(), + issuesForFile, + SonarFinding::getKey, + i -> i.getTextRange() != null ? i.getTextRange().getStartLine() : i.getLine(), + i -> i.getTextRange() != null ? i.getTextRange().getEndLine() : null, + i -> i.getTextRange() != null ? i.getTextRange().getStartOffset() : null); + } +} diff --git a/core-codemods/src/test/java/io/codemodder/codemods/SonarJNDIInjectionCodemodTest.java b/core-codemods/src/test/java/io/codemodder/codemods/SonarJNDIInjectionCodemodTest.java new file mode 100644 index 000000000..c63022268 --- /dev/null +++ b/core-codemods/src/test/java/io/codemodder/codemods/SonarJNDIInjectionCodemodTest.java @@ -0,0 +1,36 @@ +package io.codemodder.codemods; + +import io.codemodder.DependencyGAV; +import io.codemodder.testutils.CodemodTestMixin; +import io.codemodder.testutils.Metadata; +import org.junit.jupiter.api.Nested; + +final class SonarJNDIInjectionCodemodTest { + + @Nested + @Metadata( + codemodType = SonarJNDIInjectionCodemod.class, + testResourceDir = "sonar-jndi-injection-s2078/normal", + renameTestFile = "src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + expectingFixesAtLines = {15}, + dependencies = DependencyGAV.JAVA_SECURITY_TOOLKIT_GAV) + final class ExpectedSinkInLocationTest implements CodemodTestMixin {} + + @Nested + @Metadata( + codemodType = SonarJNDIInjectionCodemod.class, + testResourceDir = "sonar-jndi-injection-s2078/misleading-location", + renameTestFile = "src/main/java/com/mycompany/app/jndi/FindResource.java", + expectingFixesAtLines = {18}, + dependencies = DependencyGAV.JAVA_SECURITY_TOOLKIT_GAV) + final class MisleadingSinkInLocationTest implements CodemodTestMixin {} + + /** Just confirms that when there are no changes for a given file, nothing errors. */ + @Nested + @Metadata( + codemodType = SonarJNDIInjectionCodemod.class, + testResourceDir = "sonar-jndi-injection-s2078/unrelated-file", + renameTestFile = "src/main/java/com/acme/jndi/UnrelatedFile.java", + dependencies = {}) + final class UnrelatedFileTest implements CodemodTestMixin {} +} diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/FindResource.java.after b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/FindResource.java.after new file mode 100644 index 000000000..a08498b6d --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/FindResource.java.after @@ -0,0 +1,21 @@ +package com.acme.jndi; + +import io.github.pixee.security.JNDI; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +/** JNDI resource finder. */ +public final class FindResource { + + private FindResource() { } + + public static String findResource(final String resource) throws NamingException { + return lookupResource(resource); + } + + private static String lookupResource(final String resource) throws NamingException { + Context ctx = new InitialContext(); + return String.valueOf(JNDI.limitedContext(ctx).lookup(resource)); + } +} diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/FindResource.java.before b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/FindResource.java.before new file mode 100644 index 000000000..e8f288b0b --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/FindResource.java.before @@ -0,0 +1,20 @@ +package com.acme.jndi; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +/** JNDI resource finder. */ +public final class FindResource { + + private FindResource() { } + + public static String findResource(final String resource) throws NamingException { + return lookupResource(resource); + } + + private static String lookupResource(final String resource) throws NamingException { + Context ctx = new InitialContext(); + return String.valueOf(ctx.lookup(resource)); + } +} \ No newline at end of file diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/sonar-issues.json b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/sonar-issues.json new file mode 100644 index 000000000..f16b8550a --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/misleading-location/sonar-issues.json @@ -0,0 +1,552 @@ +{ + "total": 6, + "p": 1, + "ps": 500, + "paging": { + "pageIndex": 1, + "pageSize": 500, + "total": 6 + }, + "effortTotal": 110, + "debtTotal": 110, + "issues": [ + { + "key": "AZJM52DeO14kODUdUlL7", + "rule": "javasecurity:S2078", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "project": "andrecsilva_bad-code-java", + "line": 18, + "hash": "04ad6717d681874235a5c5f3f6ce5f2e", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 41, + "endOffset": 62 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 26, + "endOffset": 40 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 15, + "endOffset": 39 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 38, + "endOffset": 59 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 25, + "endOffset": 37 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 21, + "endLine": 21, + "startOffset": 15, + "endOffset": 50 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 20, + "endLine": 20, + "startOffset": 77, + "endOffset": 85 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 20, + "endLine": 20, + "startOffset": 40, + "endOffset": 63 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + }, + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 41, + "endOffset": 62 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 26, + "endOffset": 40 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 15, + "endOffset": 39 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 38, + "endOffset": 59 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 25, + "endOffset": 37 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 26, + "endLine": 26, + "startOffset": 15, + "endOffset": 50 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 25, + "endLine": 25, + "startOffset": 80, + "endOffset": 88 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 25, + "endLine": 25, + "startOffset": 43, + "endOffset": 66 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not construct this LDAP name or filter from user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cert", + "cwe" + ], + "creationDate": "2024-10-02T13:04:36+0200", + "updateDate": "2024-10-02T13:04:36+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZJM52D0O14kODUdUlL8", + "rule": "javasecurity:S2078", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "project": "andrecsilva_bad-code-java", + "line": 15, + "hash": "71889032360e7572c8d7400ea6f029a5", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 21, + "endOffset": 41 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 21, + "endOffset": 41 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 70, + "endOffset": 78 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 33, + "endOffset": 56 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not construct this LDAP name or filter from user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cert", + "cwe" + ], + "creationDate": "2024-10-02T13:04:36+0200", + "updateDate": "2024-10-02T13:04:36+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLU0LHhd1vFwOk7J", + "rule": "java:S1220", + "severity": "MINOR", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "project": "andrecsilva_bad-code-java", + "flows": [], + "status": "OPEN", + "message": "Move this file to a named package.", + "effort": "10min", + "debt": "10min", + "tags": [ + "convention" + ], + "creationDate": "2024-09-27T13:14:20+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "MODULAR", + "cleanCodeAttributeCategory": "ADAPTABLE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "LOW" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLU0LHhd1vFwOk7K", + "rule": "javasecurity:S5146", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "project": "andrecsilva_bad-code-java", + "line": 8, + "hash": "b7a8781b629c5d632230d13cbd8ba8f5", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 3, + "endOffset": 30 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 3, + "endOffset": 30 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 7, + "endLine": 7, + "startOffset": 3, + "endOffset": 45 + }, + "msg": "A malicious value can be assigned to variable ‘location’" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 7, + "endLine": 7, + "startOffset": 21, + "endOffset": 44 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not perform redirects based on user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cwe" + ], + "creationDate": "2024-09-27T13:14:20+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLVmLHhd1vFwOk7M", + "rule": "xml:S1134", + "severity": "MAJOR", + "component": "andrecsilva_bad-code-java:pom.xml", + "project": "andrecsilva_bad-code-java", + "line": 12, + "hash": "57a1d2bace8541f648f11f4019ae460c", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 2, + "endOffset": 51 + }, + "flows": [], + "status": "OPEN", + "message": "Take the required action to fix the issue indicated by this \"FIXME\" comment.", + "effort": "0min", + "debt": "0min", + "tags": [ + "cwe" + ], + "creationDate": "2024-09-27T13:09:45+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "MEDIUM" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLVfLHhd1vFwOk7L", + "rule": "java:S106", + "severity": "MAJOR", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/App.java", + "project": "andrecsilva_bad-code-java", + "line": 11, + "hash": "a6bb3cf9230562f25bf42bea1ce34544", + "textRange": { + "startLine": 11, + "endLine": 11, + "startOffset": 8, + "endOffset": 18 + }, + "flows": [], + "status": "OPEN", + "message": "Replace this use of System.out by a logger.", + "effort": "10min", + "debt": "10min", + "tags": [ + "bad-practice", + "cert" + ], + "creationDate": "2024-09-27T13:09:45+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "MODULAR", + "cleanCodeAttributeCategory": "ADAPTABLE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "MEDIUM" + } + ], + "issueStatus": "OPEN" + } + ], + "components": [ + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/App.java", + "uuid": "AZIzNLJLLHhd1vFwOk7D", + "enabled": true, + "qualifier": "FIL", + "name": "App.java", + "longName": "src/main/java/com/mycompany/app/App.java", + "path": "src/main/java/com/mycompany/app/App.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "uuid": "AZIzNLJLLHhd1vFwOk7C", + "enabled": true, + "qualifier": "FIL", + "name": "RedirectionForgery.java", + "longName": "src/main/java/com/mycompany/app/RedirectionForgery.java", + "path": "src/main/java/com/mycompany/app/RedirectionForgery.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "uuid": "AZJM3WlnzAV4pOA1RILi", + "enabled": true, + "qualifier": "FIL", + "name": "JNDIVuln.java", + "longName": "src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "path": "src/main/java/com/mycompany/app/jndi/JNDIVuln.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "uuid": "AZJM3WlnzAV4pOA1RILh", + "enabled": true, + "qualifier": "FIL", + "name": "FindResource.java", + "longName": "src/main/java/com/mycompany/app/jndi/FindResource.java", + "path": "src/main/java/com/mycompany/app/jndi/FindResource.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:pom.xml", + "uuid": "AZIzNLJLLHhd1vFwOk7I", + "enabled": true, + "qualifier": "FIL", + "name": "pom.xml", + "longName": "pom.xml", + "path": "pom.xml" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java", + "uuid": "AZIzNG7PBzBgaIxETvJi", + "enabled": true, + "qualifier": "TRK", + "name": "bad-code-java", + "longName": "bad-code-java" + } + ], + "organizations": [ + { + "key": "andrecsilva", + "name": "André C. Silva" + } + ], + "facets": [] +} diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/JNDIVuln.java.after b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/JNDIVuln.java.after new file mode 100644 index 000000000..587d253e7 --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/JNDIVuln.java.after @@ -0,0 +1,29 @@ +package com.mycompany.app.jndi; + +import io.github.pixee.security.JNDI; +import jakarta.ws.rs.*; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +@Path("/unsafe-jndi-lookup") +public class JNDIVuln { + + @GET + public String lookupResource(@QueryParam("resource") final String resource) throws NamingException { + Context ctx = new InitialContext(); + Object obj = JNDI.limitedContext(ctx).lookup(resource); + return String.valueOf(obj); + } + + @POST + public String lookupAnotherResource(@QueryParam("resource") final String resource) throws NamingException { + return FindResource.findResource(resource); + } + + @PUT + public String lookupYetAnotherResource(@QueryParam("resource") final String resource) throws NamingException { + return FindResource.findResource(resource); + } +} diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/JNDIVuln.java.before b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/JNDIVuln.java.before new file mode 100644 index 000000000..941a0ce66 --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/JNDIVuln.java.before @@ -0,0 +1,28 @@ +package com.mycompany.app.jndi; + +import jakarta.ws.rs.*; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +@Path("/unsafe-jndi-lookup") +public class JNDIVuln { + + @GET + public String lookupResource(@QueryParam("resource") final String resource) throws NamingException { + Context ctx = new InitialContext(); + Object obj = ctx.lookup(resource); + return String.valueOf(obj); + } + + @POST + public String lookupAnotherResource(@QueryParam("resource") final String resource) throws NamingException { + return FindResource.findResource(resource); + } + + @PUT + public String lookupYetAnotherResource(@QueryParam("resource") final String resource) throws NamingException { + return FindResource.findResource(resource); + } +} diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/sonar-issues.json b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/sonar-issues.json new file mode 100644 index 000000000..f16b8550a --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/normal/sonar-issues.json @@ -0,0 +1,552 @@ +{ + "total": 6, + "p": 1, + "ps": 500, + "paging": { + "pageIndex": 1, + "pageSize": 500, + "total": 6 + }, + "effortTotal": 110, + "debtTotal": 110, + "issues": [ + { + "key": "AZJM52DeO14kODUdUlL7", + "rule": "javasecurity:S2078", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "project": "andrecsilva_bad-code-java", + "line": 18, + "hash": "04ad6717d681874235a5c5f3f6ce5f2e", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 41, + "endOffset": 62 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 26, + "endOffset": 40 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 15, + "endOffset": 39 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 38, + "endOffset": 59 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 25, + "endOffset": 37 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 21, + "endLine": 21, + "startOffset": 15, + "endOffset": 50 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 20, + "endLine": 20, + "startOffset": 77, + "endOffset": 85 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 20, + "endLine": 20, + "startOffset": 40, + "endOffset": 63 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + }, + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 41, + "endOffset": 62 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 26, + "endOffset": 40 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 15, + "endOffset": 39 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 38, + "endOffset": 59 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 25, + "endOffset": 37 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 26, + "endLine": 26, + "startOffset": 15, + "endOffset": 50 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 25, + "endLine": 25, + "startOffset": 80, + "endOffset": 88 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 25, + "endLine": 25, + "startOffset": 43, + "endOffset": 66 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not construct this LDAP name or filter from user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cert", + "cwe" + ], + "creationDate": "2024-10-02T13:04:36+0200", + "updateDate": "2024-10-02T13:04:36+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZJM52D0O14kODUdUlL8", + "rule": "javasecurity:S2078", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "project": "andrecsilva_bad-code-java", + "line": 15, + "hash": "71889032360e7572c8d7400ea6f029a5", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 21, + "endOffset": 41 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 21, + "endOffset": 41 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 70, + "endOffset": 78 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 33, + "endOffset": 56 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not construct this LDAP name or filter from user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cert", + "cwe" + ], + "creationDate": "2024-10-02T13:04:36+0200", + "updateDate": "2024-10-02T13:04:36+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLU0LHhd1vFwOk7J", + "rule": "java:S1220", + "severity": "MINOR", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "project": "andrecsilva_bad-code-java", + "flows": [], + "status": "OPEN", + "message": "Move this file to a named package.", + "effort": "10min", + "debt": "10min", + "tags": [ + "convention" + ], + "creationDate": "2024-09-27T13:14:20+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "MODULAR", + "cleanCodeAttributeCategory": "ADAPTABLE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "LOW" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLU0LHhd1vFwOk7K", + "rule": "javasecurity:S5146", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "project": "andrecsilva_bad-code-java", + "line": 8, + "hash": "b7a8781b629c5d632230d13cbd8ba8f5", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 3, + "endOffset": 30 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 3, + "endOffset": 30 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 7, + "endLine": 7, + "startOffset": 3, + "endOffset": 45 + }, + "msg": "A malicious value can be assigned to variable ‘location’" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 7, + "endLine": 7, + "startOffset": 21, + "endOffset": 44 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not perform redirects based on user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cwe" + ], + "creationDate": "2024-09-27T13:14:20+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLVmLHhd1vFwOk7M", + "rule": "xml:S1134", + "severity": "MAJOR", + "component": "andrecsilva_bad-code-java:pom.xml", + "project": "andrecsilva_bad-code-java", + "line": 12, + "hash": "57a1d2bace8541f648f11f4019ae460c", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 2, + "endOffset": 51 + }, + "flows": [], + "status": "OPEN", + "message": "Take the required action to fix the issue indicated by this \"FIXME\" comment.", + "effort": "0min", + "debt": "0min", + "tags": [ + "cwe" + ], + "creationDate": "2024-09-27T13:09:45+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "MEDIUM" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLVfLHhd1vFwOk7L", + "rule": "java:S106", + "severity": "MAJOR", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/App.java", + "project": "andrecsilva_bad-code-java", + "line": 11, + "hash": "a6bb3cf9230562f25bf42bea1ce34544", + "textRange": { + "startLine": 11, + "endLine": 11, + "startOffset": 8, + "endOffset": 18 + }, + "flows": [], + "status": "OPEN", + "message": "Replace this use of System.out by a logger.", + "effort": "10min", + "debt": "10min", + "tags": [ + "bad-practice", + "cert" + ], + "creationDate": "2024-09-27T13:09:45+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "MODULAR", + "cleanCodeAttributeCategory": "ADAPTABLE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "MEDIUM" + } + ], + "issueStatus": "OPEN" + } + ], + "components": [ + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/App.java", + "uuid": "AZIzNLJLLHhd1vFwOk7D", + "enabled": true, + "qualifier": "FIL", + "name": "App.java", + "longName": "src/main/java/com/mycompany/app/App.java", + "path": "src/main/java/com/mycompany/app/App.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "uuid": "AZIzNLJLLHhd1vFwOk7C", + "enabled": true, + "qualifier": "FIL", + "name": "RedirectionForgery.java", + "longName": "src/main/java/com/mycompany/app/RedirectionForgery.java", + "path": "src/main/java/com/mycompany/app/RedirectionForgery.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "uuid": "AZJM3WlnzAV4pOA1RILi", + "enabled": true, + "qualifier": "FIL", + "name": "JNDIVuln.java", + "longName": "src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "path": "src/main/java/com/mycompany/app/jndi/JNDIVuln.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "uuid": "AZJM3WlnzAV4pOA1RILh", + "enabled": true, + "qualifier": "FIL", + "name": "FindResource.java", + "longName": "src/main/java/com/mycompany/app/jndi/FindResource.java", + "path": "src/main/java/com/mycompany/app/jndi/FindResource.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:pom.xml", + "uuid": "AZIzNLJLLHhd1vFwOk7I", + "enabled": true, + "qualifier": "FIL", + "name": "pom.xml", + "longName": "pom.xml", + "path": "pom.xml" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java", + "uuid": "AZIzNG7PBzBgaIxETvJi", + "enabled": true, + "qualifier": "TRK", + "name": "bad-code-java", + "longName": "bad-code-java" + } + ], + "organizations": [ + { + "key": "andrecsilva", + "name": "André C. Silva" + } + ], + "facets": [] +} diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/unrelated-file/UnrelatedFile.java.before b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/unrelated-file/UnrelatedFile.java.before new file mode 100644 index 000000000..a4f4c5f76 --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/unrelated-file/UnrelatedFile.java.before @@ -0,0 +1,8 @@ +package com.acme; + +// this class has no findings, but it shouldn't cause an error +class UnrelatedFile { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +} \ No newline at end of file diff --git a/core-codemods/src/test/resources/sonar-jndi-injection-s2078/unrelated-file/sonar-issues.json b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/unrelated-file/sonar-issues.json new file mode 100644 index 000000000..f16b8550a --- /dev/null +++ b/core-codemods/src/test/resources/sonar-jndi-injection-s2078/unrelated-file/sonar-issues.json @@ -0,0 +1,552 @@ +{ + "total": 6, + "p": 1, + "ps": 500, + "paging": { + "pageIndex": 1, + "pageSize": 500, + "total": 6 + }, + "effortTotal": 110, + "debtTotal": 110, + "issues": [ + { + "key": "AZJM52DeO14kODUdUlL7", + "rule": "javasecurity:S2078", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "project": "andrecsilva_bad-code-java", + "line": 18, + "hash": "04ad6717d681874235a5c5f3f6ce5f2e", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 41, + "endOffset": 62 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 26, + "endOffset": 40 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 15, + "endOffset": 39 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 38, + "endOffset": 59 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 25, + "endOffset": 37 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 21, + "endLine": 21, + "startOffset": 15, + "endOffset": 50 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 20, + "endLine": 20, + "startOffset": 77, + "endOffset": 85 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 20, + "endLine": 20, + "startOffset": 40, + "endOffset": 63 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + }, + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 18, + "endLine": 18, + "startOffset": 30, + "endOffset": 50 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 41, + "endOffset": 62 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 16, + "endLine": 16, + "startOffset": 26, + "endOffset": 40 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 15, + "endOffset": 39 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 38, + "endOffset": 59 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 25, + "endOffset": 37 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 26, + "endLine": 26, + "startOffset": 15, + "endOffset": 50 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 25, + "endLine": 25, + "startOffset": 80, + "endOffset": 88 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 25, + "endLine": 25, + "startOffset": 43, + "endOffset": 66 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not construct this LDAP name or filter from user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cert", + "cwe" + ], + "creationDate": "2024-10-02T13:04:36+0200", + "updateDate": "2024-10-02T13:04:36+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZJM52D0O14kODUdUlL8", + "rule": "javasecurity:S2078", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "project": "andrecsilva_bad-code-java", + "line": 15, + "hash": "71889032360e7572c8d7400ea6f029a5", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 21, + "endOffset": 41 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 21, + "endOffset": 41 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 70, + "endOffset": 78 + }, + "msg": "This instruction can propagate malicious content" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "textRange": { + "startLine": 13, + "endLine": 13, + "startOffset": 33, + "endOffset": 56 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not construct this LDAP name or filter from user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cert", + "cwe" + ], + "creationDate": "2024-10-02T13:04:36+0200", + "updateDate": "2024-10-02T13:04:36+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLU0LHhd1vFwOk7J", + "rule": "java:S1220", + "severity": "MINOR", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "project": "andrecsilva_bad-code-java", + "flows": [], + "status": "OPEN", + "message": "Move this file to a named package.", + "effort": "10min", + "debt": "10min", + "tags": [ + "convention" + ], + "creationDate": "2024-09-27T13:14:20+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "MODULAR", + "cleanCodeAttributeCategory": "ADAPTABLE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "LOW" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLU0LHhd1vFwOk7K", + "rule": "javasecurity:S5146", + "severity": "BLOCKER", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "project": "andrecsilva_bad-code-java", + "line": 8, + "hash": "b7a8781b629c5d632230d13cbd8ba8f5", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 3, + "endOffset": 30 + }, + "flows": [ + { + "locations": [ + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 3, + "endOffset": 30 + }, + "msg": "Sink: this invocation is not safe; a malicious value can be used as argument" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 7, + "endLine": 7, + "startOffset": 3, + "endOffset": 45 + }, + "msg": "A malicious value can be assigned to variable ‘location’" + }, + { + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "textRange": { + "startLine": 7, + "endLine": 7, + "startOffset": 21, + "endOffset": 44 + }, + "msg": "Source: a user can craft an HTTP request with malicious content" + } + ] + } + ], + "status": "OPEN", + "message": "Change this code to not perform redirects based on user-controlled data.", + "effort": "30min", + "debt": "30min", + "tags": [ + "cwe" + ], + "creationDate": "2024-09-27T13:14:20+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "VULNERABILITY", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "SECURITY", + "severity": "HIGH" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLVmLHhd1vFwOk7M", + "rule": "xml:S1134", + "severity": "MAJOR", + "component": "andrecsilva_bad-code-java:pom.xml", + "project": "andrecsilva_bad-code-java", + "line": 12, + "hash": "57a1d2bace8541f648f11f4019ae460c", + "textRange": { + "startLine": 12, + "endLine": 12, + "startOffset": 2, + "endOffset": 51 + }, + "flows": [], + "status": "OPEN", + "message": "Take the required action to fix the issue indicated by this \"FIXME\" comment.", + "effort": "0min", + "debt": "0min", + "tags": [ + "cwe" + ], + "creationDate": "2024-09-27T13:09:45+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "COMPLETE", + "cleanCodeAttributeCategory": "INTENTIONAL", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "MEDIUM" + } + ], + "issueStatus": "OPEN" + }, + { + "key": "AZIzNLVfLHhd1vFwOk7L", + "rule": "java:S106", + "severity": "MAJOR", + "component": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/App.java", + "project": "andrecsilva_bad-code-java", + "line": 11, + "hash": "a6bb3cf9230562f25bf42bea1ce34544", + "textRange": { + "startLine": 11, + "endLine": 11, + "startOffset": 8, + "endOffset": 18 + }, + "flows": [], + "status": "OPEN", + "message": "Replace this use of System.out by a logger.", + "effort": "10min", + "debt": "10min", + "tags": [ + "bad-practice", + "cert" + ], + "creationDate": "2024-09-27T13:09:45+0200", + "updateDate": "2024-09-27T13:18:51+0200", + "type": "CODE_SMELL", + "organization": "andrecsilva", + "cleanCodeAttribute": "MODULAR", + "cleanCodeAttributeCategory": "ADAPTABLE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "severity": "MEDIUM" + } + ], + "issueStatus": "OPEN" + } + ], + "components": [ + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/App.java", + "uuid": "AZIzNLJLLHhd1vFwOk7D", + "enabled": true, + "qualifier": "FIL", + "name": "App.java", + "longName": "src/main/java/com/mycompany/app/App.java", + "path": "src/main/java/com/mycompany/app/App.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/RedirectionForgery.java", + "uuid": "AZIzNLJLLHhd1vFwOk7C", + "enabled": true, + "qualifier": "FIL", + "name": "RedirectionForgery.java", + "longName": "src/main/java/com/mycompany/app/RedirectionForgery.java", + "path": "src/main/java/com/mycompany/app/RedirectionForgery.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "uuid": "AZJM3WlnzAV4pOA1RILi", + "enabled": true, + "qualifier": "FIL", + "name": "JNDIVuln.java", + "longName": "src/main/java/com/mycompany/app/jndi/JNDIVuln.java", + "path": "src/main/java/com/mycompany/app/jndi/JNDIVuln.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:src/main/java/com/mycompany/app/jndi/FindResource.java", + "uuid": "AZJM3WlnzAV4pOA1RILh", + "enabled": true, + "qualifier": "FIL", + "name": "FindResource.java", + "longName": "src/main/java/com/mycompany/app/jndi/FindResource.java", + "path": "src/main/java/com/mycompany/app/jndi/FindResource.java" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java:pom.xml", + "uuid": "AZIzNLJLLHhd1vFwOk7I", + "enabled": true, + "qualifier": "FIL", + "name": "pom.xml", + "longName": "pom.xml", + "path": "pom.xml" + }, + { + "organization": "andrecsilva", + "key": "andrecsilva_bad-code-java", + "uuid": "AZIzNG7PBzBgaIxETvJi", + "enabled": true, + "qualifier": "TRK", + "name": "bad-code-java", + "longName": "bad-code-java" + } + ], + "organizations": [ + { + "key": "andrecsilva", + "name": "André C. Silva" + } + ], + "facets": [] +} diff --git a/plugins/codemodder-plugin-sonar/src/main/java/io/codemodder/providers/sonar/DefaultRuleFinding.java b/plugins/codemodder-plugin-sonar/src/main/java/io/codemodder/providers/sonar/DefaultRuleFinding.java index cd219e586..39496b470 100644 --- a/plugins/codemodder-plugin-sonar/src/main/java/io/codemodder/providers/sonar/DefaultRuleFinding.java +++ b/plugins/codemodder-plugin-sonar/src/main/java/io/codemodder/providers/sonar/DefaultRuleFinding.java @@ -25,7 +25,7 @@ abstract class DefaultRuleFinding implements RuleFinding @Override public List getResultsByPath(final Path path) { - return findings.get(path.toString()); + return findings.getOrDefault(path.toString(), List.of()); } @Override