Huginn: Scenario Import Runs Script in the Victim's Session

An imported scenario's description is rendered as raw HTML, already in the preview, before the import is confirmed.

Advisory ID: TP-2026-085
Product: Huginn (self-hosted automation platform, Ruby on Rails)
Vulnerability type: Stored cross-site scripting (CWE-79)
CVE: not assigned
CVSS 3.1: 8.1 (High) · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
Affected versions: <= 2026.08.27
Vendor advisory: GHSA-x738-j22q-h2jw
Fixed in: 2026.09.08
Reported: 3 June 2026

Summary

Huginn advertises that users share ready-made automation scenarios as a JSON file or through a public URL. On import, Huginn first shows a preview in which the scenario's description passes through the markdown helper. That helper lets raw HTML through unchanged and marks the result as safe, so a script element in the description field executes. This happens on the preview page, that is before the victim confirms the import, and Huginn sends no Content-Security-Policy. Anyone who gets an administrator to look at a crafted scenario runs script in that administrator's logged-in session.

Root cause

The markdown() helper calls Kramdown::Document.new(text, auto_ids: false).to_html.html_safe and applies no filter (app/helpers/markdown_helper.rb:3-5). Kramdown's defaults parse_block_html and parse_span_html pass raw HTML through unchanged, and .html_safe switches off Rails' automatic escaping. The preview hands parsed_data["description"] straight to that helper (app/views/scenario_imports/_step_two.html.erb:32), where parsed_data is the attacker's raw JSON (app/importers/scenario_import.rb:45-47), taken from pasted text, an uploaded file or a fetched URL (:124-128). ScenarioImportsController#create re-renders the preview whenever import_confirmed? is false, which is why the script fires before any confirmation. After the import the same happens on the scenario page (app/views/scenarios/show.html.erb:12), and the application sends no Content-Security-Policy.

Proof of Concept

# scenario JSON, hosted by the attacker at a public URL
{
  "name": "Useful scenario",
  "description": "<script>alert(document.domain)</script>",
  "guid": "...", "agents": []
}

# victim: Scenarios -> Import Scenario -> paste into "Public Scenario URL"
# the preview renders the description raw inside a <blockquote>,
# the script runs without "Finish Import" ever being clicked.

Kramdown escapes a standalone <svg onload=...> as a paragraph, while a script block and markdown links using javascript: pass through unchanged. The script element alone is enough, so the quirk does not reduce the impact.

Impact

  • Script execution in the logged-in session of any user who previews someone else's scenario.
  • Privilege escalation when the victim is an administrator: the session cookie is HttpOnly, but the CSRF token sits in the DOM, so the script issues authenticated requests and creates a new administrator account through the admin endpoints.
  • Disclosure and modification of all of the victim's agents, including the third-party credentials stored in them.
  • Repeated execution every time the scenario is opened, once the import has been confirmed.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.