diff --git a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql index f3efb578f76a..e02ac4deb8f7 100644 --- a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql +++ b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql @@ -15,7 +15,19 @@ import java import semmle.code.java.security.LogInjectionQuery import LogInjectionFlow::PathGraph +/** + * Holds if `m` is a test method annotated with a JUnit test annotation. + */ +private predicate isTestMethod(Method m) { + m.getAnAnnotation().getType().hasQualifiedName("org.junit.jupiter.api", + ["Test", "ParameterizedTest", "RepeatedTest", "TestFactory"]) + or + m.getAnAnnotation().getType().hasQualifiedName("org.junit", "Test") +} + from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink -where LogInjectionFlow::flowPath(source, sink) +where + LogInjectionFlow::flowPath(source, sink) and + not isTestMethod(sink.getNode().getEnclosingCallable()) select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/test/query-tests/security/CWE-117/LogInjectionTestAnnotation.java b/java/ql/test/query-tests/security/CWE-117/LogInjectionTestAnnotation.java new file mode 100644 index 000000000000..d2772703378d --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-117/LogInjectionTestAnnotation.java @@ -0,0 +1,32 @@ +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.servlet.http.HttpServletRequest; + +/** + * Test that log injection results inside test methods are excluded. + */ +public class LogInjectionTestAnnotation { + private static final Logger logger = LoggerFactory.getLogger(LogInjectionTestAnnotation.class); + + // GOOD: test methods should not be flagged for log injection + @Test + void testLogUserInput(HttpServletRequest request) { + String userInput = request.getParameter("input"); + logger.info("Testing with input: " + userInput); + } + + // GOOD: parameterized test should not be flagged + @ParameterizedTest + void testLogParameterized(HttpServletRequest request) { + String userInput = request.getParameter("input"); + logger.warn("Param test: " + userInput); + } + + // BAD: non-test method should still be flagged + void handleRequest(HttpServletRequest request) { + String userInput = request.getParameter("input"); + logger.info("Processing: " + userInput); // $ Alert + } +}