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]