Repository navigation
Releases
Qertum 1.0.0
Qertum 1.0.0
The first stable release. From this version the
support and compatibility policy applies: it says what a
version number promises and which releases get security fixes. Qertum stays free software under the MIT licence,
provided as is; no support plan is sold.
Security
- Automatic renewals revoke what they replace. ACME and EST renewals that are approved automatically now honour
AutoRevokeOnRenewal, as manual approval already did: the replaced certificate is revoked with reason
superseded. - Concurrent revocations keep the winning reason. Two revocation requests for the same certificate can no
longer overwrite each other's reason or side effects. - CA keys at rest are always encrypted. Startup encrypts legacy plaintext CA key files, including per-issuer
files, with the Data Protection key ring, replacing them atomically with owner-only permissions. - TPM wrapping keys never touch disk. Sealing and unsealing pass the wrapping key through process pipes instead
of temporary files. - Multi container: CA hosts no longer see identity or web state. API, ACME, EST and the queue consumer see
/data/identityand/data/webas empty; API and the queue consumer read only the identity audit logs. - Shorter access tokens. The built-in identity provider issues access tokens valid for 10 minutes instead of an
hour (IdentityService__AccessTokenLifetimeMinutes, 1 to 60), so a disabled, deleted or demoted user loses API
access within that time. - Permission changes reach every API instance. When the shared cache cannot be read, role permissions are read
from the database instead of a cached copy. - The first settings save cannot weaken PQC enforcement. The PQC stage starts at Enforce and only an
administrator changes it. - ACME http-01 never uses a proxy, so the challenge address policy checks the address actually connected to.
- ACME renewals need an issued predecessor to qualify for the Pilot-stage classical-key exception.
- Bulk operations without a stable creator are administrator-only.
- Sign-in input is bounded: usernames up to 256 and passwords up to 1024 characters.
- The web UI's localhost development addresses are registered with the built-in identity provider only in
Development. qcareplaces terminal control characters in server text with?and writes key files without following a
symbolic link at the output path.- Logs name issuers by ID in the CRL supersession message, not by their user-controlled name.
- Patched .NET runtime. Both images now build on ASP.NET Core 10.0.15, which fixes the November 2026
ASP.NET Core advisories, among them an elevation of privilege in the connection layer that Blazor's web UI uses
(CVE-2026-114146) and a denial of service (CVE-2026-114147). ASP.NET Core, EF Core and the cryptography packages
move to 10.0.15 too. - Source builds: Aspire 13.6.5. The AppHost and its packages move to Aspire 13.6.5, which fixes a dashboard
cookie leak to a linked container (CVE-2026-120006). The Aspire CLI must be 13.6.5 or newer too
(CVE-2026-120778, CVE-2026-120792). This concerns local development only: the release images do not contain
Aspire.
Changed
- The cache is named Valkey throughout. The multi-container image reads the cache address from
VALKEY_ADDRESS;
the oldREDIS_ADDRESSstill works. - Step-up during onboarding. When step-up authentication is on, the onboarding pages ask for a fresh sign-in
instead of failing. - Issue forms on GitHub. Bug reports and feature requests use forms, and questions go to the
Q&A category of GitHub Discussions. Report a
vulnerability by email as SECURITY.md describes, never in a
public issue.
Verified for this release
- Full test suite, local CodeQL (security and code quality) and the security scan of both layouts, with the browser
check in Chromium, Firefox and WebKit. - Upgrade from 1.0.0-rc7 on the same data volume.
- The post-quantum compatibility matrix on x86_64 as well as arm64: all 33 Linux cells give the same verdict on both
architectures, and the .NET cell now has a Linux x64 run. - TPM secret storage on real hardware in both layouts, as a non-root user: one x86_64 firmware TPM 2.0 (Microsoft
Pluton). Clearing or replacing a TPM was tested on software TPMs only. Discrete TPM chips, other firmware TPMs and
arm64 are untested. - Step-up with Keycloak 26.8.1: the web UI's reauthentication works. The tested Keycloak device flow does not
produce the required MFA level, soqcastep-up against Keycloak is refused; see
Identity Providers.
Upgrading
- Back up
/datafirst. This release adds no database migration over 1.0.0-rc7. - Multi container: refresh your copy of
deploy/multi-container/from this release before
docker compose up -d. The data initializer is now the containerqertum-data-init, and the backup and restore
wrappers take the volume from it. With the bind override, refreshdocker-compose.bind.ymltoo. - Access tokens of the built-in identity provider now last 10 minutes; the web UI and
qcarenew them on their own. - Every change is listed in Upgrading.
Qertum 1.0.0-rc7
Qertum 1.0.0-rc7
Security
- CA certificates cannot be relabelled as leaf certificates. A request's certificate type can now
change only while the request is Pending or Rejected. Attempts to change the type later return HTTP 409.
This closes a path that could otherwise bypass the permission required to revoke a CA certificate. - CRL publication is safe under concurrency. Full and delta CRLs coordinate publication with revocation
writes, reserve distinct CRL numbers and prevent an older snapshot from replacing a newer one. A partial
cache failure cannot cause an already published CRL number to be reused. - Public CRL endpoints are protected from repeated cache misses. Full and delta CRLs use the same
per-caller API rate limit as certificate requests and OCSP. Concurrent misses for the same CRL share one
build. Anonymous callers are identified by their client address. - Certificate request sizes are bounded. REST create and update accept at most 100 subject alternative
names in total and 65,536 characters inpropertiesJson. EST CSRs accept at most 100 DNS names.
Changed
- Release-matched architecture diagram. The README and wiki include a complete SVG overview of the
services, integrations, key protection and manual CA trust hierarchy. Each release's wiki snapshot keeps
the matching diagram. - Dependencies and base images refreshed. OpenIddict, Scalar, StackExchange.Redis, OpenTelemetry
instrumentation and the Aspire development SDK are updated. The container base-image digests are refreshed;
the .NET runtime remains on the 10.0 servicing line.
Upgrading
- Back up
/databefore upgrading. This release adds no database migration over 1.0.0-rc6. - CRL and OCSP fetches now share the certificate-request quota: by default, 100 requests per caller per
60 seconds, with a queue of 10. Fetchers that poll frequently can receive HTTP 429; review their frequency
and your configured rate limit before upgrading. - Certificate request type changes and input sizes are subject to the limits above. Existing issued
certificates are not modified by the upgrade.
Qertum 1.0.0-rc6
Qertum 1.0.0-rc6
Security
- A CA certificate is issued only when it was approved as one. Approval checks the
certificates.ca
permission and the independent-approver rule when the request's template can sign certificates, but the
issuing worker used the template as it was at signing time. Someone allowed to edit templates could add
KeyCertSignto the template of an already approved leaf request and have a subordinate CA certificate
issued that nobody with the CA permission approved. Approval now records whether a request was approved as a
CA certificate, and the worker refuses to sign a CA-capable template for a request that was not, rejecting
it without retry. Automatic approvals (ACME, EST, auto-renewal) never count as a CA approval.
New
-
Releases are signed. The container images on Docker Hub, Quay and GHCR carry a cosign signature, and
SHA256SUMSis signed inSHA256SUMS.sigstore.json, which covers the deploy bundle, theqcabinaries, the
SBOMs and the third-party notices. The keys live in YubiKeys and cannot be exported; the public keys are in
signing/of the source. Signatures are recorded in the public Sigstore transparency log. See the wiki page
Verify a Release:cosign verify --key signing/qertum-release-primary.pub qertum/qertum:1.0.0-rc6 cosign verify-blob --key signing/qertum-release-primary.pub --bundle SHA256SUMS.sigstore.json SHA256SUMSEarlier releases are not signed.
-
Compliance documentation for operators. A new wiki page lists the personal data Qertum keeps and for how
long, how to handle erasure requests given the tamper-evident audit log, and gives a record-of-processing
template and notes on DPIA, NIS2, eIDAS and the Cyber Resilience Act. The Configuration Reference has a new
Retention table.
Fixed
- Single container: the web UI reaches the API when the API port is remapped. With the API published on
another host port (for example-p 9082:8082 -e API_PORT=9082), every page answered
Unable to load dashboard. Connection refused. The web UI now calls the API on the port it listens on inside
the container. - Images include Ubuntu's latest security updates. The .NET base image still carried
apt3.2.0
(CVE-2026-109518); the images now apply pending Ubuntu updates when they are built. - Issuers page: row actions stay on the page. At smaller window widths the actions of an issuer ran past the
right edge; they now wrap.
Changed
- Support is provided as is. Qertum is free open-source software under the MIT licence with no paid support.
SECURITY.mdandSUPPORT.mdnow say that security fixes are made on a best-effort basis, with no guaranteed
response or fix time.
Upgrading
- One database migration is added. The API service applies it at start. Back up the data volume first.
- A CA certificate request (a subordinate CA template) that is approved but not yet signed when you upgrade is
rejected after the upgrade, because it carries no record of a CA approval. File it again and have it approved.
Requests that are already issued are not affected.
Qertum 1.0.0-rc5
Qertum 1.0.0-rc5
Breaking changes
- Browser, identity and API ports bind to host loopback in both compose layouts. Use a TLS proxy for remote
access. Multi-container plain HTTP additionally requires an explicitQERTUM_ALLOW_INSECURE_HTTP=truelab
opt-in; see the TLS proxy setup before recreating containers. - Multi-container web and identity now mount only their own state. Keep the existing named volume/project;
existing bind installations must adddocker-compose.bind.yml. No data is moved or deleted. Named subpaths
require Docker 26+ and Compose 2.35+; the bind override requires Compose 2.24.4+. qca est credentials create --passwordand-pare refused. Use the hidden terminal prompt or pipe a password
from a secret manager with--password-stdin.- EST certificate-based re-enrollment requires an active certificate issued through EST with explicit TLS client
authentication and signing usage. The default WebServer template has serverAuth only: configure a dedicated
client-authentication EST template and bootstrap older devices again with credential-based/simpleenroll. - Public ACME catch-all CIDRs no longer admit internal addresses. Add explicit internal ranges for intended
private enrollment. Metadata/link-local addresses remain blocked unconditionally.
Fixed
-
Identity password hashes and client secrets are readable by the file owner only on Unix. The identity
service creates temporary files with mode 0600 before writing hashes or OIDC client secrets, then replaces stores
atomically. It uses a new, exclusively created temporary path for every write, so a pre-existing
symbolic link cannot redirect the write. Startup repairs permissions on existingusers.json,clients.json
and one-time API secret files without replacing users, passwords or client secrets. -
Anonymous OCSP requests have a caller quota. GET and POST on both OCSP aliases share the existing
certificate-request rate limit; excess requests receive 429 before parsing, lookup or response signing. -
Interactive navigation enforces page permissions. The web router now evaluates declared role and policy
requirements inside an existing circuit and after permission changes. -
EST re-enrollment requires an enrollment credential certificate. Other CA certificates and certificates
pending revocation cannot bypass enrollment credentials. The presented certificate must match the stored EST
certificate, permit client authentication, chain to a trusted issuer, and have Good revocation status. -
ACME public validation cannot implicitly probe private hosts. Broad CIDRs require an additional explicit
internal range before a private or loopback address can be reached. -
Web and identity containers cannot read CA state. Each mounts only its own state subdirectory; the CA
hosts retain their shared signing/database state and backups retain the existing layout. -
Web and identity sessions use separate cookie names. Signing in to one service no longer replaces the
other service's cookie when both use the same host on different ports. -
Sign-in over plain HTTP on a LAN address works. The web UI no longer forces a Secure session cookie on
an HTTP deployment. -
Licence notices ship with the product. Every image carries
LICENSEandTHIRD-PARTY-NOTICES.txtin
/usr/share/doc/qertum/; theqcaLinux archives carry both besideqca, and the release has
THIRD-PARTY-NOTICES.txtas an asset of its own. The notices list every bundled .NET package, web asset, font and
the .NET runtime with their licences. -
The shared cache is Valkey instead of Redis. Redis 8 is offered only under RSALv2, SSPLv1 or AGPLv3, which
does not fit an MIT-licensed product image. Valkey 9.1 (BSD-3-Clause) is Redis-compatible and holds the same
regenerable data (published CRLs, ACME nonces). The single container runsvalkey-server; the multi-container
cacheservice uses thevalkey/valkeyimage. Nothing is migrated: the cache is not persisted and refills on
first use. -
The browser tab shows the Qertum icon everywhere. A 32x32 icon sits beside the SVG one for browsers that do
not use an SVG icon.
Upgrading
- No database migration is added by these fixes. Back up the data volume before upgrading.
- Run the identity service as the owner of its data files, so it can repair Unix permissions. Windows continues
to use the data directory's inherited ACLs. Earlier copies and backups retain their old permissions. - The session-cookie names changed; sign in again after upgrading.
- Protect the one-time password output from
qca est credentials create, including JSON output. - Email and UPN policy restrictions introduced in rc4.3 limit domains, not individual user identities. Approvers
must still verify that the requester may use each requested identity.
Scan follow-up
The earlier root-renewal, email/UPN policy and logout reports were checked against rc4.3 and retain their existing
fixes. A fresh scan of that snapshot reported eight additional issues; the changes above address those paths with
focused regression coverage. A new AI Scan of the released source is still needed to confirm the service's results.
Qertum 1.0.0-rc4.3
Qertum 1.0.0-rc4.3
An interim release with fixes for findings from code scanning of the rc4.2 source. Two database migrations add
columns at start; a few things behave differently, listed under Upgrading.
Breaking changes
- Multi container with
QERTUM_SCHEME=https: the identity service refuses plain HTTP on its own port. Through
the TLS proxy nothing changes. Before, the published identity port also accepted plain HTTP in https mode, so
passwords and tokens could cross the network unencrypted. To keep the old behaviour set
IdentityService__DisableTransportSecurity=true. - CA certificates issued from a template have a path length of 0. A certificate from a template that can sign
certificates (for example SubordinateCA) signs end-entity certificates only. For a CA that issues further CAs,
use the issuer ceremony (qca issuers create-intermediate), which also sets name constraints. Certificates issued
before are unchanged.
Fixed
- A CA renewal needs a second person. Renewing the root skipped the independent-approver rule, and a renewal
keeps the original requester as its owner, so whoever filed a CA renewal could approve it alone. The renewer is now
recorded and cannot approve, for the root and for subordinate CAs. - Policies can restrict email and UPN entries. New rules list allowed email domains and allowed UPN suffixes.
Before, a template that issues them (the built-in ClientAuth) took any UPN typed, and a client-authentication
certificate with someone else's UPN signs in as them. Requests must also give both aslocal@domain. - Account changes by an administrator are no longer undone by the user. A profile or password change, or the
sign-in that upgrades a stored password hash, could put back a user an administrator had just deleted, disabled,
changed roles for or reset. - Sign-in has a limit per client address, 100 failed attempts in 15 minutes across all user names, so trying a
new user name every time is no longer unlimited. Successful sign-ins do not count. - Signing out of the identity service needs the user's intent.
/connect/logoutsigns out at once only with
the signed-in user's own ID token as a hint (which the web UI sends), otherwise it asks. qca root initwrites the root key readable by its owner only, in a folder only the owner can open.qca root signcannot be made to overwrite the root certificate. It refuses a request namedrootor
chain, never overwrites an earlier certificate file, and shows the file it will write before asking.
Upgrading
- Back up
/datafirst, then pull the new tag. The upgrade from rc4.2 was tested. The two migrations add columns;
existing policies keep issuing as before (the new rules start empty, which means unrestricted). - Read Breaking changes above if you run the multi container behind a TLS proxy or issue CA certificates from
a template. - Renewing the root through the shared renew route now needs a second approver unless an administrator has waived
the rule (qca ca approval set waived). - An application other than the Qertum web UI that sends users to
/connect/logoutwithout anid_token_hintnow
shows them a confirmation page. - Coming from rc4.1 or earlier: read the rc4.2, rc4.1 and rc4 notes too (rc4 has two breaking changes).
Known limits
- The images and the
qcafiles are not signed yet. Signing and build provenance come with the next release;
every release already carries a CycloneDX SBOM per image and checksums. qcafor Windows was run on Windows x64 (--version); sign-in and API commands were exercised on Linux only.
Windows on Arm and macOS have no build of their own.- With
QERTUM_HOST=localhostand remapped host ports, the single container's API refuses every token; use a
host name or IP address, or keep the published ports at 8080-8083 (see Troubleshooting in the wiki). - A root CA that was imported, rather than generated in Qertum, cannot be renewed in Qertum.
- Step-up authentication has been tested against Keycloak and a claim-mock server only. The web UI is tested in
Chromium, Firefox and WebKit; Safari itself is untested. - TPM-backed secret storage has been run on one x86_64 TPM 2.0 only.
- Composite ML-DSA follows an IETF draft and may change.
Qertum 1.0.0-rc4.2
Qertum 1.0.0-rc4.2
An interim release with twelve fixes for findings from code scanning of the rc4.1 source. No migration and no new
configuration; a few things behave differently, listed under Upgrading.
Fixed
- CA certificates are guarded on every route that reaches them. The routes every certificate shares reached CA
certificates with only the ordinary permissions: an operator could approve any request by editing its status,
renew and approve the root (which replaces the trust anchor), or revoke a CA certificate (which retires the
issuer and, by default, everything below it). Now a request's status changes only through approve, reject and
revoke; revoking a CA certificate and renewing the root needcertificates.ca; bulk operations leave CA
certificates out; and automatic renewal never renews the root. - Publishing a policy publishes exactly the reviewed draft. An edit saved at the moment of publishing could
become the published policy, unreviewed, under the publisher's name. - ACME account keys meet the key-size rule of certificate requests: RSA account keys under 2048 bits are refused.
- Sign-in can no longer be blocked for someone else. Failed attempts count per user name and client address,
with a looser per-user limit across addresses. - Unknown user names take as long as wrong passwords at sign-in and EST enrollment, so timing no longer shows
which user names exist. qcawrites downloaded private keys and PFX files readable by their owner only.- Signing out needs a form post from the web UI, so another site cannot sign you out with a link.
Upgrading
- Back up
/datafirst, then pull the new tag. The upgrade from rc4.1 was tested. PUT /v1/certificate-requests/{id}ignores astatusin the body; use approve, reject and revoke.- Revoking a CA certificate and renewing the root need
certificates.ca. Bulk operations leave CA certificates out,
so after an issuer compromise revoke each subordinate CA on its own. - An ACME client registered with an RSA account key under 2048 bits must register a new account.
- Signing out of the web UI is a form post; a link or bookmark to
/signoutno longer signs out. - Coming from rc4 or earlier: read the rc4.1 and rc4 notes too (rc4 has two breaking changes).
Known limits
- The images and the
qcafiles are not signed yet. Signing and build provenance come with the next release;
every release already carries a CycloneDX SBOM per image and checksums. qcafor Windows was run on Windows x64 (--version); sign-in and API commands were exercised on Linux only.
Windows on Arm and macOS have no build of their own.- With
QERTUM_HOST=localhostand remapped host ports, the single container's API refuses every token; use a
host name or IP address, or keep the published ports at 8080-8083 (see Troubleshooting in the wiki). - A root CA that was imported, rather than generated in Qertum, cannot be renewed in Qertum.
- Step-up authentication has been tested against Keycloak and a claim-mock server only. The web UI is tested in
Chromium, Firefox and WebKit; Safari itself is untested. - TPM-backed secret storage has been run on one x86_64 TPM 2.0 only.
- Composite ML-DSA follows an IETF draft and may change.
Qertum 1.0.0-rc4.1
Qertum 1.0.0-rc4.1
An interim release with four fixes for findings from code scanning of the rc4 source. No new features, no
configuration change, no migration.
Fixed
- Backup archives are readable only by their owner.
backup.shandbackup.ps1wrote the archive, which holds
the CA key, readable by every local user (mode 0644). It is now mode 0600 and owned by the user who ran the
script. Archives taken before rc4.1 keep their old mode: runchmod 600on them (or on the folder that holds
them) once. - One ACME external account key binds one account, also under load. Registrations sent at the same moment with
the same external account key could each get an account; now exactly one does and the others are refused with
unauthorized. - TPM storage never leaves the plain key readable. While sealing a new key, the TPM provider briefly wrote it to
a file other local users could read; secret files are now created readable by their owner only. - The standalone identity example listens on localhost only, matching its plain-http
localhostaddress. To
serve other machines, put a TLS proxy in front of it.
Upgrading
- Back up
/datafirst, then pull the new tag. Nothing else changes; the upgrade from rc4 was tested. - Run
chmod 600on backup archives taken before this release. - Coming from rc3 or earlier: read the rc4 notes first (two breaking changes: API clients must request the
qertum-apiscope, andQERTUM_TRUSTED_PROXIESis required behind a TLS proxy).
Known limits
- The images and the
qcafiles are not signed yet. Signing and build provenance come with the next release;
every release already carries a CycloneDX SBOM per image and checksums. qcafor Windows was run on Windows x64 (--version); sign-in and API commands were exercised on Linux only.
Windows on Arm and macOS have no build of their own.- With
QERTUM_HOST=localhostand remapped host ports, the single container's API refuses every token; use a
host name or IP address, or keep the published ports at 8080-8083 (see Troubleshooting in the wiki). - A root CA that was imported, rather than generated in Qertum, cannot be renewed in Qertum.
- Step-up authentication has been tested against Keycloak and a claim-mock server only. The web UI is tested in
Chromium, Firefox and WebKit; Safari itself is untested. - TPM-backed secret storage has been run on one x86_64 TPM 2.0 only.
- Composite ML-DSA follows an IETF draft and may change.
Qertum 1.0.0-rc4
Qertum 1.0.0-rc4
The fourth release candidate. These are the changes since 1.0.0-rc3: two security fixes found by code scanning of
the rc3 source, both of which change how a deployment is set up (see Breaking changes), the encryption key ring
now actually encrypted on disk (found while testing TPM storage), console log hardening, and code-quality work with
no change in behaviour.
Breaking changes
- The API accepts only tokens issued for it. An access token from the built-in identity provider now carries the
API audience (qertum-api) only when the client requested theqertum-apiscope. Before, every token carried it,
so a client that asked only for the user's profile (openid profile) could still call the API with the user's
roles. A client that calls the API without requesting the scope now gets 401 Unauthorized: add
scope=qertum-apito its token request and make sure itsclients.jsonentry permits that scope. The web UI,
qcaand the automation snippets in the web UI already request it, so they need no change. Tokens issued before
the upgrade stay valid until they expire (about an hour); a refresh token issued without the scope keeps
returning tokens without the audience, so sign in again. Another OpenID Connect provider is not affected: its
audience comes from its own settings. - Behind a TLS proxy, name the proxy. With
QERTUM_PUBLIC_SCHEME=https(single container) orQERTUM_SCHEME=https
(multi container), setQERTUM_TRUSTED_PROXIESto the proxy's IP address or network, comma-separated for several,
for example the subnet of the Docker network it shares with Qertum. Web, identity and API accept
X-Forwarded-ProtoandX-Forwarded-Forfrom those addresses only; before, a client that reached their ports
directly could claim https (and pass the identity provider's https check) or another address (and escape the
per-address rate limit). Without the variable the container, or the web, identity and API containers, stop at
start (exit 64) with a message that names it. Plain http deployments are not affected. The standalone identity
image applies the headers only whenQERTUM_TRUSTED_PROXIESis set.
Fixed
- The encryption key ring is now encrypted on disk. The key ring in
/data/DataProtection-Keys, which protects
the CA key, stored private keys and webhook secrets, was written unencrypted by every earlier release: the local
file key or TPM chosen under Secret Storage was never applied to it, so a copy of/datawas enough to decrypt the
CA key. The first start of rc4 encrypts the existing files. Two faults that this had hidden are fixed with it: a
migration to another secret storage (for example to the TPM) built its new key in a folder it then deleted, and the
services of the single container, starting at the same moment, could each make a key of their own. Tested on a real
TPM 2.0: a CA on the file key, migrated to the TPM and restarted, keeps every key readable, and its data cannot be
opened without that TPM. - Console log forging. Text from requests (a common name, an issuer or policy name, a webhook URL, an ACME
identifier) reached the console log unescaped, so a line break in it could forge a second log line. Every
service now escapes control characters and Unicode line separators in logged values. The audit log was not
affected. - The README picture of the dashboard shows the loaded data instead of the loading spinner.
- Code quality. Every warning of the CodeQL code-quality analysis is fixed, mostly resource disposal and null
handling, with no change in behaviour. For code that uses the API client library:
CertificateRequestsApiClientis nowIDisposableand disposes theHttpClientit was given; pass
disposeHttpClient: falsewhen thatHttpClientis shared.
Upgrading
- Back up
/datafirst. rc4 adds no migration; the upgrade from rc3 was tested with certificates of every key kind,
a revoked certificate, pending and rejected requests: everything carries over, the audit hash chains continue,
and the offline restore check passes. - Backups taken before rc4 hold the encryption key ring in plain text, so they decrypt the CA key without the
file key or the TPM. Keep them as safe as the CA key itself, or take a new backup after the upgrade and delete the
old ones. - Check the two breaking changes above: API clients that request no
qertum-apiscope, and
QERTUM_TRUSTED_PROXIESbehind a TLS proxy. The wiki page "Upgrading" has both.
Known limits
- The images and the
qcafiles are not signed yet. Signing and build provenance come with 1.0.0; every
release already carries a CycloneDX SBOM per image and checksums. qcafor Windows was run on Windows x64 (--version); sign-in and API commands were exercised on Linux only.
Windows on Arm and macOS have no build of their own.- With
QERTUM_HOST=localhostand remapped host ports, the single container's API refuses every token; use a
host name or IP address, or keep the published ports at 8080-8083 (see Troubleshooting in the wiki). - A root CA that was imported, rather than generated in Qertum, cannot be renewed in Qertum.
- Step-up authentication has been tested against Keycloak and a claim-mock server only. The web UI is tested in
Chromium, Firefox and WebKit; Safari itself is untested. - TPM-backed secret storage has been run on one x86_64 TPM 2.0 only (single container, again for rc4).
- Composite ML-DSA follows an IETF draft and may change.
Qertum 1.0.0-rc3
Qertum 1.0.0-rc3
The third release candidate. These are the changes since 1.0.0-rc2: security fixes found by code scanning of the
rc2 source, the qca command line as a download, and a few fixes.
New
qcaas a download. Every release now carries the command line client as a single file that needs no .NET
install:qca.exefor Windows x64, andqca-linux-x64.tar.gzandqca-linux-arm64.tar.gz, each holding the executable
qca, all listed inSHA256SUMS.
qca --versionprints the release and its source commit. The files are not signed with a code-signing
certificate, so Windows SmartScreen may warn the first time; check the file againstSHA256SUMSand choose
More info, then Run anyway. macOS builds are not published yet. Download and install steps are on the
wiki page "Using the CLI".
Fixed
- Security fixes from code scanning of the rc2 source:
- the private key of the second certificate of a paired request (hybrid, or signing + encryption) was stored
unencrypted in the database; it is now encrypted like every other private key, and the first start of rc3
encrypts the ones already stored; - a certificate template with the type key
RootCAlet a requester file a root CA request through the ordinary
request route, without the permission, step-up or independent approval that creating a CA needs; the type is
now reserved; - a common name in an EST request could add extra subject fields (for example
O=) to the issued certificate;
the subject is now built field by field; - ACME and EST accepted RSA keys of any size; keys shorter than 2048 bits, or with a public exponent below
65537, are refused; - the webhook list returned each webhook's signing secret; the secret is now write-only (the list says whether
one is set); - the public OCSP endpoint read request bodies of any size into memory; bodies over 64 KiB are refused;
- the device sign-in confirmation page (
qca auth login) could be submitted from another page on the same site,
and did not encode the user name and code it shows; qcastored its session tokens in a file other local users could often read; on Linux and macOS it is now
readable by its owner only, andqca auth loginopens only web addresses;- an unexpected server error returned the internal error text; it now returns a fixed message and the
correlation id.
- the private key of the second certificate of a paired request (hybrid, or signing + encryption) was stored
- Certificate templates are checked when they are saved: key usages, extended key usages, name types and custom
extensions must be valid. A template saved earlier through the API with a value that cannot be read used to
issue certificates without that extension; its requests are now rejected with a reason that names the field. - Saving a template in the web UI no longer erases its custom extensions.
GET /v1/certificate-requests/{id}/private-keyand.../certificatework without?pqc=, as documented.- Issuers: row actions confirm in a dialog, and their buttons are spaced. Policies: a refused publish shows
its reason beside the button.
Upgrading
- Back up
/datafirst. rc3 adds no migration. Its first start encrypts the stored private keys of paired
certificates (the API log says how many); downloads return the same keys as before. - Backups taken before rc3 still hold those keys unencrypted. Keep them as safe as the keys themselves, or take
a new backup after the upgrade and delete the old ones. - A template with the type key
RootCA(only possible through the REST API orqca) no longer accepts requests;
create one under another type key. CSRs with RSA keys under 2048 bits are refused. Webhook listings no longer
return signing secrets.
Known limits
- The images and the
qcafiles are not signed yet. Signing and build provenance come with 1.0.0; every
release already carries a CycloneDX SBOM per image and checksums. qcafor Windows was run on Windows x64 (--version); sign-in and API commands were exercised on Linux only.
Windows on Arm and macOS have no build of their own.- With
QERTUM_HOST=localhostand remapped host ports, the single container's API refuses every token; use a
host name or IP address, or keep the published ports at 8080-8083 (see Troubleshooting in the wiki). - A root CA that was imported, rather than generated in Qertum, cannot be renewed in Qertum.
- Step-up authentication has been tested against Keycloak and a claim-mock server only. The web UI is tested in
Chromium, Firefox and WebKit; Safari itself is untested. - TPM-backed secret storage has been run on one x86_64 TPM 2.0 only.
- Composite ML-DSA follows an IETF draft and may change.
Qertum 1.0.0-rc2
Qertum 1.0.0-rc2
The second release candidate. These are the changes since 1.0.0-rc1.1.
New
- Renew an intermediate CA. Issuers, Renew (or
qca issuers renew <id>,POST /v1/issuers/{id}/renew)
gives an active or revoked intermediate a new key under the same name, subject, algorithm, constraints and
parent. The renewal takes the old intermediate's place: the default seat and every template pinned to it. A
live old intermediate is retired, not destroyed, so its CRL and OCSP keep answering. When Qertum holds the
parent's key it finishes at once; under an offline root or an external CA it goes through the same request file
and install as creating an intermediate. An imported intermediate's renewal must be signed by the CA that
issued the old one. After a root renewal, renewing an intermediate signs it under the new root. - Renewing a root CA gives it a new key and makes it the default as soon as the renewal is signed; a live old
root is retired, never destroyed. Before, approving a root renewal handed back the old certificate. Renewal is
also the way back after the root certificate was revoked. A renewed CA keeps its name; serial, thumbprint and
dates tell the two apart. - Show only valid certificates. All Certificates and Issuers hide, by default, what can no longer be used:
expired, revoked or revoking certificates, anything signed under a CA whose certificate is revoked or expired,
and archived or destroyed CAs. A renewed certificate stays until it expires, so the overlap with its renewal is
visible. The API takesvalidOnly=true; without it the lists are unchanged. - A new look. The web UI and the sign-in pages use the Qertum brand: dark, flat surfaces, a mint accent,
Space Grotesk headings and monospace labels. Fonts and icons are served by Qertum itself, so the UI makes no
request to another site and works offline. - https public URLs behind a TLS proxy (
QERTUM_PUBLIC_SCHEME=httpsfor the single container,
QERTUM_SCHEME=httpsfor the multi-container layout). Plainhttpstays the default and now logs a warning
at every start, because sign-in, tokens and the admin password then cross the network unencrypted. - After a revoked CA certificate the web UI stays usable. An administrator is no longer forced into
onboarding; a banner offers Renew it (the root's certificate page, or the Issuers page for an intermediate)
and Set up a new CA. Revoking a CA certificate, root or intermediate, warns first what it stops.
Fixed
- Sign-in behind a TLS proxy never worked in either image: the identity service saw the proxy's plain-http hop
and refused every request. In https mode the web UI, identity service and API now honour the proxy's
X-Forwarded-*headers; ACME and EST never do. Expose those three ports to the proxy only. - Security fixes from a security scan and from code scanning:
- malformed or unsigned ACME requests answered 500 with the .NET exception text; they now answer 400 with an
ACME error type, and server errors no longer echo internal messages; - every service now sends
X-Content-Type-Options,Referrer-Policy,X-Frame-Optionsand a
Content-Security-Policy (the web UI and sign-in pages allow scripts from Qertum itself only); - the API rate limit was one window shared by every caller; it is now one window per caller;
- the sign-in redirect no longer announces the identity library's version;
- audit entries are written one line per value, so a name taken from a request cannot forge a log line;
- the EST HTTPS requirement now checks the connection's own TLS handshake;
- a TPM tool call broke on a data path containing a space;
- the bootstrap password is no longer written to the log.
- malformed or unsigned ACME requests answered 500 with the .NET exception text; they now answer 400 with an
Upgrading
- Back up
/datafirst. Starting 1.0.0-rc2 on an rc1.1 volume applies two migrations: issuer names are no longer
unique (a renewed CA keeps its name) and issuers record which issuer they renew. There is no downgrade; the
rollback is the backup restored with the previous image. Existing CAs, certificates, the CRL, sign-in and the
audit log carry over unchanged, and the audit hash chains continue across the upgrade. - Set
QERTUM_HOSTto the public address, exactly as users type it in the browser, with no NAT, DNS alias or
proxy name in between: sign-in accepts only that address. Behind a TLS proxy, also set
QERTUM_PUBLIC_SCHEME=https(orQERTUM_SCHEME=https).
Known limits
- The images are not signed yet. Signing and build provenance come with 1.0.0; every release already carries
a CycloneDX SBOM per image and checksums. - With
QERTUM_HOST=localhostand remapped host ports, the single container's API refuses every token; use a
host name or IP address, or keep the published ports at 8080-8083 (see Troubleshooting in the wiki). - A root CA that was imported, rather than generated in Qertum, cannot be renewed in Qertum.
- Step-up authentication has been tested against Keycloak and a claim-mock server only. The web UI is tested in
Chromium, Firefox and WebKit; Safari itself is untested. - TPM-backed secret storage has been run on one x86_64 TPM 2.0 only.
- Composite ML-DSA follows an IETF draft and may change.