Skip to content

Commit f6b3bd7

Browse files
jbonofreFokkomartin-g
authored
AVRO-3985: Add trusted packages support in SpecificData (#2934)
* AVRO-3985: Add trusted packages support in SpecificData * Apply suggestions from code review Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com> * Move to SecurityException * Remove redundant import --------- Co-authored-by: Fokko Driesprong <fokko@apache.org> Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
1 parent 3718b76 commit f6b3bd7

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java

-10
Original file line numberDiff line numberDiff line change
@@ -429,16 +429,6 @@ private FieldAccessor getFieldAccessor(Class<?> c, String fieldName) {
429429
return null;
430430
}
431431

432-
/** @deprecated Replaced by {@link SpecificData#CLASS_PROP} */
433-
@Deprecated
434-
static final String CLASS_PROP = "java-class";
435-
/** @deprecated Replaced by {@link SpecificData#KEY_CLASS_PROP} */
436-
@Deprecated
437-
static final String KEY_CLASS_PROP = "java-key-class";
438-
/** @deprecated Replaced by {@link SpecificData#ELEMENT_PROP} */
439-
@Deprecated
440-
static final String ELEMENT_PROP = "java-element-class";
441-
442432
private static final Map<String, Class> CLASS_CACHE = new ConcurrentHashMap<>();
443433

444434
static Class getClassProp(Schema schema, String prop) {

lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java

+46-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,25 @@
2424
import org.apache.avro.io.ResolvingDecoder;
2525
import org.apache.avro.util.ClassUtils;
2626
import java.io.IOException;
27+
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
import java.util.List;
2730

2831
/**
2932
* {@link org.apache.avro.io.DatumReader DatumReader} for generated Java
3033
* classes.
3134
*/
3235
public class SpecificDatumReader<T> extends GenericDatumReader<T> {
36+
37+
public static final String[] SERIALIZABLE_PACKAGES;
38+
39+
static {
40+
SERIALIZABLE_PACKAGES = System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES",
41+
"java.lang,java.math,java.io,java.net,org.apache.avro.reflect").split(",");
42+
}
43+
44+
private final List<String> trustedPackages = new ArrayList<>();
45+
3346
public SpecificDatumReader() {
3447
this(null, null, SpecificData.get());
3548
}
@@ -55,6 +68,7 @@ public SpecificDatumReader(Schema writer, Schema reader) {
5568
*/
5669
public SpecificDatumReader(Schema writer, Schema reader, SpecificData data) {
5770
super(writer, reader, data);
71+
trustedPackages.addAll(Arrays.asList(SERIALIZABLE_PACKAGES));
5872
}
5973

6074
/** Construct given a {@link SpecificData}. */
@@ -101,12 +115,43 @@ private Class getPropAsClass(Schema schema, String prop) {
101115
if (name == null)
102116
return null;
103117
try {
104-
return ClassUtils.forName(getData().getClassLoader(), name);
118+
Class clazz = ClassUtils.forName(getData().getClassLoader(), name);
119+
checkSecurity(clazz);
120+
return clazz;
105121
} catch (ClassNotFoundException e) {
106122
throw new AvroRuntimeException(e);
107123
}
108124
}
109125

126+
private boolean trustAllPackages() {
127+
return (trustedPackages.size() == 1 && "*".equals(trustedPackages.get(0)));
128+
}
129+
130+
private void checkSecurity(Class clazz) throws ClassNotFoundException {
131+
if (trustAllPackages() || clazz.isPrimitive()) {
132+
return;
133+
}
134+
135+
boolean found = false;
136+
Package thePackage = clazz.getPackage();
137+
if (thePackage != null) {
138+
for (String trustedPackage : getTrustedPackages()) {
139+
if (thePackage.getName().equals(trustedPackage) || thePackage.getName().startsWith(trustedPackage + ".")) {
140+
found = true;
141+
break;
142+
}
143+
}
144+
if (!found) {
145+
throw new SecurityException("Forbidden " + clazz
146+
+ "! This class is not trusted to be included in Avro schema using java-class. Please set org.apache.avro.SERIALIZABLE_PACKAGES system property with the packages you trust.");
147+
}
148+
}
149+
}
150+
151+
public final List<String> getTrustedPackages() {
152+
return trustedPackages;
153+
}
154+
110155
@Override
111156
protected Object readRecord(Object old, Schema expected, ResolvingDecoder in) throws IOException {
112157
SpecificData data = getSpecificData();

0 commit comments

Comments
 (0)