SECURITYCRITICALCVE-2026-108264

CVE-2026-108264: Wizarr Jinja2 Template Injection Leads to RCE

Unsandboxed Jinja2 rendering of Wizarr wizard steps lets authenticated users or malicious bundle imports achieve remote code execution.

Dylan H.

Security Team

October 10, 2026
6 min read
CVE-2026-108264: Wizarr Jinja2 Template Injection Leads to RCE

Critical severity

Rated critical. Prioritise patching — see the remediation guidance below.

Affected Products

  • wizarrrr/wizarr — all versions prior to 2026.9.1

Overview

Wizarr is a self-hosted invitation and onboarding system used by homelab and media-server communities to manage user access to Jellyfin, Plex, Emby, and other services, including custom "wizard step" onboarding flows written in Markdown. Versions prior to 2026.9.1 render that Markdown through a non-sandboxed Jinja2 environment with application globals exposed, allowing an authenticated user who can create wizard steps — or an administrator who imports a malicious shareable "bundle" — to inject Jinja2 template expressions that execute as arbitrary Python code on the host. The flaw carries a CVSS score of 9.1 (Critical) and was published October 9, 2026.


Technical Details

FieldValue
CVE IDCVE-2026-108264
CVSS Score9.1 (Critical) — AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
CWECWE-1336 (Server-Side Template Injection) / CWE-94 (Code Injection)
Attack VectorNetwork (requires the privilege to create or import a wizard step/bundle)
Affected Componentapp/blueprints/wizard/routes.py — wizard step Markdown rendering (also app/jinja_filters.py and app/services/wizard_widgets.py)
Root CauseJinja2 environment overlaid with autoescape=False and no sandbox, evaluating attacker-controlled Markdown as live template code
Fixed In2026.9.1

How It Works

Wizarr lets admins (and, depending on configuration, other users able to reach the wizard editor) build custom onboarding "wizard steps" as Markdown, and lets admins import pre-built "bundles" of wizard steps shared by the community via POST /settings/wizard/import. The rendering path for that Markdown overlays the application's Jinja2 environment with autoescape=False rather than using jinja2.sandbox.SandboxedEnvironment, so the engine still has full access to Python's object graph and application globals. Any Jinja2 expression syntax embedded in a wizard step's Markdown — whether typed directly into the editor or hidden inside an imported bundle — is evaluated server-side the next time that step is rendered via GET /wizard/{server}/{idx}, rather than being treated as literal text. Bundle import only validates field types, so it does not catch malicious template syntax smuggled into the Markdown body.

Jinja2's non-sandboxed mode is notorious for escalating straightforward template injection into full remote code execution, because an attacker can walk the Python object graph from any template-exposed object back to builtins. A generic, illustrative pattern (not a working Wizarr-specific payload) looks like:

{{ self.__init__.__globals__.__builtins__ }}

From there, a real exploit chain would continue traversing object attributes to reach something callable — such as os.system or subprocess.Popen — and invoke it with attacker-chosen arguments, which is how the advisory describes attackers executing arbitrary operating-system commands, disclosing the Flask SECRET_KEY, and reaching the database and connected media-server credentials.


Impact Assessment

Impact AreaDescription
ConfidentialityHigh — RCE exposes the Flask SECRET_KEY, the Wizarr database (users, credentials, invitations), and any connected Jellyfin/Plex/Emby credentials
IntegrityHigh — arbitrary Python/OS command execution on the Wizarr host, plus stored cross-site scripting via the same unsanitized rendering path
AvailabilityHigh — an attacker with code execution can disrupt or disable the Wizarr instance and anything it manages

Who Is At Risk

  • Self-hosted Wizarr instances (≤ 2026.9.0) where any user besides the fully trusted root admin can create or edit wizard steps
  • Admins who import community-shared wizard-step "bundles" from third-party sources without reviewing their Markdown content first
  • Homelabs where Wizarr's host or container has network access to the Flask secret, local database, or Jellyfin/Plex/Emby admin APIs — i.e., essentially all default deployments

Attack Chain

  1. An attacker with the ability to create a wizard step (or craft a shareable bundle for an admin to import via POST /settings/wizard/import) embeds a Jinja2 expression in the step's Markdown body.
  2. The step is saved without any template-syntax sanitization — only field types are validated on import.
  3. When the step is later rendered (GET /wizard/{server}/{idx}), the application's non-sandboxed Jinja2 environment evaluates the embedded expression instead of displaying it as text.
  4. The expression walks Python's object graph to reach a callable such as os.system, achieving remote code execution as the application user, with follow-on access to the Flask secret key, the Wizarr database, and any connected Jellyfin/Plex/Emby credentials.

Mitigation

Immediate Actions

  • Upgrade to Wizarr 2026.9.1 or later, which restricts wizard template rendering
  • Audit any previously imported wizard-step bundles — especially from third-party or community sources — for {{ or {% template syntax that shouldn't be there
  • Rotate the Flask SECRET_KEY and any credentials Wizarr holds for connected Jellyfin/Plex/Emby servers if compromise is suspected
  • Restrict who holds the role that can create, edit, or import wizard steps to fully trusted admins only, pending the upgrade

Detection Opportunities

  • Review stored wizard-step content (editor-created and imported) for template syntax such as {{, {%, or references to __globals__, __init__, or __builtins__
  • Watch for unexpected outbound connections or child-process spawns from the container or host running Wizarr
  • Check Wizarr and reverse-proxy logs for unusual activity around POST /settings/wizard/import or repeated hits to GET /wizard/{server}/{idx}

Defence-in-Depth

  • Run Wizarr in an isolated container with minimal host access and no unnecessary outbound network reachability
  • Network-segment Wizarr from the Jellyfin/Plex/Emby admin APIs it connects to, so a compromised Wizarr instance can't pivot directly into the media server
  • Treat community-shared wizard-step bundles as untrusted input, the same as any other imported, unaudited code or config

Background

Wizarr fills a common niche in self-hosted media-server communities: a friendly, templated onboarding experience that spares admins from manually walking each new user through Jellyfin, Plex, or Emby setup. That same flexibility — letting admins build and share reusable "wizard step" bundles — is what turned a convenience feature into a server-side template injection vector. Self-hosted admin tools that accept community-shared "content" (templates, themes, plugins, onboarding bundles) without sandboxing the engine that renders it are a recurring pattern behind SSTI and supply-chain-style vulnerabilities across the homelab ecosystem, and CVE-2026-108264 is a textbook example: a convenience feature (Markdown-based wizard steps) built on a templating engine (Jinja2) that was never isolated from the host application it was embedded in.


References