> ## Content Index
> Fetch the complete content index at: https://www.process-one.net/llms.txt
> Use this file to discover other available public pages before exploring further.

# ejabberd 26.09
- URL: https://www.process-one.net/blog/ejabberd-26-09/
- Published: 2026-09-30T09:37:02.000Z
- Updated: 2026-09-30T09:37:02.000Z
- Description: We are pleased to announce the publication of ejabberd 26.09, which includes several security fixes, some improvements and other minor bugfixes. It is strongly encouraged that you update ejabberd as soon as possible.
- Author: Jérôme Sautret
- Tags: ejabberd, Release, XMPP

**Contents:**

- **[Security fixes](#security)**
- **[Fixed the ordering of some XML child elements](#xmlorder)**
- **[New option for CAPTCHA POW](#pow)**
- **[ChangeLog](#changelog)**
- **[Acknowledgments](#ack)**
- **[Improvements in ejabberd Business Edition](#ebe)**
- **[ejabberd 26.09 download & feedback](#download)**

## Security fixes

This release contains fixes for those security issues:

- Unauthenticated Remote Code Execution on ejabberd (reported by Gia Bui) when:  
  - ejabberd versions is at least 25.10
  - BOSH is enabled on any port
  - S2S is enabled
  - mod\_adhoc\_api is loaded
  - outbound connectivity from ejabberd on ports epmd (default 4369), s2s (default 5269) and Erlang distribution port (dynamically assigned, typically in the range 49152-65535 unless FIREWALL\_WINDOW is set in ejabberdctl.cfg).
- DoS attack on 16.12+ versions if BOSH is enabled on any port.
- Cross-Tenant MUC, Roster and Shared-Roster unauthorized access (reported by Hoang Gia).

## Fixed the ordering of some XML child elements

There was a reference-ordering problem in the `fast_xml` generator, it generated XML encoders that could reorder child elements in a different order from the one declared in the codec specification. From now, the order is the one declared in the codec specification. See details in [https://github.com/processone/fast\_xml/pull/53](https://github.com/processone/fast%5Fxml/pull/53?ref=process-one.net)

Additionally there was an incorrect sasl2\_continue declaration order in the `xmpp` erlang library: it declared "additional-data, text, tasks". Now it follows the ordering defined in XEP-0388 schema: "additional-data, tasks, text". See details in [https://github.com/processone/xmpp/pull/112](https://github.com/processone/xmpp/pull/112?ref=process-one.net)

## New option for CAPTCHA POW

New toplevel option [captcha\_pow](https://docs.ejabberd.im/admin/configuration/toplevel/?ref=process-one.net#captcha%5Fpow) adds a [SHA-256 hashcash](https://xmpp.org/extensions/xep-0158.html?ref=process-one.net#challenge-hashcash) challenge as described in XEP-0158 in the CAPTCHA form, alongside the image challenge or on its own.

Unlike the image challenge, this does not require setting the option [captcha\_cmd](https://docs.ejabberd.im/admin/configuration/toplevel/?ref=process-one.net#captcha%5Fcmd).

This option is used only by `mod_register` when registering a new account using In-Band Registration, not in MUC rooms or in `mod_register_web`. It is disabled by default.

## Improved support for vhost-admins

It is well known how to [grant administrative privileges](https://docs.ejabberd.im/admin/install/next-steps/?ref=process-one.net#administration-account) to an account: by adding that account to an [acl](https://docs.ejabberd.im/admin/configuration/basic/?ref=process-one.net#acl) called `admin`:

```yaml
acl:
  admin:
    user: admin1@localhost

```

The default ejabberd configuration uses this `admin` ACL in many places:

- the `announce` [access rule](https://docs.ejabberd.im/admin/configuration/basic/?ref=process-one.net#access-rules) used by [mod\_announce](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fannounce)
- the `configure` access rule used by [mod\_configure](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fconfigure) and [WebAdmin](https://docs.ejabberd.im/admin/guide/managing/?ref=process-one.net#web-admin)
- several [api\_permissions](https://docs.ejabberd.im/admin/configuration/toplevel/?ref=process-one.net#api%5Fpermissions) entries used to execute [API commands](https://docs.ejabberd.im/developer/ejabberd-api/?ref=process-one.net) in WebAdmin, [mod\_adhoc\_api](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fadhoc%5Fapi), [mod\_http\_api](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fhttp%5Fapi), ...
- some [shaper\_rules](https://docs.ejabberd.im/admin/configuration/basic/?ref=process-one.net#shaper-rules)
- many options modules, for example `access_admin` option in [mod\_muc](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fmuc)

Consequently, that admin account can administer all of ejabberd: all the global features, all the modules, in all the vhosts... For now let's call it a "global admin".

If you have several vhosts, you can allow specific accounts to administer only specific vhosts. Let's call them "vhost-admins". In this example `admin1@localhost` can execute commands on all vhosts. Additionally, `localhost` has a vhost-admin, `second` has two vhosts-admins, and `third` has a vhost-admin:

```yaml
hosts:
 - localhost
 - second
 - third

acl:
  admin:
    user: admin1@localhost

append_host_config:
  localhost:
    acl:
      aclhostadmin:
        - user: hostadmin@localhost
  second:
    acl:
      aclhostadmin:
        - user: hostadmin@second
        - user: hostadmin@third
  third:
    acl:
      aclhostadmin:
        - user: hostadmin@second

api_permissions:
  "vhost http access":
    from: mod_http_api
    who:
      access:
        allow:
          - acl: admin
        allow:
          - acl: aclhostadmin
    what: "*"

```

Example call of a vhost command by a vhost-admin:

```
$ curl --basic --user hostadmin@third:somepass -k \
  'https://localhost:5443/api/status_num_host?host=second&status=dnd'
7

```

If a vhost-admin tries to execute an API command directed to a vhost he does not administer, or a global command (that has no host argument, and affects all ejabberd), they are rejected:

```
$ curl --basic --user hostadmin@third:somepass -k \
  'https://localhost:5443/api/status_num_host?host=third&status=dnd'
{"code":32,
 "message":"AccessRules: Account does not have the right to perform the operation.",
 "status":"error"}

$ curl --basic --user hostadmin@third:somepass -k \
  'https://localhost:5443/api/stats?name=registeredusers'
{"code":32,
 "message":"AccessRules: Account does not have the right to perform the operation.",
 "status":"error"}

```

## ChangeLog

#### Security fixes

- Unauthenticated Remote Code Execution on ejabberd
- DoS attack on BOSH
- Cross-Tenant MUC, Roster and Shared-Roster unauthorized access

#### Core

- Add `force` value to `auth_external_user_exists_check` option
- Add XEP-0158 SHA-256 hashcash CAPTCHA challenge ([#4594](https://github.com/processone/ejabberd/pull/4594?ref=process-one.net))
- Add gen\_mod:get\_module\_proc\_check()
- Fix to preserve reference order in XML, done in fast\_xml and xmpp ([#4606](https://github.com/processone/ejabberd/pull/4606?ref=process-one.net))
- Get rid of couple `*_to_atom`
- Make `ejabberd_cluster:*call` operate only on known nodes
- More fixes for arguments in commands for vhost-admin
- Optimize `acl:load_tab()`
- `ejabberd_systemd`: Prefer matching over `length/1`
- Updated Portuguese-Brazil and Chinese-Simplified translations

#### Modules

- `mod_auth_fast`: Make sure that fast tokens can be used only with method that they were created for
- `mod_invites`: don't apply overuse limit if `max_invites` is `infinity` ([#4615](https://github.com/processone/ejabberd/pull/4615?ref=process-one.net))
- `mod_invites`: don't crash in `get_invite_by_invitee_t` if `reset_token` present ([#4620](https://github.com/processone/ejabberd/pull/4620?ref=process-one.net))
- `mod_invites`: now that Conversations is for free we remove Yaxim ([#4621](https://github.com/processone/ejabberd/pull/4621?ref=process-one.net))
- `mod_mix`: Make access\_create rule be applied when creating channel
- `mod_mqtt`: Add lower limits for pre-auth packets
- `mod_muc_room`: Fix handling of hats request with missing xdata
- `mod_muc_rtbl`: Accept also plain account and domain JIDs
- `mod_muc_rtbl`: Fix handling of remote ban servers ([#4622](https://github.com/processone/ejabberd/pull/4622?ref=process-one.net))
- `mod_register`: After changing password disallow password change on currently authenticated sessions

#### SQL

- Add `db_serialize` to `mod_privacy` and `mod_pubsub`
- Add `rename_column` op to `ejabbrd_sql_schema` update routines
- Make `rename_column` compatible with older mysql versions
- `ejabberd_sql_schema`: Escape all column/table names
- Update `mod_roster` serializer with info about approved field

#### Administration

- Allow vhost-admin to execute MUC commands for his vhost ([#4603](https://github.com/processone/ejabberd/pull/4603?ref=process-one.net))
- Fix method to check vhost-admin permission in Host API ([#4619](https://github.com/processone/ejabberd/pull/4619?ref=process-one.net))
- WebAdmin: Fix shared roster page when visited by vhost-admin
- WebAdmin: For vhost-admins, hide useless link to node page
- WebAdmin: Show proper domain in URLs, not the first configured vhost

#### Installers and Container

- `make-binaries`: Bump Elixir to 1.19.6
- `make-binaries`: Bump Erlang/OTP version to 28.5.0.7
- `make-binaries`: Bump Expat version to 2.8.5
- `make-binaries`: Bump JPEG version to 10
- `make-binaries`: Bump OpenSSL 3.6.4
- `make-binaries`: Bump PNG version to 1.6.58
- `make-binaries`: Bump SQLite version to 3530400
- `make-binaries`: Bump WebP version to 1.6.0
- `Dockerfile`: Workaround to get image with `amd64` ([#4598](https://github.com/processone/ejabberd/pull/4598?ref=process-one.net))

### Full Changelog

[https://github.com/processone/ejabberd/compare/26.07...26.09](https://github.com/processone/ejabberd/compare/26.07...26.09?ref=process-one.net)

## Acknowledgments

We would like to thank for the security reports provided by:

- [Gia Bui](https://github.com/yabeow?ref=process-one.net) from Calif.io
- [Hoang Gia](https://github.com/uziii2208?ref=process-one.net)
- [Nguyễn Huy Hoàng](https://github.com/hoanggxyuuki?ref=process-one.net)
- [Pham Kiet](https://github.com/zokieer?ref=process-one.net)
- [On3nvm](https://github.com/phamthanhnhat?ref=process-one.net)

the contributions to the source code by:

- [rallep71](https://github.com/rallep71?ref=process-one.net) for the fixes in `fast_xml` and `xmpp` XML child ordering
- [MrEddX](https://github.com/MrEddX?ref=process-one.net) for fixes in mod\_muc\_rtbl
- [Pounceandmiss](https://github.com/pounceandmiss?ref=process-one.net) for improvement in CAPTCHA
- [Stefan Strigler](https://github.com/sstrigler?ref=process-one.net) for Invites improvements
- [Andreas Aaberge Eide](https://github.com/aaaeide?ref=process-one.net) for SQL improvements
- [Holger Weiß](https://github.com/weiss?ref=process-one.net) for installers updates

and the translation by:

- [Daltux](https://github.com/daltux?ref=process-one.net) for updating the Portuguese (Brazil) translation
- [Sketch6580](https://hosted.weblate.org/user/Sketch6580/?ref=process-one.net) for updating the Chinese (Simplified) translation

And also to all the people contributing in the ejabberd chatroom, issue tracker...

## Improvements in ejabberd Business Edition

Customers of the [ejabberd Business Edition](https://www.process-one.net/compare/), in addition to all those bugfixes, also get the following changes:

- Improve p1db serialization
- Fix SQLite backend for push
- Recognize gateway\_sandbox option inside `mod_applepush` service (to change sandbox connection endpoint)

### Changes in SQL schema

#### MySQL

When using multihost schema:

```sql
ALTER TABLE push_gate CHANGE COLUMN user username text NOT NULL;
CREATE INDEX i_push_gate_username_server_host USING BTREE ON `push_gate`(username(191), server_host(191));

```

Otherwise:

```sql
ALTER TABLE push_gate RENAME COLUMN user TO username;
CREATE INDEX i_push_gate_username USING BTREE ON `push_gate`(username(191));

```

#### PgSql

When using multihost schema:

```sql
ALTER TABLE push_gate RENAME COLUMN "user" TO "username";
CREATE INDEX i_push_gate_token_server_host ON "push_gate" USING btree ("username", "server_host");

```

Otherwise:

```sql
ALTER TABLE push_gate RENAME COLUMN "user" TO "username";
CREATE INDEX i_push_gate_token ON "push_gate" USING btree ("username");

```

##  ejabberd 26.09 download & feedback

As usual, the release is tagged in the Git source code repository on [GitHub](https://github.com/processone/ejabberd?ref=process-one.net).

The source package and installers are available in [ejabberd Downloads](https://www.process-one.net/download/) page. To check the `*.asc` signature files, see [How to verify ProcessOne downloads integrity](https://www.process-one.net/blog/verifying-process-one-downloads-integrity/).

For convenience, there are alternative download locations like the [ejabberd DEB/RPM Packages Repository](https://repo.process-one.net/?ref=process-one.net) and the [GitHub Release / Tags](https://github.com/processone/ejabberd/tags?ref=process-one.net).

The `ecs` container image is available in [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/?ref=process-one.net) and [ghcr.io/processone/ecs](https://github.com/processone/docker-ejabberd/pkgs/container/ecs?ref=process-one.net). The alternative `ejabberd` container image is available in [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd?ref=process-one.net).

If you consider that you've found a bug, please search or fill a bug report on [GitHub Issues](https://github.com/processone/ejabberd/issues?ref=process-one.net).