Java Serialization Filters

The Java serialization filtering mechanism screens incoming streams of serialized objects to help improve security and robustness. Filters can validate incoming instances of classes before they are deserialized.

As stated in JEP 290 and JEP 415, the goals of the Java serialization filtering mechanism are to:
  • Provide a way to narrow the classes that can be deserialized down to a context-appropriate set of classes.

  • Provide metrics to the filter for graph size and complexity during deserialization to validate normal graph behaviors.

  • Allow RMI-exported objects to validate the classes expected in invocations.

There are two kinds of filters:

  • JVM-wide filter: Is applied to every deserialization in the JVM. However, whether and how a JVM-wide filter validates classes in a particular deserialization depends on how it's combined with other filters.
  • Stream-specific filter: Validates classes from one specific ObjectInputStream.

You can implement a serialization filter in the following ways:

  • Specify a JVM-wide, pattern-based filter with the jdk.serialFilter property: A pattern-based filter consists of a sequence of patterns that can accept or reject the name of specific classes, packages, or modules. It can place limits on array sizes, graph depth, total references, and stream size. A typical use case is to add classes that have been identified as potentially compromising the Java runtime to a reject-list. If you specify a pattern-based filter with the jdk.serialFilter property, then you don't have to modify your application.

  • Implement a custom or pattern-based stream-specific filter with the ObjectInputFilter API: You can implement a filter with the ObjectInputFilter API, which you then set on an ObjectInputStream. You can create a pattern-based filter with the ObjectInputFilter API by calling the Config.createFilter(String) method.

Note:

A serialization filter is not enabled or configured by default. Serialization filtering doesn't occur unless you have specified the filter in a system property or a Security Property or set it with the ObjectInputFilter class.

For every new object in the stream, the filter mechanism applies only one filter to it. However, this filter might be a combination of filters.

In most cases, a stream-specific filter should check if a JVM-wide filter is set, especially if you haven't specified a filter factory. If a JVM-wide filter does exist, then the stream-specific filter should invoke it and use the JVM-wide filter’s result unless the status is UNDECIDED.