From eaab7c37f4843b594842ba5d2b5113bc37381493 Mon Sep 17 00:00:00 2001 From: Kiro Agent <244629292+kiro-agent@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:01:44 +0000 Subject: [PATCH] feat: improve java/log-injection query with URLEncoder sanitizer, test exclusion, and DEBUG/TRACE level exclusion - Add java.net.URLEncoder.encode() as a sanitizer since URL encoding replaces line breaks with percent-encoded equivalents - Exclude results in test files to reduce noise from non-production code - Exclude DEBUG/TRACE level logging methods (debug, trace, fine, finer, finest) from sinks since these are typically disabled in production --- .../2025-06-14-log-injection-improvements.md | 5 ++++ .../code/java/security/LogInjection.qll | 26 ++++++++++++++++++- .../src/Security/CWE/CWE-117/LogInjection.ql | 5 +++- .../2025-06-14-log-injection-improvements.md | 6 +++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 java/ql/lib/change-notes/2025-06-14-log-injection-improvements.md create mode 100644 java/ql/src/change-notes/2025-06-14-log-injection-improvements.md diff --git a/java/ql/lib/change-notes/2025-06-14-log-injection-improvements.md b/java/ql/lib/change-notes/2025-06-14-log-injection-improvements.md new file mode 100644 index 000000000000..1db28332043f --- /dev/null +++ b/java/ql/lib/change-notes/2025-06-14-log-injection-improvements.md @@ -0,0 +1,5 @@ +--- +category: majorAnalysis +--- +* The `java/log-injection` query now excludes calls to DEBUG and TRACE level logging methods (`debug`, `trace`, `fine`, `finer`, `finest`) from its sinks, since these log levels are typically disabled in production. +* Added `java.net.URLEncoder.encode()` as a sanitizer for the `java/log-injection` query, since URL encoding replaces line breaks with percent-encoded equivalents. diff --git a/java/ql/lib/semmle/code/java/security/LogInjection.qll b/java/ql/lib/semmle/code/java/security/LogInjection.qll index b585c249d1eb..8df9477059c2 100644 --- a/java/ql/lib/semmle/code/java/security/LogInjection.qll +++ b/java/ql/lib/semmle/code/java/security/LogInjection.qll @@ -30,12 +30,36 @@ class LogInjectionAdditionalTaintStep extends Unit { } private class DefaultLogInjectionSink extends LogInjectionSink { - DefaultLogInjectionSink() { sinkNode(this, "log-injection") } + DefaultLogInjectionSink() { + sinkNode(this, "log-injection") and + not exists(MethodCall mc | + this.asExpr() = mc.getAnArgument() and + mc.getMethod().getName() in [ + "debug", "trace", // SLF4J, Log4j, Commons Logging, JBoss Logging + "fine", "finer", "finest" // java.util.logging + ] + ) + } } private class DefaultLogInjectionSanitizer extends LogInjectionSanitizer instanceof SimpleTypeSanitizer { } +/** + * A call to `java.net.URLEncoder.encode(...)` is considered a sanitizer for log injection, + * since URL encoding replaces line breaks and other special characters with percent-encoded + * equivalents that cannot be used to forge log entries. + */ +private class UrlEncoderSanitizer extends LogInjectionSanitizer { + UrlEncoderSanitizer() { + exists(MethodCall mc | + mc.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLEncoder") and + mc.getMethod().hasName("encode") and + this.asExpr() = mc + ) + } +} + private class LineBreaksLogInjectionSanitizer extends LogInjectionSanitizer { LineBreaksLogInjectionSanitizer() { logInjectionSanitizer(this.asExpr()) diff --git a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql index f3efb578f76a..7974b1018943 100644 --- a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql +++ b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql @@ -13,9 +13,12 @@ import java import semmle.code.java.security.LogInjectionQuery +import semmle.code.java.dataflow.internal.ModelExclusions import LogInjectionFlow::PathGraph from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink -where LogInjectionFlow::flowPath(source, sink) +where + LogInjectionFlow::flowPath(source, sink) and + not isInTestFile(sink.getNode().getLocation().getFile()) select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/change-notes/2025-06-14-log-injection-improvements.md b/java/ql/src/change-notes/2025-06-14-log-injection-improvements.md new file mode 100644 index 000000000000..223bd64cc2ee --- /dev/null +++ b/java/ql/src/change-notes/2025-06-14-log-injection-improvements.md @@ -0,0 +1,6 @@ +--- +category: majorAnalysis +--- +* The `java/log-injection` query now excludes calls to DEBUG and TRACE level logging methods (`debug`, `trace`, `fine`, `finer`, `finest`) from its results, since these log levels are typically disabled in production and do not present a realistic log injection attack surface. +* The `java/log-injection` query now recognizes `java.net.URLEncoder.encode()` as a sanitizer, since URL encoding replaces line breaks and other special characters with percent-encoded equivalents. +* The `java/log-injection` query now excludes results in test files to reduce noise from non-production code.