CVE Patch Review

GHSA-HVQH-JW65-WCPQ: Root-cause XSS Fix in devbridge-autocomplete Rendering

GHSA-HVQH-JW65-WCPQ · Updated 2026-06-23 Root-cause

Summary

The patch addresses DOM XSS in default autocomplete rendering paths by HTML-encoding untrusted suggestion values and category labels before insertion into generated markup. Based on the provided diff, the vulnerable direct string concatenation and raw value return paths were replaced with DOM text assignment via textContent and serialization via innerHTML/outerHTML, which is an appropriate root-cause remediation for the affected default renderers.

Analysis

Vulnerability

GHSA-HVQH-JW65-WCPQ describes a cross-site scripting issue in devbridge-autocomplete where untrusted suggestion content could reach HTML rendering sinks without sufficient escaping. The provided commit diff shows two default rendering paths were unsafe: returning suggestion.value directly when no query term was present, and concatenating category into a <div class="autocomplete-group">...</div> string. In both cases, attacker-controlled HTML could be interpreted by the browser when inserted into the suggestions container.

The vulnerable behavior is visible in the patch source summary from the upstream commit 63ff096ff5b77a90aac7fb5dad7c86e538a59ce0. The issue is specifically in the default formatter logic shipped in the distribution artifacts, not merely in consumer code. That makes the library itself responsible for converting untrusted data into executable DOM.

// vulnerable default rendering paths
return suggestion.value;
return '<div class="autocomplete-group">' + category + "</div>";

Patch

The patch replaces raw string-based rendering with DOM-based escaping primitives. For suggestion values in the no-query path, it creates a span, assigns suggestion.value to textContent, and returns the escaped serialization via innerHTML. For group labels, it creates a div, sets the CSS class, assigns the untrusted category to textContent, and returns outerHTML. This ensures special characters are encoded before the resulting HTML string is later inserted into the document.

// patched default rendering paths
const span = document.createElement("span");
span.textContent = suggestion.value;
return span.innerHTML;

const div = document.createElement("div");
div.className = "autocomplete-group";
div.textContent = category;
return div.outerHTML;

This is consistent with the advisory and commit evidence in the GitHub Security Advisory and the upstream patch commit. The fix targets the exact unsafe sinks shown in the diff rather than adding superficial filtering elsewhere.

Review

Pros

  • Fixes the direct root cause in the default renderers: untrusted data was previously emitted as HTML without encoding.
  • Uses browser-native escaping via textContent, which is less error-prone than hand-written replacement logic.
  • Covers both affected default paths shown in the diff: suggestion values and group/category labels.
  • Preserves intended markup generation for the group wrapper while ensuring only the wrapper is trusted and the content is encoded.
  • The minified distribution was updated alongside the non-minified builds, reducing the risk of shipping inconsistent artifacts.

Cons

  • The patch evidence is limited to distribution files; no source-level patch or tests are shown in the provided materials, which makes long-term maintainability and regression resistance harder to assess from this dataset alone.
  • The highlighted-query branch still relies on string manipulation and selective re-enabling of <strong> tags. While that path appears intentionally constrained in the provided code, it remains more fragile than a fully DOM-constructed renderer.
  • Consumers that override formatResult or formatGroup with unsafe custom HTML remain responsible for their own escaping; this patch only secures the library defaults.

Verdict

Root-cause.

Based on the supplied diff, the patch directly removes the unsafe raw HTML emission points that enabled XSS in the default rendering logic. It does not merely block a single payload pattern or add an incomplete filter; it changes the rendering mechanism so untrusted values are encoded before insertion. Within the scope evidenced by the commit and the advisory, this is an appropriate root-cause fix for the library-provided default formatters.

Sources