Harden JDBCJobStore deserialization: centralize getObjectFromBlob and support a JEP-290 ObjectInputFilter - #1494
Conversation
Route the base StdJDBCDelegate.getObjectFromBlob() and the ten dialect delegate overrides through a shared readObjectFromBinaryStream(InputStream) helper, and add an optional, configurable ObjectInputFilter (JEP 290) that is applied at that single point. The filter is set via the delegate init-string setting objectInputFilter=<pattern>; when unset, deserialization behavior is unchanged. No new dependencies (ObjectInputFilter is JDK 9+, this project targets Java 11). Adds StdJDBCDelegateTest coverage for the unfiltered (behavior-preserving) and filtered (rejects a non-allow-listed class) paths. Signed-off-by: Nexory <St4yl3r30@hotmail.de>
898e0da to
2322cd9
Compare
|
Marking this ready for review. There has been no feedback on the default-policy question in #1495, so I have kept the non-breaking opt-in default (option a): the filter defaults to Happy to switch the default to the conservative resource-limit variant (b) or a documented reject-list (c) if the team prefers; either is a small follow-up on top of this change. Whatever default you choose, the central choke point stays the same. |
|
LGTM but i guess this needs the opinion of the maintainers. |
|
@jhouserizer when you have a moment I'd appreciate a review. The only open item is the default |
|
@Nexory - This looks good - I'm remote next few days (just on my phone )- I think how you've defaulted it is fine - would you mind adding a bit of update to doc/examples about how to use it? Even just incorporating the example into an existing one, or something? e.g. https://github.com/quartz-scheduler/quartz/tree/main/examples , https://github.com/quartz-scheduler/quartz-scheduler.org-site/tree/master/documentation/quartz-2.5.x/configuration |
|
Thanks! Added a commented, off-by-default example of the |
Adds a commented, off-by-default example of the objectInputFilter delegate setting to the JDBC/clustering example (example13), showing the java.io.ObjectInputFilter pattern syntax on driverDelegateInitString. The line stays disabled by default, so the example runs unchanged. Signed-off-by: Nexory <St4yl3r30@hotmail.de>
9bf2631 to
248febf
Compare
Summary
This centralizes the
JDBCJobStoreBLOB deserialization behind a single helper and adds support for a configurable JEP-290ObjectInputFilter, so the job-data-map / trigger / calendar deserialization can be constrained in one place instead of being an unfilterednew ObjectInputStream(...).readObject()duplicated across the base delegate and every dialect delegate (CWE-502 hardening).Discussion / design question (default policy): see the linked issue. Opening as a draft: the default is left as opt-in (no behavior change) pending the team's preference on the default filter policy.
Changes
StdJDBCDelegate.readObjectFromBinaryStream(InputStream), the single choke point that constructs theObjectInputStream, applies the configuredObjectInputFilter(if any), and reads the object.getObjectFromBlob()and all ten dialect overrides (PostgreSQLDelegate,MSSQLDelegate,OracleDelegate,HSQLDBDelegate,SybaseDelegate,WebLogicDelegate,PointbaseDelegate,CUBRIDDelegate,CacheDelegate,GaussDBDelegate) through it. Each delegate keeps its own dialect-specific stream fetching; only the deserialization step is shared.objectInputFilterfield, configurable via the delegate init-string settingobjectInputFilter=<JEP-290 pattern>(parsed withObjectInputFilter.Config.createFilter). The init-string split is changed tosplit("=", 2)so filter patterns (which contain=) survive parsing.java.io.ObjectInputFilteris JDK 9+, this project targets Java 11).Behavior
objectInputFilterconfigured, the field isnulland deserialization behaves exactly as before.org.quartz.jobStore.driverDelegateInitString = objectInputFilter=maxdepth=20;java.**;org.quartz.**;!*), the filter is applied at the single choke point for every BLOB the store reads back.Testing
./gradlew :quartz:compileJavasucceeds on the Java 11 toolchain../gradlew :quartz:test --tests StdJDBCDelegateTest: 7 passed, 0 failed. Two tests were added:testReadObjectFromBinaryStreamWithoutFilterIsBehaviorPreserving: legitimate map round-trips unchanged with no filter.testReadObjectFromBinaryStreamAppliesConfiguredFilter: a legitimate map still deserializes, while a class outside the configured allow-list is rejected (InvalidClassException).Notes
Commits are DCO signed-off. This is a draft pending the default-policy discussion in the linked issue; happy to adjust the default (opt-in vs. a non-breaking resource-limit default vs. a reject-list) before finalizing.