Security
Each of these was found by the hMailServer project (Progressive Robot Ltd) and, but for the last, is fixed in 6.3.8; each work item is public now, and each has a CVE request through GitLab's CNA. Between them they reach back to 6.0.0's first beta. The 6.3.8 section of CHANGELOG.md at the tag gives each, with how it is tested. Upgrade every server running 6.3.7 or earlier.
- CVE requested (work item 112):
TlsMode=verify-full on MySQL and MariaDB checks the database server's certificate against the file TlsCaFile names when that name holds a character outside ASCII (on Linux any, on Windows one above U+00FF), where the client was given no CA file at all and checked the certificate against the system's trust store, with some versions of MariaDB Connector/C less than that, while the log and the diagnostics said it had been checked; 6.3.4 to 6.3.7. Its entry corrects what 6.3.7's notes said of a named TlsCaFile as the mitigation for CVE-2026-107819, MariaDB Connector/C's own flaw: it did not hold for such a name. - CVE requested (work item 113):
TlsMode=verify-full without TlsCaFile, on a connection that MariaDB Connector/C 3.4.1 or later takes as one to this machine, checked neither the database server's certificate's issuer nor its name; 6.3.4 to 6.3.7. It is now refused, with HM7535 (the notices above). Connector/C 3.3 and 3.4.0 and Oracle's MySQL client were not affected. - CVE requested (work item 114): on Windows, a root certificate's name (PostgreSQLSslRootCert, or TlsCaFile with
TlsMode=verify-full) whose bytes in the ANSI code page outside ASCII also read as UTF-8 could make the database's client check the server's certificate against another file than the one named; 6.2.25 to 6.3.7. Such a name is now refused with HM7534. The bundled MariaDB Connector/C and the Linux builds were not affected. - CVE requested (work item 115): on Windows, the files the server hands to OpenSSL by name (the TLS certificates' certificate and private key files, dh2048.pem, a port's client-certificate CA file, MessageStoreObjectCaFile and the files in AcmeCertificateDirectory) could, under a name with some characters outside ASCII, be read from another file than the one configured; every release up to and including 6.3.7. Each is now read from the file configured, or refused with HM7536.
- CVE requested (work item 116): on Windows, the bundled MySQL and MariaDB client, MariaDB Connector/C, loads its authentication plugins from the installation's own plugin folder, one that only administrators control, or from none.
- CVE requested (work item 100): the database layer's test for the marker that lets a statement's error be ignored, and the log's and the trace's redaction of a statement's literals, read a literal as each engine does.
- CVE requested (work item 102): the auto-ban saves the IP range it adds under a name of its own, so that it bans the address. Up to 6.3.7 a later ban for a long user name could take a range name in use, be refused (HM6099) and leave the address unbanned, its counted failures cleared all the same, so that it was given a whole new set of attempts.
- CVE requested (work item 104): a sign-in's name is matched to its account as the per-name lockout (from 6.2.22-pre2) and the compromised-account hold (from 6.3.4) count it. Up to 6.3.7 every spelling of a name that the database's own comparison took for the account signed in to it, each with a lockout threshold of its own, and an account held for review could be signed into under another spelling of its name with its password.
- CVE requested (work item 105): the web services listener (CardDAV, CalDAV, Autodiscover; off by default) did not refuse an address an auto-ban or an administrator's IP range banned, which could go on guessing passwords at its sign-in; it now closes such a connection with no answer, before the TLS handshake.
- CVE requested (work item 106): a failed sign-in at the web services listener through a proxy is no longer charged to the proxy's address, whose ban could shut the proxy, and every client behind it, out of the SMTP, POP3, IMAP and ManageSieve listeners; since 6.3.3 for CardDAV and 6.3.4 for CalDAV and Autodiscover.
- CVE requested (work item 107): a failed account sign-in at the REST listener through a reverse proxy on the same machine is no longer charged to 127.0.0.1, whose ban then refused loopback at the mail listeners; since 6.2.28. Until the upgrade, on 6.3.2 to 6.3.7, listing 127.0.0.1 and ::1 in AutoBanNeverBan avoids it.
- CVE requested (work items 110 and 111): the REST API, and the reader of a report mailed to a domain's report address, read a JSON body in time and memory that follow its bytes. From 6.3.2 an account's own password was enough to send the REST API a body that took far more time and memory to read than its size, in the service that also serves SMTP, IMAP and POP3, and from 6.3.4 the same was true of the reply to a password-protected message. A body of more than 100,000 values, an object of more than 10,000 members or more than 32 levels is now answered 400, the reply is held to 2 MB, and a TLS-RPT report is read through the bounded parse.
- CVE requested, one for each case (work item 78): on Windows, setup makes or hardens the program folder, Bin and ControlPanel before it copies a file or runs a program of the installation, and refuses a folder or a link on the way to them, or a program, library or script in them, that another account controls. These are the four narrower cases that 6.3.7's notes listed as still open: a new folder, a folder already there, a link on the way to them, and a program, library or script in them. In 6.3.7 an upgrade had the three hardened only at the end of setup, by /ProtectFolders, and setup installed through any link.
- CVE requested (work item 103): published with 6.3.8, the advisory for a flaw in the auto-ban on MySQL and MariaDB that 6.3.4 fixed.
The release notes' Security section has more beside these. The container image secures a new installation by itself, whatever the container's command, where a docker run of the image with its own command took passwords in the clear on every port, and its two passwords no longer reach the server's environment, nor that of anything it starts, nor does HMAILSERVER_RECOVERY_PASSPHRASE when the container runs the image's own command (hardening, not a flaw). A mailbox's recovery address can no longer be sent more password-reset links than the per-address limit allows by other spellings of the address, as it could from 6.3.4. On Linux a command run as root examines and opens the folders it will work in by the names the server uses for them, and hMailServer.exe /ProtectFolders says a key or certificate file that inherits a group of every user's Read as inheriting it.
One of these fixes, work item 100's, was public on GitLab from 19 October 2026 and on master from 20 October 2026, a week before it was judged a vulnerability, longer than the day SECURITY.md allows; the others were pushed with the release. The rule, that a security fix becomes public about a day before the release that ships it, holds again after 6.3.8 (SECURITY.md, "What gets a release").
What changes without a switch
The full list is the 6.3.8 section of CHANGELOG.md, under "What changes on upgrade without a switch", in 29 items. Beside the notices above, in short:
- Stops: work that outlasted a stop of the servers, a reinitialise among them, writes a line to the debug log where it wrote HM5136 or another code to the error log, so the error log of a server that reinitialises may be quieter; a database connection such a call held goes back to the pool; and on Linux a session or a task that went on after a stop no longer ends the process.
- ACME: a name no certificate can carry (a wildcard, an IP address, a name past ASCII not in its xn-- form) is left out of the check and the order and named in the application log, where it failed every order; a CA's rateLimited answer holds every order until its Retry-After; an ACME URL that is not https is refused unless it is to this machine; and the certificate a CA sends is installed only when it is for the request's key, names every host asked for and has not expired.
- The auto-ban's ranges: a ban for a long user name is named with the user name cut so that the name and its suffix fit the column, and POST
/api/v1/ipranges reads a name in UTF-8, as PUT does. - Failed sign-ins through a proxy: from loopback or an address in WebServicesTrustedProxies at the web services listener, and from loopback at the REST listener, a failed sign-in is counted against the name alone (AccountLockoutThreshold, off by default, is then the limit on the guesses at one account), never towards a ban of the address.
- Sign-in names: the IMAP master user's own hold, country policy and lockout are asked of its own address as well; the account.locked webhook is raised only for a locked name that is an account's own; and POST
/api/v1/password-reset counts its per-address limit under the address as a sign-in compares it. - The logs: the slow-query line and the trace's db.statement read a literal as the configured database does, so a line may differ from before, and --check-database's settings line and the connection lines say what the database client checks.
- spamd and Blowfish: spamd's User: header carries a name outside ASCII, where it was left out, and a name it cannot carry is sent as no header with HM5514 (new); the legacy Blowfish scheme refuses a secret it cannot carry (HM7278, new), where it wrote an empty one, and a backup's XML leaves such a secret out and names it (HM7280, new), to be entered again after a restore.
- Argon2id: GET
/api/v1/status's argon2id and post_quantum_key_exchange say what the library the server runs with does, and an app password raised to Argon2id where that library has none is made with scrypt and said once (HM5607), where it was an empty hash the store refused. - On Linux, hmailserver --create-database asks first whether the schema's version table is there, so a new installation no longer logs HM5033 as its first error; on Alpine a log line holding a character outside ASCII is written, where it came out empty.
- The Control Panel's Logging page shows a destination never chosen as Files on disk, its Anti-spam page opens and saves a refuse threshold at or below the mark threshold, the Anti-spam overview reads the quarantine switch, and the ACME page and the Setup checklist read AcmeDomains as the server does. The PowerShell module says why a call got no answer, and hmctl takes a file that begins with a byte order mark and refuses a body holding NaN or Infinity.
What is new
- A host added to AcmeDomains no longer waits for the renewal, some sixty days, and a check can be asked for (work item 98). A certificate that does not name every host on the list is now due at once, a save of AcmeDomains in the running server starts the check, and GET
/api/v1/acme and POST /api/v1/acme/run (COM Utilities.GetAcmeStatus and Utilities.RunAcmeCheck, and a card on the Control Deck's Certificates page) give the certificate's state and ask for a check, with the CA's rate limits and a pause after a failed attempt kept (Acme.md). - An event after an IMAP move, for scripts (work item 109): OnIMAPMessageMoved is called once for each message an IMAP MOVE or UID MOVE moved between two folders of the account signed in, after the command and off the IMAP thread. Off as shipped: IMAPMessageMovedEvents switches it on.
- Rspamd learns from the Junk folder, beside SpamAssassin (work item 108). A message a user moves into Junk is taught as spam, and one moved out as ham, to the filter MoveLearningBackend names, SpamAssassin by default; nothing is sent to Rspamd until it is chosen and its controller and classifier are set (
JunkFolderLearning.md). - The Linux server reaches clamd over its Unix socket: ClamAVHost takes the absolute path of clamd's LocalSocket in place of a host name (
ClamAV.md). - New ways to install: an Ansible collection, progressiverobot.hmailserver (
Ansible.md); a Kubernetes operator for Operator Lifecycle Manager and OperatorHub.io; and a container on Proxmox VE with one command on the host (Proxmox.md). Known issues, below, says where each stood when 6.3.8 was published. - The release's provenance is held to the pipeline that publishes it and to what GitLab certified of the run, and the documents say its SLSA level, Build L1 and no higher.
- Who made what: the packages, the image, the chart, the snap and the command-line clients say that they are Progressive Robot's fork of hMailServer and credit the original's author, Martin Knafve, and the tree is REUSE-compliant, with a CI job that holds it.
Reported from outside and answered besides: on-demand ACME issuance (work item 98), Rspamd learning from the Junk folder (work item 108) and an event after an IMAP move (work item 109), each asked for by ThiagoES84. Thank you.
Downloads
The release carries 62 files, each with its Sigstore bundle, <file>.cosign.bundle, beside it, and each file but a <file>.cdx.json SBOM has that bundle a second time as <file>.sigstore.json, the name Sigstore's own clients look for; with the bundles, the provenance and the provenance's envelope, 161 files.
- Windows:
hMailServer-6.3.8-x64.exe, and hMailServer-6.3.8-arm64.exe for Windows on ARM, both Authenticode-signed by Progressive Robot Ltd. The ARM64 installer is a preview: it is cross-compiled on the project's x64 Windows runner and has never run on ARM64 hardware. SQL Server Compact has no ARM64 build, so a new ARM64 installation is set up against SQL Server or PostgreSQL (WindowsOnArm.md). - Linux, x86-64 and AArch64: the generic
hmailserver_6.3.8_amd64.deb, hmailserver_6.3.8_arm64.deb, hmailserver-6.3.8-1.x86_64.rpm and hmailserver-6.3.8-1.aarch64.rpm, the names an installed server's update check asks for; and each Debian 12 and 13, Ubuntu 24.04, Fedora 44 and 43, Enterprise Linux 10 and 9, openSUSE Leap 16.0 and Tumbleweed release's own package for both architectures, named hmailserver_6.3.8-1~<release>_<arch>.deb or hmailserver-6.3.8-1.<release>.<arch>.rpm. The generic .deb does not install on Debian 12, nor the generic .rpm on Enterprise Linux 9: each takes its own release's package. The AArch64 files are cross-compiled and tested under emulation: no AArch64 machine has run them. - The AppImages,
hMailServer-6.3.8-x86_64.AppImage and hMailServer-6.3.8-aarch64.AppImage, and beside them the source of the libraries they carry and of those their runtime links, hmailserver-6.3.8-appimage-bundled-sources.tar.gz and hmailserver-6.3.8-appimage-runtime-sources.tar.gz. - The source tarball, hmailserver-6.3.8.tar.gz; the Helm chart, hmailserver-chart-6.3.8.tgz, the first published chart that starts a server; and the PowerShell module, HmailServer.psd1 and HmailServer.psm1, Authenticode-signed.
- An SBOM for each compiled file and the tarball, <file>.cdx.json, and the source tree's two,
hmailserver.spdx.json and hmailserver.cyclonedx.json; hmailserver-linux-6.3.8-SHA256SUMS.txt, the SHA-256 of every Linux file; and, beside the 62, hmailserver-6.3.8.intoto.sigstore.json, SLSA v1 build provenance that names each of them by its SHA-256. - New in 6.3.8,
hmailserver-6.3.8.intoto.jsonl: the DSSE envelope inside the provenance's Sigstore bundle, the statement and its one signature byte for byte as the bundle has them, written alone as one line of JSON. It is not a second signature, and it carries neither the certificate nor the transparency log's entry, which only the bundle carries: the bundle is the file to verify with.
The container image, registry.gitlab.com/hmailserver/hmailserver:6.3.8, also tagged 6.3 and latest, for linux/amd64 and linux/arm64, is pushed from this release's own pipeline once the release is published, by a job started by hand, as 6.3.6's and 6.3.7's were; it carries MariaDB Connector/C beside PostgreSQL's client. In the container the update check names the image to pull and installs nothing. ContainerImage.md, "Checking an image", gives the cosign verify command and the check of the project's id. The chart is also in the project's Helm repository, https://updates.progressiverobot.com/helm/.
The channels are sent 6.3.8 by jobs started by hand on master once the release is published, each verified against the release's bundles: the Ubuntu PPA, Fedora Copr, Docker Hub, Chocolatey (a version is listed once its moderators have approved it), PyPI and the PowerShell Gallery; the openSUSE Build Service once its package holds this release's new _service, keeping 6.3.7 until then; and the snaps, to the Snap Store's edge and candidate channels, stable being promoted by hand. 6.3.8's snaps are the first there, since 6.3.7's were never uploaded (Channels.md).
https://updates.progressiverobot.com/download/ leads to the newest stable release's page, and updates.progressiverobot.com/download/hMailServer-x64.exe, /download/hmailserver_amd64.deb, /download/hmailserver.x86_64.rpm and the rest of the download links UpdateFeed.md lists to that file of it, never to a pre-release; add .cosign.bundle for the bundle.
Verification
Every file is signed with Sigstore by the project's GitLab CI pipeline for the tag v6.3.8, and was checked before publication with hmailserver --verify-update, built from the same commit, 3a2fc29b7fb52a27e7c1a6b8e25c99d94a4756ba. The certificate's identity is https://gitlab.com/hmailserver/hmailserver//.gitlab-ci.yml@refs/tags/v6.3.8, its issuer https://gitlab.com, and it carries the project's id, 86730559. With cosign and OpenSSL, and the file and its bundle beside you, the first command must say Verified OK, and the second must print ..86730559, the project's own id, which cosign does not check, since the identity is a path and a path could pass to another project were the group or the project renamed or deleted:
cosign verify-blob --bundle hMailServer-6.3.8-x64.exe.cosign.bundle \
--certificate-identity 'https://gitlab.com/hmailserver/hmailserver//.gitlab-ci.yml@refs/tags/v6.3.8' \
--certificate-oidc-issuer https://gitlab.com hMailServer-6.3.8-x64.exe
jq -r .verificationMaterial.certificate.rawBytes hMailServer-6.3.8-x64.exe.cosign.bundle \
| base64 -d | openssl x509 -inform DER -noout -text | grep -A1 1.3.6.1.4.1.57264.1.15
If your cosign has the --new-bundle-format option and does not use it by default, add it. Each file but a <file>.cdx.json SBOM also has its bundle a second time as <file>.sigstore.json; either name verifies the same way. From the source tarball, python3 build/ci/sigstore-certificate.py repository-id <file>.cosign.bundle reads the id as the server does and prints id=86730559. To check that a file is one this release's pipeline built, against its build provenance, which says Verified OK only when the file's SHA-256 is one the provenance names:
cosign verify-blob-attestation --new-bundle-format \
--bundle hmailserver-6.3.8.intoto.sigstore.json --type slsaprovenance1 \
--certificate-identity 'https://gitlab.com/hmailserver/hmailserver//.gitlab-ci.yml@refs/tags/v6.3.8' \
--certificate-oidc-issuer https://gitlab.com hmailserver_6.3.8_amd64.deb
That check takes the bundle, hmailserver-6.3.8.intoto.sigstore.json, not hmailserver-6.3.8.intoto.jsonl, which holds the same envelope without the certificate. Then sha256sum -c --ignore-missing hmailserver-linux-6.3.8-SHA256SUMS.txt must say OK for each Linux file you downloaded. On Windows, Get-AuthenticodeSignature on either installer must answer Valid, with a signer certificate for CN=Progressive Robot Ltd; the x64 installer's published SHA-256 is 4b9b9c3102cbed743f6c826289c54cec25c395d02208e55cdd3219187fbf8654 and the ARM64 installer's e5ce357b9ca4e013529898c5208d43895fec3a397b1a4defa4cd905ee9b7f27a. On Linux a server from 6.3.4 on makes the same check its live update makes, hmailserver --verify-update <file>, with the bundle beside the file. In a clone, git -c gpg.ssh.allowedSignersFile=.gitlab/allowed_signers verify-tag v6.3.8 must report a good signature by the key that file lists. The release's own notes, at https://gitlab.com/hmailserver/hmailserver/-/releases/v6.3.8 under Verification, give each file's SHA-256 and the certificate the pipeline was given; SECURITY.md, "Verifying a release", has the rest.
How it was checked
The tag's pipeline, https://gitlab.com/hmailserver/hmailserver/-/pipelines/3016341592, ran every gate before anything was published: the Windows suite, in two halves on the project's two Windows benches, 4,569 tests, 4,489 passed, 0 failed, 80 skipped; the Linux suite on one of the project's Linux runners, 2,749 tests, 2,374 passed, 0 failed, 375 skipped; the rebuild of the x86-64 server, .deb and .rpm byte for byte; the install of every Linux package in a clean container of its release, by that release's own package manager, the AArch64 ones under emulation, but for the generic x86-64 .rpm, which is built on Ubuntu and was installed on Fedora 44 with rpm --nodeps, its dependencies not resolved; the start of the generic x86-64 .deb and of the generic AArch64 .deb and .rpm against a database; the REUSE check; the static analysis, Semgrep and the dependency scan. It then checked every signature with the server's own verifier, hmailserver --verify-update, built from the same commit. The signed installer went through the installer smoke test: an upgrade from 6.3.7 passed 105 checks and a new installation 65, none failed. The published chart, installed from the project's Helm repository into a one-node cluster, started its pod with 6.3.8's image and answered SMTP with STARTTLS and the REST API over TLS.
Known issues
- The ARM64 installer has never run on ARM64 hardware: it is cross-compiled on the project's x64 Windows runner and remains a preview (
WindowsOnArm.md). The AArch64 Linux files are cross-compiled, and installed, the generic .deb and .rpm started as well, in the release's pipeline under emulation: no AArch64 machine has run them. If you install either, please say how it went, working or not, in an issue on GitLab. - The channels are sent 6.3.8 by jobs started by hand (Downloads, above). The Ansible collection was not on Ansible Galaxy when 6.3.8 was published, and the one in 6.3.8's tree installs 6.3.7 unless it is given another release's SHA-256; the operator's pull request to OperatorHub.io is made by hand.
- The Proxmox VE scripts have not run on a Proxmox VE host, only as a dry run, with stand-ins of its commands, and in a container made from its own debian-13-standard template. If you run them, please say how it went in an issue.
- The image's OpenSSL, Ubuntu 24.04's 3.0.13, has neither the hybrid post-quantum key exchange groups nor Argon2id: its server logs HM5720 and takes the classical groups and scrypt, and GET
/api/v1/status says false for both. - An AppImage on Fedora, Enterprise Linux or openSUSE runs on the host's glibc and cannot require its extra character-set converters: install glibc-gconv-extra (Fedora, EL) or glibc-gconv-modules-extra (openSUSE) by hand; the server says when they are missing.
- An upgraded server keeps the .NET 10 Desktop Runtime it had (the notices above).
While releases pause
6.3.6 was the last release planned by date, by the owner's decision of 28 September 2026; the releases since are security releases, each cut from master with whatever finished work master holds then, until the maintainers say otherwise in SECURITY.md, "While releases pause". A confirmed vulnerability still ships in a release: a critical or high one as soon as its fix has passed the gates, and none held past 90 days from its acknowledgement. Other defects are fixed on master and ship with the next security release, or when releases resume. 6.3.8 was first decided on 24 October 2026, under the owner's delegation, because the published Helm charts of 6.3.6 and 6.3.7 start no server, and neither the chart nor the image of a release can be put right but by a release; the project's own work since found the vulnerabilities above, and 6.3.8 is made as a security release, that reason standing beside them. The 6.3 line receives security fixes until 30 September 2027; before that date the maintainers write in SECURITY.md whether support continues, and if nothing has been written, the 6.3 line is not supported from 1 October 2027. Nothing is back-ported: an installation of 6.3.7, 6.2 or anything older is upgraded in place to the newest release. To hear of a release, switch the server's update check on (UpdateCheckEnabled), or follow the releases' feed at updates.progressiverobot.com/releases.atom.
The project, and reporting a vulnerability
The project's home is GitLab, at gitlab.com/hmailserver/hmailserver, where it moved from gitlab.com/Progressiverobot/hmailserver on 29 September 2026, with issue templates and a Service Desk address for anyone without a GitLab account: a bug report or a question for the maintainers emailed to contact-project+hmailserver-hmailserver-86730559-issue-@incoming.gitlab.com becomes a confidential issue, which only the maintainers see. Open an issue at https://gitlab.com/hmailserver/hmailserver/-/issues/new; the work items, 6.3.8's among them, are listed at https://gitlab.com/hmailserver/hmailserver/-/work_items. The release is also mirrored on GitHub, at https://github.com/RainbowWizard-coder/hMailServer/releases/tag/v6.3.8; GitLab stays canonical and the one place the project is worked on, and the repository on GitHub takes no issues. Questions go to the forum, https://www.hmailserver.co.uk/, where 6.3.8 is announced at https://www.hmailserver.co.uk/topic/28278; give the full build stamp on Windows, 6.3.8.47 for 6.3.8, or the exact package version on Linux. Report a vulnerability privately, as SECURITY.md says: a confidential GitLab issue with the Security template (check that it is still marked confidential before you submit it), or an email to that Service Desk address, which GitLab files as a confidential issue. Never in a forum thread or a public issue.