Skip to content

Hold drawcustom images and fonts to Home Assistant's allowlists - #149

Open
g4bri3lDev wants to merge 1 commit into
mainfrom
fix/drawcustom-allowlist
Open

g4bri3lDev wants to merge 1 commit into
mainfrom
fix/drawcustom-allowlist

Conversation

@g4bri3lDev

@g4bri3lDev g4bri3lDev commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Summary

drawcustom passed its payload straight to the renderer, which opens any absolute path and fetches any http(s) URL that a dlimg url or a font names. upload_image already checks URLs against allowlist_external_urls; drawcustom checked nothing.

This bumps odl-renderer to 0.5.15, which asks the caller before it loads a source (OpenDisplay/odl-renderer#43), and answers with Home Assistant's own allowlists:

  • A dlimg http(s) URL must be in allowlist_external_urls (the same rule as upload_image, reusing url_not_allowed).
  • A dlimg file path and an absolute font path must be in a folder Home Assistant allows: www, the media folders, or allowlist_external_dirs. The check is hass.config.is_allowed_path, so symlinks and .. out of an allowed folder are refused. The renderer calls it from its drawing thread, not the event loop.

The integration only supplies the policy (_source_guard). Which element fields name a source is the renderer's knowledge and stays there, so new element types are covered without a change here. A refusal arrives as SourceNotAllowedError and is turned into a ServiceValidationError for the whole call, since the payload is the same for every target.

The renderer bump also brings two fixes that need no integration code:

  • A font given by name can no longer climb out of the font folders with ...
  • Each image download is limited to 30 seconds and 32 MB.

Data URIs, hidden elements (the renderer never loads them) and fonts given by name are unaffected.

Breaking change for existing payloads

A dlimg that loads from an http(s) URL stops working until that URL is added to allowlist_external_urls in configuration.yaml. This includes URLs that point at the user's own Home Assistant. Files under www and the media folders keep working without configuration, as do the documented font locations.

Not in this PR

The service registrations are unchanged; the actions are not made admin-only.

Strings

New exception path_not_allowed in strings.json and translations/en.json. Other languages are left to the translation workflow.

Testing

  • scripts/test: 247 passed
  • scripts/test --min-ha: 247 passed
  • uv run ruff check ., uv run ruff format --check ., scripts/verify_translations.py: clean

The new tests run the real renderer rather than a mock: each refused source (image URL, image path, font path, font name with ..) fails with the right error and makes no HTTP request; a symlink and a .. path out of an allowed folder are refused; an allowlisted file and a bundled font still render with a hidden disallowed element in the payload. The URL allowlist is tested on the guard directly, because Home Assistant's HTTP test mock lacks content_length, which the renderer's size limit reads.

@g4bri3lDev
g4bri3lDev marked this pull request as draft October 13, 2026 14:04
drawcustom passed its payload straight to the renderer, which opens any
absolute path and fetches any http(s) URL that a `dlimg` url or a font
names. upload_image already checks URLs against `allowlist_external_urls`;
drawcustom checked nothing.

Bump odl-renderer to 0.5.15, which asks the caller before it loads a
source, and answer with Home Assistant's own allowlists:

- a `dlimg` http(s) URL must be in `allowlist_external_urls`
- a `dlimg` file path and an absolute font path must be in an allowed
  folder (`www`, the media folders, or `allowlist_external_dirs`)

0.5.15 also stops a font name from climbing out of the font folders with
`..`, and limits each image download to 30 seconds and 32 MB.

Data URIs, hidden elements and fonts given by name are unaffected.

Payloads that load images from URLs outside the allowlist stop working
until the URL is added to `allowlist_external_urls` in configuration.yaml.
@g4bri3lDev
g4bri3lDev force-pushed the fix/drawcustom-allowlist branch from 50ff6cd to a653338 Compare October 13, 2026 14:10
@g4bri3lDev
g4bri3lDev marked this pull request as ready for review October 13, 2026 14:10
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