Possible security issues
Suspected but not fully confirmed. Listed so they can be verified and, where cheap, mitigated proactively.
Reachability legend — U = untrusted data · I = internal data · N = network-exposed. See Proved issues for confirmed findings and the security model for context.
SSRF / resource loading from untrusted URLs in markup — U (high impact)
Any template that places untrusted data into an <img src>, <iframe>, <link>, <script>, or fetch() URL lets the browser fetch attacker-chosen targets (internal services, cloud metadata). Auto-escaping prevents tag break-out but not a malicious URL value. file:// subresource loads are normally blocked by the browser’s default policy (no --allow-file-access-from-files is set), so local-file read is likely mitigated by the browser rather than by application code.
- Verify: whether any deployed template puts untrusted data in a URL position; current browser behavior for the pinned image.
- Mitigate: an egress network policy blocking private/link-local ranges; validate/allowlist URL values in templates.
JavaScript composition planner has no interrupt/timeout — U (DoS, author-trusted)
The JS planner (composition.js) runs in goja with no execution deadline and a shared mutex. A data-driven infinite loop in the (trusted) planner would hang the request and serialize other renders of that composition. goja has no filesystem or network access, so impact is limited to CPU/hang.
- Verify: whether any timeout wraps the planner call.
- Mitigate: set a runtime interrupt/deadline around
buildPlan.
Log injection via request fields — N (low, likely mitigated)
The request-ID query parameter and request path/query are logged. The default text formatter quotes special characters (newlines are escaped), which largely prevents forged log lines; JSON format is safe.
- Verify: the configured formatter in production.
- Mitigate: constrain/validate the
request_idparameter; use JSON logs.
Internal server exposes any template’s assets to the rendering page — U (low)
The internal render server serves /templates/<name>/assets/* for any template name. Path traversal outside a template’s assets/ is blocked, but a rendering page could read other templates’ (non-secret by design) asset files.
- Mitigate: scope asset access to the current render if templates ship sensitive assets (they should not).
embed_* path taken from data — U (low)
If a template passes untrusted data as the path to embed_text/embed_base64, an attacker could read arbitrary files within that template’s assets/ directory (traversal outside is blocked).
- Mitigate: never pass untrusted data as an embed path.