Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ To avoid deserialization of objects from untrusted sources, Hazelcast offers som
xref:security:tls-ssl.adoc#mutual-authentication[mutual TLS authentication] and disabling xref:clusters:network-configuration.adoc#multicast-element[multicast join] configuration.
We recommend using Java serialization filter configuration for whitelisting the set of trusted classes or
packages which are allowed for deserialization.
* Hazelcast can fall back to zero-configuration Compact serialization for classes that have no explicit serializer. We recommend restricting the classes eligible for zero-config Compact serialization by defining an allowlist of only the classes your application needs, rather than relying on the default behavior. See xref:serialization:compact-serialization.adoc#zero-config-filter[Restricting Classes for Zero-Config Compact Serialization].

@k-jamroz k-jamroz Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Hazelcast can fall back to zero-configuration Compact serialization for classes that have no explicit serializer. We recommend restricting the classes eligible for zero-config Compact serialization by defining an allowlist of only the classes your application needs, rather than relying on the default behavior. See xref:serialization:compact-serialization.adoc#zero-config-filter[Restricting Classes for Zero-Config Compact Serialization].
* Hazelcast can use zero-configuration Compact serialization for eligible classes that have no explicit serializer. We recommend restricting the classes allowed to use zero-config Compact serialization by defining an allowlist of only the classes your application needs, rather than relying on the default behavior. See xref:serialization:compact-serialization.adoc#zero-config-filter[Restricting Classes for Zero-Config Compact Serialization].
If you do not use zero-configuration Compact serialization, disable defaults and configure empty allowlist for best security.

@th0masb could you verify this, in particular the requirement about disabling defaults to configure empty allowlist. We might have discussed this previously, but I realized (again?) that this is a bit unfortunate. If you start with empty allowlist and disabled defaults, but then want to add some unreasonable classes to allowlist (eg. com.hazelcast) you lose the safety net of default blocklist.

@k-jamroz k-jamroz Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also add a recomendation to configure serialization restrictions (Java - previous point) and ZCCS (this point) not only on members but also on clients. And they do not have to be the same, although blocked classes will not be usable in client/member that has them blocked.

* Hazelcast uses Java reflection during SQL execution when the object format is set to `java`. We recommend using xref:sql:sql-reflection-configuration.adoc#configuring-reflection[Java reflection filter configuration] to whitelist the set of trusted classes or packages that are allowed to create through reflection.
* You can disable script executions on the Hazelcast members. Scripts executed from Management center have access
to system resources (files, etc.) with privileges of user running Hazelcast.
Expand Down
108 changes: 94 additions & 14 deletions docs/modules/serialization/pages/compact-serialization.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Client.newHazelcastClient(
compact: {
serializers: [
new FooSerializer()
]
]
)
----
--
Expand Down Expand Up @@ -511,20 +511,20 @@ struct hz_serializer<employee> : public compact_serializer
static employee read(compact_reader& reader)
{
employee e;

e.id = reader.read_int64("id");
e.name = reader.read_string("name");

return e;
}

static void write(const employee& e, compact_writer& writer)
{
writer.write_int64("id", e.id);
writer.write_string("name", e.name);
}
}

static std::string type_name() { return "employee"; }
static std::string type_name() { return "employee"; }
};
----
--
Expand Down Expand Up @@ -1037,8 +1037,8 @@ When Hazelcast cannot associate a class with any other serialization mechanism,
throwing an exception directly, it tries to use zero-configuration Compact serialization
as a last effort.

Hazelcast tries to extract a schema out of the class. If successful, it registers the
zero-config serializer associated with the extracted schema and uses it while serializing
Hazelcast tries to extract a schema out of the class. If successful, it registers the
zero-config serializer associated with the extracted schema and uses it while serializing
and deserializing instances of that class. If the automatic schema extraction fails,
Hazelcast throws an exception.

Expand Down Expand Up @@ -1132,6 +1132,86 @@ module org.example.Foo {
}
----

[[zero-config-filter]]
== Restricting Classes for Zero-Config Compact Serialization

Zero-config Compact serialization uses reflection to serialize any class that does not have another registered serializer. To control which classes are eligible for this, and to prevent classes from being serialized unintentionally, configure a filter that allows or blocks classes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these restrictions apply only to ZCCS. it is possible to register explicit serializers for classes that are not allowed for ZCCS.


The filter uses an allowlist and a blocklist. This is the same format as the xref:sql:sql-reflection-configuration.adoc[SQL Java reflection filter]. You can allow or block classes by fully qualified class name, package name, or class-name prefix. The filter can be set on both members and clients.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better to link to https://docs.hazelcast.com/hazelcast/5.7/serialization/serialization-configuration#untrusted-classes instead of SQL docs (SQL is a specific feature)


When a filter is configured:

@k-jamroz k-jamroz Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

describe also how to configure empty filter to effectively disable ZCCS


* If a class is on the blocklist, serializing an object of that class throws an exception.
* If a class is on the blocklist, deserializing its data returns a `GenericRecord` instead of an instance of the class, rather than throwing an exception.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually quite nice feature, possibly worth highlighting a bit more. some features like PredicateAPI/SQL query can process a compact-serialized class even if it is blocked from serialization, because extracting individual fields without object creation is safe.
entry processor or other member-side code can use GenericRecord to access the data, which may be sufficient in some cases

* If the allowlist is non-empty, only classes on the allowlist (and not on the blocklist) are eligible for zero-config Compact serialization.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only classes on the allowlist (and not on the blocklist)

both conditions need to be met. partentheses introduce a bit of assymetry in the text. Maybe:

Suggested change
* If the allowlist is non-empty, only classes on the allowlist (and not on the blocklist) are eligible for zero-config Compact serialization.
* If the allowlist is non-empty, only classes on the allowlist which are not on the blocklist are eligible for zero-config Compact serialization.

?


Without a configured filter, Hazelcast applies a built-in blocklist of internal classes. This does not cover your own classes, so for the strongest protection, we suggest defining an allowlist containing only the classes your application needs.

[tabs]
====
XML::
+
--
[source,xml]
----
<hazelcast>
...
<serialization>
<compact-serialization>
<zero-config-filter defaults-disabled="false">
<whitelist>
<class>example.Foo</class>
<package>com.acme.app</package>
<prefix>com.acme.</prefix>
</whitelist>
<blacklist>
<class>com.acme.app.BeanComparator</class>
</blacklist>
</zero-config-filter>
</compact-serialization>
</serialization>
...
</hazelcast>
----
--
YAML::
+
--
[source,yaml]
----
hazelcast:
serialization:
compact-serialization:
zero-config-filter:
defaults-disabled: false
whitelist:
class:
- example.Foo
package:
- com.acme.app
prefix:
- com.acme.
blacklist:
class:
- com.acme.app.BeanComparator
----
--
Java::
+
--
[source,java]
----
Config config = new Config();
JavaSerializationFilterConfig filter = new JavaSerializationFilterConfig();
filter.getWhitelist().addClasses("example.Foo");
filter.getWhitelist().addPackages("com.acme.app");
filter.getWhitelist().addPrefixes("com.acme.");
filter.getBlacklist().addClasses("com.acme.app.BeanComparator");
config.getSerializationConfig().getCompactSerializationConfig().setZeroConfigFilter(filter);
----
--
====

== Schema Evolution

This section provides an introduction to schema evolution, explaining how Compact serialization allows your object
Expand Down Expand Up @@ -1255,7 +1335,7 @@ public class Employee {
[source,cs]
----
public record Employee(
long Id,
long Id,
string Name,
int Age // newly-added field
);
Expand Down Expand Up @@ -1354,7 +1434,7 @@ public class EmployeeSerializer : ICompactSerializer<Employee>
{
var id = reader.ReadInt64("id");
var name = reader.ReadString("name");
// the new 'age' field is there, but the old reader does not
// the new 'age' field is there, but the old reader does not
// know anything about it, and ignores the field.
return new Employee(id, name);
}
Expand All @@ -1375,14 +1455,14 @@ struct hz_serializer<employee> : compact_serializer
employee& read(compact_reader& reader)
{
employee e;

e.id = reader.read_int32("id");
e.name = reader.read_string("name");
// The new "age" field is there, but the old reader does not
// know anything about it. Hence, it will simply ignore that field.
return e;
}

// ...
};
----
Expand Down Expand Up @@ -1507,10 +1587,10 @@ struct hz_serializer<employee> : compact_serializer
employee& read(compact_reader& reader)
{
employee e;

e.id = reader.read_int64("id");
e.name = reader.read_string("name");

// read the "age" field if it exists, else use the default value 0
// reader.read_int32("age") would throw if the "age" field
// does not exist in data.
Expand All @@ -1520,7 +1600,7 @@ struct hz_serializer<employee> : compact_serializer
} else {
e.age = 0;
}

return e;
}
};
Expand Down
10 changes: 6 additions & 4 deletions docs/modules/sql/pages/sql-reflection-configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ When objects are constructed through reflection, the following filtering rules a

When reflection fails, a `SecurityException` is thrown.

By default, reflection restriction filter is empty and all class names or package names are allowed.
By default, a basic blocklist is applied: class names with the prefixes `com.hazelcast.shaded` and `org.springframework.beans` are blocked, while all other class names and package names are allowed.

If the reflection restriction filter is not empty, class names or package names with the specified prefixes are automatically added to the whitelist by default:
We recommend configuring your own filter, ideally a minimal allowlist as this is more secure than a blocklist against possible future vulnerabilities.

If the reflection restriction filter is configured, the following prefixes are automatically added to the allowlist by default:

* `java`
* `com.hazelcast.`
* `[` (for primitives and arrays)

If you do not want to allow these default prefixes, set the `defaults-disabled` attribute to `true`.
The default blocklist is also applied. To turn off both the default allowlist prefixes and the default blocklist, set the `defaults-disabled` attribute to `true`.

[tabs]
====
Expand Down Expand Up @@ -95,4 +97,4 @@ reflectionConfig.getWhitelist().addClasses(SomeAllowedClass.class.getName());
config.getSqlConfig().setJavaReflectionFilterConfig(reflectionConfig);
----
--
====
====