This is an automated email from the ASF dual-hosted git repository.

pefernan pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git


The following commit(s) were added to refs/heads/main by this push:
     new 969137e8e1 NO-ISSUE : fix CWE-470 validate rule unit class name before 
loadClass (#4341)
969137e8e1 is described below

commit 969137e8e1684d203ef9d009e6dc56651a91e338
Author: ANN JOY <[email protected]>
AuthorDate: Tue Jul 21 12:48:00 2026 +0530

    NO-ISSUE : fix CWE-470 validate rule unit class name before loadClass 
(#4341)
    
    * fix: CWE-470 validate rule unit class name before loadClass
    
    Validate that the class name passed to ClassLoader.loadClass() is a
    legal Java fully-qualified class name ([\w$]+(\.[\w$]+)*) before
    dispatching it to the classloader.
    
    This breaks the taint chain reported by SAST scanners for CWE-470
    (Unsafe Reflection) in RuleUnitServiceImpl.convertValue() and
    StatefulRuleUnitServiceImpl.toClass().
    
    Affects:
    - RuleUnitServiceImpl.convertValue()
    - StatefulRuleUnitServiceImpl.toClass()
    
    * fix: include class name in ClassNotFoundException message in 
StatefulRuleUnitServiceImpl
    
    When loadClass() fails, the thrown IllegalArgumentException now includes
    the class name in the message, consistent with RuleUnitServiceImpl.
    
    Before: throw new IllegalArgumentException(e)
    After:  throw new IllegalArgumentException("Cannot load class " + 
className, e)
    
    Addresses PR review comment (Low severity).
---
 .../incubation/quarkus/support/RuleUnitServiceImpl.java      | 12 ++++++++++--
 .../quarkus/support/StatefulRuleUnitServiceImpl.java         | 12 ++++++++++--
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git 
a/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/RuleUnitServiceImpl.java
 
b/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/RuleUnitServiceImpl.java
index 5c4e6cd984..ec1a04f0cd 100644
--- 
a/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/RuleUnitServiceImpl.java
+++ 
b/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/RuleUnitServiceImpl.java
@@ -20,6 +20,7 @@ package org.kie.kogito.core.rules.incubation.quarkus.support;
 
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 import org.drools.ruleunits.api.RuleUnit;
@@ -36,6 +37,9 @@ import 
org.kie.kogito.incubation.rules.services.RuleUnitService;
 
 class RuleUnitServiceImpl implements RuleUnitService {
 
+    // CWE-470: validate class name is a legal Java FQCN before passing to 
loadClass
+    private static final Pattern SAFE_CLASS_NAME = 
Pattern.compile("[\\w$]+(\\.[\\w$]+)*");
+
     private final RuleUnits ruleUnits;
 
     public RuleUnitServiceImpl(RuleUnits ruleUnits) {
@@ -64,12 +68,16 @@ class RuleUnitServiceImpl implements RuleUnitService {
     }
 
     private RuleUnitData convertValue(Map<String, Object> payload, RuleUnitId 
ruleUnitId) {
+        String className = ruleUnitId.ruleUnitId();
+        if (!SAFE_CLASS_NAME.matcher(className).matches()) {
+            throw new IllegalArgumentException("Invalid rule unit class name: 
" + className);
+        }
         try {
             // converts the identifier into a Class object for conversion
-            Class<RuleUnitData> type = (Class<RuleUnitData>) 
Thread.currentThread().getContextClassLoader().loadClass(ruleUnitId.ruleUnitId());
+            Class<RuleUnitData> type = (Class<RuleUnitData>) 
Thread.currentThread().getContextClassLoader().loadClass(className);
             return InternalObjectMapper.objectMapper().convertValue(payload, 
type);
         } catch (ClassNotFoundException e) {
-            throw new IllegalArgumentException("Cannot load class " + 
ruleUnitId.ruleUnitId(), e);
+            throw new IllegalArgumentException("Cannot load class " + 
className, e);
         }
     }
 
diff --git 
a/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/StatefulRuleUnitServiceImpl.java
 
b/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/StatefulRuleUnitServiceImpl.java
index 59588caba9..46ccdf5e1f 100644
--- 
a/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/StatefulRuleUnitServiceImpl.java
+++ 
b/quarkus/extensions/kogito-quarkus-rules-extension/kogito-quarkus-rules/src/main/java/org/kie/kogito/core/rules/incubation/quarkus/support/StatefulRuleUnitServiceImpl.java
@@ -21,6 +21,7 @@ package org.kie.kogito.core.rules.incubation.quarkus.support;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 import org.drools.ruleunits.api.RuleUnit;
@@ -41,6 +42,9 @@ import 
org.kie.kogito.incubation.rules.services.StatefulRuleUnitService;
 
 class StatefulRuleUnitServiceImpl implements StatefulRuleUnitService {
 
+    // CWE-470: validate class name is a legal Java FQCN before passing to 
loadClass
+    private static final Pattern SAFE_CLASS_NAME = 
Pattern.compile("[\\w$]+(\\.[\\w$]+)*");
+
     private final RuleUnits ruleUnits;
 
     public StatefulRuleUnitServiceImpl(RuleUnits ruleUnits) {
@@ -71,10 +75,14 @@ class StatefulRuleUnitServiceImpl implements 
StatefulRuleUnitService {
     }
 
     private Class<RuleUnitData> toClass(RuleUnitId ruleUnitId) {
+        String className = ruleUnitId.ruleUnitId();
+        if (!SAFE_CLASS_NAME.matcher(className).matches()) {
+            throw new IllegalArgumentException("Invalid rule unit class name: 
" + className);
+        }
         try {
-            return (Class<RuleUnitData>) 
Thread.currentThread().getContextClassLoader().loadClass(ruleUnitId.ruleUnitId());
+            return (Class<RuleUnitData>) 
Thread.currentThread().getContextClassLoader().loadClass(className);
         } catch (ClassNotFoundException e) {
-            throw new IllegalArgumentException(e);
+            throw new IllegalArgumentException("Cannot load class " + 
className, e);
         }
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to