Webui license load and branding URL clobbered by password managers

Issue Description

the license loading from file in my cluster setup didn’t work, so I reverted to secret values in the WebUI. It loaded the and validated the enterprise license, but when I wanted to update/add/change the default branding logo, the password manager auto filled the secret fields, so I can’t update the branding URL without breaking the license secret values.

Expected Behavior

Have the license fields separate license screen/page, from the default logo/branding

Actual Behavior

merging the two have auto fill break the license secrets when attempting to update/setup the branding logo.

Reproduction Steps

  1. add license secrets via “Value” in the Enterprise setting tab
  2. validate/restart the stalwart web ui etc.
  3. go back to Enterprise tab, fill in the Default Branding logo URL,
  4. have password manager/etc. fill something in the secrets value fields.
  5. attempt to clean/reset them…
  6. saving this page now with branding URL invalidates enterprise licensing

Relevant Log Output

2026-06-24T00:18:41Z WARN Configuration build warning (registry.build-warning) source = “Enterprise”, id = 20080258862541, key = (null), reason = “Failed to renew license: Failed to fetch https://license.stalw.art/api/license/ecs-ops.co.za: Code: Unauthorized, Details: Unauthorized”
2026-06-24T00:21:52Z WARN Configuration build warning (registry.build-warning) source = “Enterprise”, id = 20080258862541, key = (null), reason = “Failed to renew license: Failed to fetch https://license.stalw.art/api/license/envisagecloud.co.za: Code: Unauthorized, Details: Unauthorized”
2026-06-24T00:24:36Z INFO Server licensing event (server.licensing) details = “Stalwart Enterprise Edition license key is valid”, domain = “envisagecloud.co.za”, total = 25, validFrom = “2026-05-19T22:24:02Z”, validTo = “2027-06-28T22:24:02Z”
2026-06-24T00:59:16Z WARN Configuration build warning (registry.build-warning) source = “Enterprise”, id = 20080258862541, key = (null), reason = “Failed to renew license: Failed to fetch https://license.stalw.art/api/license/envisagecloud.co.za: Code: Unauthorized, Details: Unauthorized”
2026-06-24T08:32:25Z WARN Configuration build warning (registry.build-warning) source = “Enterprise”, id = 20080258862541, key = (null), reason = “Failed to renew license: Failed to fetch https://license.stalw.art/api/license/envisagecloud.co.za: Code: Unauthorized, Details: Unauthorized”
2026-06-24T09:05:13Z INFO Server licensing event (server.licensing) details = “Stalwart Enterprise Edition license key is valid”, domain = “envisagecloud.co.za”, total = 25, validFrom = “2026-05-19T22:24:02Z”, validTo = “2027-06-28T22:24:02Z”

Stalwart Version

v0.16.x

Installation Method

Binary (Linux)

Database Backend

FoundationDB

Blob Storage

S3-compatible

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

This is a confirmed UI bug: the Enterprise settings page co-locates the apiKey/licenseKey secret fields with the logoUrl field on the same form, so password managers can auto-fill (and corrupt) the secret fields while you are only trying to update the logo URL.

Immediate workaround: Instead of using the WebUI form for this change, update only the logoUrl field directly via the JMAP API (or stalwart-cli), leaving your secret values completely untouched:

stalwart-cli update Enterprise --field 'logoUrl=https://example.com/logo.png'

Or via the JMAP API directly:

curl -X POST https://mail.example.com/api \
  -H 'Authorization: Bearer $TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
      "methodCalls": [
        [
          "x:Enterprise/set",
          {
            "update": {
              "singleton": {
                "logoUrl": "https://example.com/logo.png"
              }
            }
          },
          "c1"
        ]
      ],
      "using": [
        "urn:ietf:params:jmap:core",
        "urn:stalwart:jmap"
      ]
    }'

This sends only the logoUrl patch – the apiKey and licenseKey fields are not included, so they will not be overwritten.

For the secret fields themselves, switching from Value to EnvironmentVariable or File (as the SecretKeyOptional type supports) would also make them immune to password-manager interference going forward, since there would be no secret text field on screen to fill.

See the Enterprise object reference for full JMAP/CLI details.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

This has been fixed, a new WebUI version will be released this week.