jPOS and jPOS-EE 3.0.2 Released
We are pleased to announce the release of jPOS 3.0.2 and jPOS-EE 3.0.2, available as of September 30, 2026.
These releases bring together several months of work on security, transaction observability, modern message formats, and operational reliability. jPOS strengthens the core messaging and Q2 runtime; jPOS-EE builds on that foundation with improvements to QRest, database transactions, cryptographic services, and supporting infrastructure.
Although the version increment is small, the changes are substantial. This is also a release worth planning for: the Java baseline advances, some APIs have been removed, and log consumers need to accommodate a more structured event model.
jPOS 3.0.2 fixes GHSA-2267-c568-hxcc, rated Medium (CVSS 3.1: 6.5), affecting versions through 3.0.1. The fix rejects unsafe dynamically derived schema paths and disables XML DOCTYPE and external-entity processing in FSDMsg.
Exploitation requires specific conditions—not simply sending an ordinary ISO 8583 message. An affected FSD configuration must let the sender influence schema selection. File disclosure or attacker-directed outbound requests additionally require attacker-controlled XML reachable by the server. The demonstrated exploit required placing a crafted XML file on the server; those impacts have not been demonstrated from a network message alone.
This makes exploitation significantly more constrained than a general unauthenticated file-read vulnerability. Nevertheless, deployments using FSDMsg, directly or through FSDChannel or FSDPackager, should upgrade.
Security at the boundaries
In jPOS, several changes tighten the boundaries where external data, configuration, and runtime behavior meet:
- TLS hostname verification now uses JSSE endpoint identification, following corrections to certificate-name parsing.
- XML2003Packager no longer re-enables external entities and DOCTYPE processing over the secure XML defaults.
- Java deserialization gains object-input filters and a maximum object-graph depth to reduce exposure to unsafe serialized objects.
- Q2's ENABLE and DISABLE commands reject paths that resolve outside the deployment directory.
- Context logging suppresses values stored under
Inhibitkeys.
jPOS-EE extends that work to HTTP and WebSocket applications. QRest masks credential and cookie headers, avoids dumping transport objects through ordinary Context logging, and provides safer diagnostics through DebugHttpContext. Its exception handler now returns a fixed “Internal Server Error” body rather than exposing exception messages.
WebSocket upgrades also gain same-origin checks and configurable origin allowlists. Behind a TLS-terminating proxy, forwarded scheme and host information is trusted only when the connection comes from a configured trusted proxy. That trust is explicit: the proxy must sanitize forwarded headers and validate the public host.
These changes strengthen the framework's defaults and controls; applications still need appropriate authentication, authorization, and deployment configuration.
Logs that describe transactions, not just connections
A major theme of 3.0.2 is making operational evidence easier to correlate and consume.
The new JsonlLogWriter produces structured JSON Lines with typed payloads, tags, and configurable protection of sensitive ISO fields, including nested field paths. It includes PAN masking and track/PIN wiping, and supersedes the older JSON, XML, text, and Markdown writer implementations, which are now deprecated.
A registered vocabulary of event kinds and families gives log consumers a consistent way to distinguish operational, telemetry, and security events. Realms identify stable components; tags carry changing details such as endpoints, sessions, participants, and nested fields.
Transaction tracing becomes more precise as well. Content-derived wire-exchange trace IDs follow messages through incoming processing, TransactionManager, and response handling. QueryHost connects rebuilt outbound requests to the originating Context when they do not already carry a trace claim.
The distinction matters: a session identifies a connection; a trace identifies an exchange. Multiple transactions sharing one connection no longer need to be interpreted as one trace.
QRest participates in the same structured logging model. Its access tracking records completion and failure at the request level, while HTTP, WebSocket, and Store-and-Forward metrics expand visibility into application behavior.
Q2 also reports its node number and runtime classpath fingerprint, helping operators identify what is actually running. Prometheus scraping, transaction histograms, and default JFR recordings have been adjusted to reduce observability's memory footprint.
Richer ISO 8583:2023 and CMF support
jPOS 3.0.2 expands support for ISO 8583:2023's composite data elements through DatasetPackager, ICCDataPackager, ISODatasetField, and the dataset-aware cmfv3.xml packager.
Rather than leaving complex fields as opaque byte arrays, applications can work with structured representations of customer information, card-acceptor details, response data, and other datasets.
New helpers cover:
- MessageErrorIndicator: structured identification of errors in primitive, constructed, and composite data elements.
- LifeCycleId: transaction lifecycle identification, integrated with trace identifier generation.
- PosCapability: structured terminal capability information.
The release also adds CMFChannel, aligns CMF result codes, and corrects multiple field lengths, encodings, and composite layouts. Expanded CMF fields cover tokenization, payment facilitators, cardholder-name verification, extended authorization, crypto-card indicators, and age verification.
These are practical interoperability improvements, but they also mean that applications maintaining private packager copies should compare them with the updated definitions.
Card-data handling receives smaller but useful refinements: normalization of raw Track 2 sentinels and separators, additional Track 1 service-code indicators, and standard 10-5-5 KSN parsing and serialization.
For cryptographic integrations, EMVSMAdapter adds support for EMV cryptogram generation, key derivation, secure messaging, and offline data authentication.
Database failures must not become commits
One of the most important jPOS-EE corrections concerns transaction cleanup.
Previously, a failed action could reach connection cleanup without an explicit rollback. Depending on the connection provider, that could result in unfinished work being committed—the opposite of what callers expect after an exception.
The DB execution helpers now roll back unfinished transactions on failure, and DB.close() defensively rolls back pending work. Successful explicit commits remain unchanged. When cleanup also fails, the original exception is preserved and cleanup failures are attached as suppressed exceptions.
PostgreSQL/Agroal regressions exercise this behavior against a real database.
Additional database improvements include Duration timeout overloads for transaction helpers, a fix for spurious Hibernate dirty detection on null tags, and Flyway support for database configuration modifiers and custom history tables. Migration logs now identify both the command and database, making multi-database operations easier to diagnose.
QRest: clearer ownership and request lifecycles
Asynchronous HTTP processing requires careful ownership of request and response buffers. jPOS-EE 3.0.2 addresses leaks when requests expire in a queue or never reach SendResponse.
QRest now copies the request body into an independent, garbage-collected heap snapshot before asynchronous processing and releases the original Netty request at ingress. The copy is bounded by maxContentLength, and the detached request remains readable after a client disconnects.
Response cleanup is also hardened across construction, header processing, and sending. Access logging and metrics complete once per request, and failed writes are no longer counted as successful responses.
A configurable request-timeout bounds how long the connection waits for an unanswered request. It defaults to the configured timeout, normally 300 seconds; zero disables this per-request deadline.
This is not a transaction-cancellation mechanism. A disconnect or response timeout does not cancel transaction processing, and the existing Space lease remains separate. Applications must continue to handle unknown outcomes and retries according to their transaction semantics.
More predictable day-to-day operation
Several improvements focus on failures that are easy to overlook until they happen in production:
- Log rotation avoids overwriting existing same-day archives and preserves log data when rotation or compression fails. Compression is serialized through a shared worker.
- Embedded Q2 no longer terminates its host JVM on a startup exception; command-line startup retains its exit-on-error behavior.
- Intentional listener-driven disconnects no longer produce a spurious server receive error, and concurrent socket closure no longer hides the original I/O failure.
- Date parsing handles leap-day year inference and daylight-saving normalization more reliably.
- BinLog uses bounded file-lock acquisition and condition-based waiting instead of busy polling.
ThroughputControlscales polling between 50 and 500 milliseconds, reducing wakeups without changing configured rate limits, at the cost of coarser responsiveness while throttled.
Other additions include longest-prefix fallback routing in Switch, explicit enum keys in TransactionManager context contracts, and AES-GCM additional authenticated data support in jPOS-EE's CryptoService.
Refreshed dependencies and toolchain
Both projects move to Java 26, with Gradle 9.7.1 and a Java 26.0.2 SDKMAN pin.
The release consolidates dependency updates made throughout the development cycle. Selected final versions include:
- Jackson 2.22.3, Bouncy Castle 1.86, JLine 4.4.6, and Micrometer 1.17.1 in jPOS.
- Netty 4.2.18.Final, Hibernate ORM and Tools 6.6.58.Final, H2 2.5.252, Logback 1.6.4, SLF4J 2.0.20, and AWS Payment Cryptography SDK 2.55.6 in jPOS-EE.
The full ChangeLogs record the broader JDBC, HTTP, messaging, build, and test-library updates.
Planning your upgrade
Before moving an existing application to 3.0.2, pay particular attention to:
- Java and source compatibility. Update the runtime and build toolchain. TransactionManager's static
getSerializable(),getContext(), andgetId()accessors have been removed; pass the context and transaction ID explicitly. - Log consumers. Review event-kind names, typed session payloads, realm/tag conventions, and the distinction between exchange traces and connection sessions.
- Wire formats. Reconcile custom CMF packagers and result-code mappings with the updated definitions.
- Database lifecycle. Closing unfinished work now rolls it back. Code must not rely on connection closure to commit.
- HTTP deployment settings. Review request deadlines, body-size limits, WebSocket origins, and trusted-proxy configuration.
- Security-sensitive integrations. Exercise TLS peers and serialized application objects against the stricter validation and filtering. FSD schemas must no longer depend on DOCTYPE declarations or external entities, and dynamically selected schema suffixes must satisfy the new validation.
We recommend evaluating the two releases together, particularly for applications using QRest and the shared structured logging model.
Thank you to everyone who contributed code, reviews, reproductions, and operational feedback.
For the complete release details, see the jPOS ChangeLog and the jPOS-EE ChangeLog.
