From 65ab967745b97df602c6784cb9e4c78a562ab51c Mon Sep 17 00:00:00 2001 From: rayair250-droid Date: Fri, 24 Jul 2026 18:01:18 +0200 Subject: [PATCH] fix(java/jdo-sqli): detect String.formatted() as a tainted query source The jdo-sqli rule flagged String.format(...) and string concatenation passed to JDO query APIs (setFilter/setGrouping/newQuery), but missed the Java 15+ instance method "...".formatted(input), which produces the same attacker-controlled query string. Add matching patterns (both as a pattern-inside source and as a direct argument) mirroring the existing String.format handling, plus test cases. Validated with semgrep --test. Closes #3812. --- java/lang/security/audit/sqli/jdo-sqli.java | 11 +++++++++++ java/lang/security/audit/sqli/jdo-sqli.yaml | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/java/lang/security/audit/sqli/jdo-sqli.java b/java/lang/security/audit/sqli/jdo-sqli.java index 8b177c9b4b..972fd8a76a 100644 --- a/java/lang/security/audit/sqli/jdo-sqli.java +++ b/java/lang/security/audit/sqli/jdo-sqli.java @@ -23,6 +23,13 @@ public void testJdoUnsafeFilter(String filterValue) { q.setFilter("id == "+filterValue); } + public void testJdoUnsafeFilterFormatted(String filterValue) { + PersistenceManager pm = getPM(); + Query q = pm.newQuery(UserEntity.class); + // ruleid: jdo-sqli + q.setFilter("id == %s".formatted(filterValue)); + } + public void testJdoSafeFilter(String filterValue) { PersistenceManager pm = getPM(); Query q = pm.newQuery(UserEntity.class); @@ -87,10 +94,14 @@ public void testJdoQueriesAdditionalMethodSig(String input) { PersistenceManager pm = getPM(); // ruleid: jdo-sqli pm.newQuery(UserEntity.class,new ArrayList(),"id == "+ input); + // ruleid: jdo-sqli + pm.newQuery(UserEntity.class,new ArrayList(),"id == %s".formatted(input)); // ok: jdo-sqli pm.newQuery(UserEntity.class,new ArrayList(),"id == 1"); // ruleid: jdo-sqli pm.newQuery(UserEntity.class,"id == "+ input); + // ruleid: jdo-sqli + pm.newQuery(UserEntity.class,"id == %s".formatted(input)); // ok: jdo-sqli pm.newQuery(UserEntity.class,"id == 1"); // ruleid: jdo-sqli diff --git a/java/lang/security/audit/sqli/jdo-sqli.yaml b/java/lang/security/audit/sqli/jdo-sqli.yaml index 481648a275..dd441dfa50 100644 --- a/java/lang/security/audit/sqli/jdo-sqli.yaml +++ b/java/lang/security/audit/sqli/jdo-sqli.yaml @@ -11,6 +11,9 @@ rules: - pattern-inside: | String $SQL = String.format(...); ... + - pattern-inside: | + String $SQL = "...".formatted(...); + ... - pattern-inside: | $TYPE $FUNC(...,String $SQL,...) { ... @@ -21,6 +24,8 @@ rules: - pattern: $Q.$METHOD($SQL,...) - pattern: | $Q.$METHOD(String.format(...),...); + - pattern: | + $Q.$METHOD("...".formatted(...),...); - pattern: | $Q.$METHOD($X + $Y,...); - pattern-either: @@ -46,6 +51,9 @@ rules: - pattern-inside: | String $SQL = String.format(...); ... + - pattern-inside: | + String $SQL = "...".formatted(...); + ... - pattern-inside: | $VAL $FUNC(...,String $SQL,...) { ... @@ -56,6 +64,8 @@ rules: - pattern: $PM.newQuery(...,$SQL,...) - pattern: | $PM.newQuery(...,String.format(...),...); + - pattern: | + $PM.newQuery(...,"...".formatted(...),...); - pattern: | $PM.newQuery(...,$X + $Y,...); - pattern-either: