Skip to content

Einstellung für Display URL im secondary mode - #4280

Open
kaindl wants to merge 4 commits into
openWB:masterfrom
kaindl:display_url_manual_override
Open

kaindl wants to merge 4 commits into
openWB:masterfrom
kaindl:display_url_manual_override

Conversation

@kaindl

@kaindl kaindl commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Im secondary Modus erwartet die openWB eine URL vom primary, die auf dem internen Display angezeigt wird (wenn verbaut). Nicht alle anderen Controller außer der openWB selbst senden eine solche URL und über modbus ist es gar nicht möglich. Deshalb gibt es hiermit ein Möglichkeit, diese URL direkt in den Einstellungen im Webinterface zu hinterlegen.

Alternative Implementierung zu #3205, da ich es über eine Einstellung deutlich schlanker und logischer finde, als über ein Theme.
Würde ebenso #1975 und #3861 lösen.

Zusätzliche Checks, wie in #3205 gefordert, für lokale Adressen und Last sehe ich nicht in diesem Setting: Die URL kann so auch von einem anderen Primary gesendet werden, mit den gleichen Implikationen -> wenn solche Checks wirklich relevant sind, sollten sie global für alle angezeigten URLs umgesetzt werden, egal wie die URL gesetzt wird.

Eine entsprechende Warnung ist in der Weboberfläche als danger-alert eingebaut:

Bitte beachten, dass die URL in einem Browser auf dieser secondary openWB geladen wird. Nur vertrauenswürdige Webseiten sollten hier angegeben werden. Aufwändige Webseiten mit Effekten und Animationen können die Regelung der Ladepunkte negativ beeinflussen.

zugehöriger PR auf openwb-ui-settings: openWB/openwb-ui-settings#1164

Summary by Sourcery

Support a configurable and validated display URL for secondary-mode internal displays.

New Features:

  • Allow configuring a custom HTTP(S) display URL for secondary-mode internal displays through the web interface settings.
  • Load the configured display URL on secondary displays, with fallback to the primary display when no URL is configured.

Bug Fixes:

  • Prevent repeated display navigations while MQTT configuration data is still being received.

Enhancements:

  • Validate configured display URLs and improve safe rendering of display log messages.

Chores:

  • Add the display URL to default configuration, MQTT synchronization, and access-control data.

@sourcery-ai

sourcery-ai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Data structures

Add the optional internal-display URL field and its MQTT topic so the setting is represented in configuration state.

  • data/config/mosquitto/public/default-dynamic-security.json L401-406, L1261-1266, L1309-1314
  • packages/control/optional_data.py L140
  • packages/helpermodules/update_config.py L449, L756

Uses of the API

Subscribe the secondary display to the configured URL topic so it can select the override instead of the primary display URL.

  • web/display/processAllMqttMsg.js L67-74
  • web/display/setupMqttServices.js L23

Deduplicate pending display navigations and cancel stale destinations when a newer destination is selected.

  • web/display/processAllMqttMsg.js L2-18, L76

Implementation

Validate configured display URLs as empty or HTTP(S) URLs before accepting them through the set topic.

  • packages/helpermodules/setdata.py L9, L27-36, L970-976

UI

Render display log messages as text rather than HTML to avoid interpreting logged content as markup.

  • web/display/processAllMqttMsg.js L127, L132

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="web/display/setupMqttServices.js" line_range="23" />
<code_context>
 	"openWB/system/current_branch": false,
 	"openWB/system/current_commit": false,
 	"openWB/general/extern_display_mode": false,
+	"openWB/optional/int_display/display_url": false,
 	"openWB/internal_chargepoint/global_data": false,
 	"openWB/internal_chargepoint/0/data/parent_cp": false,
</code_context>
<issue_to_address>
**Display-setting payload triggers XSS**

When a publisher with display-configuration access sends a string containing executable HTML markup as the URL value, `handleMessage` passes the MQTT payload to `addLog`, which inserts it with `innerHTML`; markup in the payload therefore executes in the display wrapper’s origin and can access same-origin data such as the MQTT cookie.

Render log messages as text (for example, with `textContent`) rather than inserting MQTT payloads through `innerHTML`.

Also at `packages/helpermodules/setdata.py:960`.
</issue_to_address>

### Comment 2
<location path="web/display/processAllMqttMsg.js" line_range="52" />
<code_context>
-			addLog(`all done, loading theme from primary`);
+			const configuredDisplayUrl = data["openWB/optional/int_display/display_url"];
+			if (configuredDisplayUrl && configuredDisplayUrl.trim()) {
+				destination = configuredDisplayUrl.trim();
+				addLog(`all done, loading manually configured display URL`);
+			} else {
</code_context>
<issue_to_address>
**Configured URL runs same-origin script**

When a display-configuration publisher sets `display_url` to a `javascript:` URL, `location.href` evaluates a `javascript:` URL in the display wrapper’s origin, letting the publisher run script there and read same-origin data such as the MQTT cookie.

Parse the configured value and allow only `http:` or `https:` URLs before navigating.
</issue_to_address>

### Comment 3
<location path="web/display/setupMqttServices.js" line_range="23" />
<code_context>
 	"openWB/system/current_branch": false,
 	"openWB/system/current_commit": false,
 	"openWB/general/extern_display_mode": false,
+	"openWB/optional/int_display/display_url": false,
 	"openWB/internal_chargepoint/global_data": false,
 	"openWB/internal_chargepoint/0/data/parent_cp": false,
</code_context>
<issue_to_address>
**Anonymous clients can read URL tokens**

When the configured display URL contains a bearer token or other secret, an unauthenticated MQTT client in the default anonymous group can subscribe to the retained URL and retrieve any bearer token or credentials embedded in it, exposing access to the protected resource.

Avoid broadcasting secret-bearing URLs to the anonymous role; use an authenticated resource or a mechanism that does not expose the secret through MQTT.
</issue_to_address>

### Comment 4
<location path="web/display/processAllMqttMsg.js" line_range="52" />
<code_context>
-			addLog(`all done, loading theme from primary`);
+			const configuredDisplayUrl = data["openWB/optional/int_display/display_url"];
+			if (configuredDisplayUrl && configuredDisplayUrl.trim()) {
+				destination = configuredDisplayUrl.trim();
+				addLog(`all done, loading manually configured display URL`);
+			} else {
</code_context>
<issue_to_address>
**Display opens stale destination**

When the configured URL changes while a navigation timeout is pending, an earlier timeout navigates to its captured destination before the later timeout applies the new setting, so the display opens the stale URL.

Cancel and replace any pending navigation timeout when the destination changes, or have the timeout use the latest destination.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread web/display/setupMqttServices.js Resolved
Comment thread web/display/processAllMqttMsg.js Resolved
Comment thread web/display/setupMqttServices.js Resolved
Comment thread web/display/processAllMqttMsg.js Resolved
kaindl and others added 2 commits November 7, 2026 17:43
Render display logs as text and reject display URLs that do not use HTTP or HTTPS.\n\nCo-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant