This guide walks you through integrating the Blocklist XStream adapter into your application and choosing the right security mode for your use case.
Add the dependency to your pom.xml:
1 2<dependency> <groupId>com.atlassian.security.serialblocklist</groupId> <artifactId>blocklist-xstream-adapter</artifactId> <version>${serialblocklist.version}</version> <scope>provided</scope> </dependency>
Add the dependency to your build.gradle:
1 2dependencies { implementation 'com.atlassian.security.serialblocklist:blocklist-xstream-adapter:${serialblocklist.version}' }
The adapter supports two operating modes. Choose based on your security requirements and migration constraints:
Best for: New applications, high-security environments, APIs processing untrusted input
Security level: Maximum - only explicitly allowed types can be processed
1 2import com.atlassian.security.serialblocklist.xstream.BlocklistRestrictedXStream; XStream xstream = new BlocklistRestrictedXStream(); // Allowlist mode is the default - no additional configuration needed // Must explicitly allow each type you want to serialize xstream.allowTypes(new Class<?>[] { MyUserData.class, MyConfiguration.class, MyApiResponse.class });
Best for: Existing applications, gradual security hardening, complex type hierarchies
Security level: Good - blocks known dangerous classes while allowing broad compatibility
1 2import com.atlassian.security.serialblocklist.xstream.BlocklistRestrictedXStream; import com.thoughtworks.xstream.security.AnyTypePermission; XStream xstream = new BlocklistRestrictedXStream(); // Enable blocklist mode xstream.addPermission(AnyTypePermission.ANY); // Can now serialize/deserialize any type except blocklisted ones // No explicit type allowlisting required
1 2public class UserProfile { private String username; private String email; private List<String> roles; // constructors, getters, setters... } // Allowlist mode XStream xstream = new BlocklistRestrictedXStream(); xstream.allowTypes(new Class<?>[] { UserProfile.class }); String xml = xstream.toXML(userProfile); UserProfile restored = (UserProfile) xstream.fromXML(xml);
1 2// Blocklist mode for complex legacy configurations XStream xstream = new BlocklistRestrictedXStream(); xstream.addPermission(AnyTypePermission.ANY); // Configure aliases for cleaner XML xstream.alias("config", ApplicationConfig.class); xstream.alias("database", DatabaseConfig.class); String xml = xstream.toXML(applicationConfig); ApplicationConfig restored = (ApplicationConfig) xstream.fromXML(xml);
You can still use custom converters with both modes:
1 2XStream xstream = new BlocklistRestrictedXStream(); // Custom converter registration (priority must be lower than blocklist converter) xstream.registerConverter(new MyCustomConverter(), XStream.PRIORITY_VERY_HIGH); // Local field converters are automatically wrapped for security xstream.registerLocalConverter(MyClass.class, "specialField", new MyFieldConverter());
The adapter throws specific exceptions for security violations:
1 2try { Object result = xstream.fromXML(untrustedXml); } catch (ForbiddenClassException e) { // A blocklisted class was encountered logger.warn("Blocked deserialization attempt for class: " + e.getMessage()); // Handle gracefully - do not expose internal details to users }
IllegalArgumentException when registering converterCause: Converter priority is too high (>= blocklist converter priority) Solution: Use a lower priority value
ForbiddenClassException for allowed typeCause: Type is on Atlassian's security blocklist Solution: Use a different type or contact security team if needed
Rate this page: