Releases: Seclume/seclume
Release list
seclume 0.10.0
Java heap dumps without database credentials.
The three items listed under Not yet in 0.9.0 are done: the four wire
parsers are fuzzed, the compatibility matrix is generated from the test run
rather than written by hand, and the benchmark figures are recorded by a
harness that states the machine they came from.
Beyond that, in short:
- Logins with no secret in the process: Kerberos for PostgreSQL, MariaDB
and SQL Server; PostgreSQL 18 OAuth; Azure SQL access tokens; RDS IAM and
Secrets Manager from the EC2 instance role. - Beyond databases:
seclume-kafka(SASL/SCRAM) andseclume-redis
(Jedis) without the password on the heap;seclume-quarkus, JVM and native. - Security work: constant-time AES, Base64 and RSA; AES-GCM from the
operating system; post-quantum key exchange; a code review's ten findings
fixed; Semgrep, Trivy, CodeQL and Scorecard in CI. - Tested against real AWS: seven bugs found there and fixed
(test-reports/aws-2026-09-26.md). - A pool bug that lost a connection to every Spring
queryForStream, and a
login that could hang for ever on a silent server, fixed.
The full list is in CHANGELOG.md.
Getting it
Published to GitHub Packages (https://maven.pkg.github.com/Seclume/seclume; GitHub requires a token with read:packages to download from it):
<dependency>
<groupId>space.seclume</groupId>
<artifactId>seclume-spring-boot-starter</artifactId>
<version>0.10.0</version>
</dependency>seclume 0.9.0
The first published artifact, and the version number is the point: 0.9.0 is
not 1.0.0, deliberately. Everything below works and is tested against real
servers, but three things a 1.0 should be able to claim are not true yet, and
they are listed under Not yet rather than
glossed over.
What this is
Four JDBC drivers and a connection pool for PostgreSQL, MySQL, SQL Server and
Oracle, written from the wire protocol up, with one defining property:
A secret never becomes a
Stringor achar[]on the Java heap.
Credentials are read from a provider straight into off-heap memory, used where
the protocol needs them, and wiped. A heap dump of an application using these
drivers does not contain the database password, because the password was never
an object that a dump could find. seclume-heapcheck exists to prove that on a
running process rather than to assert it in a comment.
No runtime dependency beyond the JDK. Java 25.
Modules
seclume-core |
secret providers, off-heap buffers, the TLS 1.3 client, the JDBC scaffolding |
seclume-postgresql, seclume-mysql, seclume-sqlserver, seclume-oracle |
the four drivers |
seclume-pool |
a connection pool that understands credential lifetimes |
seclume-spring-boot-starter |
auto-configuration, JFR-to-Micrometer metrics, tracing |
seclume-verify |
a preflight command: does this configuration actually connect, and how |
seclume-heapcheck |
reads a live heap and reports whether a secret is in it |
seclume-bom, seclume-tck, seclume-bench, seclume-diff, seclume-spring-test |
dependency management, the shared test kit, benchmarks, the differential harness against the vendor drivers |
Secrets
- Providers for a file, an environment variable, a Unix domain socket, an
encrypted file, HashiCorp Vault, AWS Secrets Manager, Azure Key Vault and
Google Secret Manager - none of them through a vendor SDK, so none of
them drags a dependency or aStringin with it. - Vault leases and AWS temporary credentials are understood: a connection is
retired before its credential expires rather than after it fails. secret-uriin a JDBC URL, and a guard that refuses a plaintext password in
one.- The wipe is proven on the failure paths, not only the happy one - a login
that is rejected, a connection that dies mid-handshake, a server that is not
there at all.
TLS
- Two stacks, chosen per connection with
tlsStack: the JDK'sSSLEngine, or
seclume's own TLS 1.3 client, where every traffic secret lives in native
memory. - mTLS with a client key that never becomes a Java object.
- Channel binding (SCRAM-SHA-256-PLUS) on both stacks.
- TDS 8.0 for SQL Server, which is the only route by which that driver reaches
the own stack - and therefore the only route to a client certificate there. - Oracle over TCPS.
- The own stack is checked against the RFC 8448 vectors, against JSSE, and
against all four real servers.
The drivers
- Every driver has
CallableStatement, named parameters, XA,DatabaseMetaData,
procedures that return rows, and a pipeline block that puts a unit of work in
one round trip. - Result rows are read in place out of the receive buffer - a thousand rows
cost a handful of system calls and no copies. - Statement caching per connection, with an eviction that gives the server its
cursors back rather than leaking them. targetServerType=primary|secondaryover a host list, with a per-engine probe
for what a server says it is.- A
QueryFingerprintthat names a statement's shape and carries none of its
values.
Observability
- JFR events for statements, the cache, failover and TLS, with no runtime
dependency. - The Spring Boot starter bridges those to Micrometer and to tracing spans.
StatementListener, the one hook in the statement path, for a span that needs
the caller's thread context.
Testing
1695 tests. CI runs against PostgreSQL 15 and 18, MySQL 8.4, MariaDB 11.4,
SQL Server 2022 and 2025, Oracle Free 23ai, CockroachDB and YugabyteDB.
The vendor drivers are used as the oracle in a differential harness: the same
statement, the same server, both drivers, and any disagreement is a defect
here. It found eight.
Also in this release
- A session can be handed from one holder to another.
detach()gives up
an authenticated stream andresume()picks one up, so a login can happen
once, where the credential is, and whoever receives the stream never needs
one. On seclume's own TLS stack the encryption goes along with it; on the
JDK's it cannot, and the refusal says why. What anybody builds on that is
their business - this library provides the join. OracleSession.releaseCursors().detach()refuses while cursors are
open and told callers to close them, and nothing here offered a way. Now it
does, at the cost of one round trip.- Fixed:
close()on all four channels ignored a channel that had been
given up, and so closed the socket it had just handed over.
Not yet, and why this is 0.9.0
| The wire parsers are not fuzzed. | Four protocols are parsed here by hand, and every one of those parsers reads a length and then trusts it. The property tests are good at valid values and at edges; they are not an adversary. A 1.0 for a library whose argument is byte-level correctness should be able to say it has been attacked. |
| The compatibility matrix is prose, not generated. | The list of servers above is written by hand next to the run instead of produced by it, so it can drift from it. |
| The benchmark numbers are not reproducible by a reader. | The figures in the README are real and were measured, but without the hardware, the server configuration, the warm-up, the repetitions and the raw data beside them they ask to be taken on trust. |
The API may still change before 1.0.0. It changed on the day of this release.
A note on this registry
GitHub Packages requires a token even to read a public package. That is a
property of the registry, not of this project. A dependency that should simply
resolve belongs on Maven Central, and that is where 1.0.0 will go.