Luligu/matterbridge

Frontend appends trailing slash to plugin configUrl, corrupting query strings (since 3.9.2)

Open

#579 opened on Jul 11, 2026

 (2 comments) (0 reactions) (1 assignee)TypeScript (53 forks)auto 404
help wanted

Repository metrics

Stars
 (938 stars)
PR merge metrics
 (PR metrics pending)

Description

Since 3.9.2, the frontend's handleConfigUrl normalizes a device's configUrl before loading it in the plugin-frontend iframe (introduced with the Ingress base-path support):

const t = ${basePath}${configUrl.replace(/^\.?\//, '')};
const n = t.endsWith('/') ? t : ${t}/; // ← appends '/' blindly

The trailing-slash normalization ignores query strings. A plugin configUrl like:

/plugins/matterbridge-mqtt-devices/?device=temp1 becomes: /plugins/matterbridge-mqtt-devices/?device=temp1/

The slash lands inside the query value, so the plugin page receives device=temp1/, its GET /plugins/<name>/api/config?device=temp1%2F lookup fails, and onFetch returning undefined produces a 404 — the config page renders empty. This worked in 3.9.1, which passed configUrl to the iframe verbatim.

Steps to reproduce

Install a plugin whose device configUrl carries a query string, e.g. matterbridge-mqtt-devices (/plugins/matterbridge-mqtt-devices/?device=<id>). Open the device's config page from the Devices view on Matterbridge ≥3.9.2. The plugin frontend loads, but the query parameter arrives with a trailing / appended. Expected behavior The trailing slash should only be applied to the path portion, e.g.:

const url = new URL(t, window.location.origin);
if (!url.pathname.endsWith('/')) url.pathname += '/';

Reported downstream: hobbyquaker/matterbridge-mqtt-devices#2 (worked around plugin-side in 0.10.4 by stripping trailing slashes from the query value).

Contributor guide