diff --git a/coffee/lib/abstract-chosen.coffee b/coffee/lib/abstract-chosen.coffee
index d53c968fb81..e15282bee53 100644
--- a/coffee/lib/abstract-chosen.coffee
+++ b/coffee/lib/abstract-chosen.coffee
@@ -51,7 +51,7 @@ class AbstractChosen
choice_label: (item) ->
if @include_group_label_in_selected and item.group_label?
- "#{item.group_label}#{item.html}"
+ "#{this.escape_html(item.group_label)}#{item.html}"
else
item.html
diff --git a/spec/jquery/bugfixes.spec.coffee b/spec/jquery/bugfixes.spec.coffee
new file mode 100644
index 00000000000..a55647717bd
--- /dev/null
+++ b/spec/jquery/bugfixes.spec.coffee
@@ -0,0 +1,30 @@
+describe "Bugfixes", ->
+ it "https://github.com/harvesthq/chosen/issues/2996 - XSS Vulnerability with `include_group_label_in_selected: true`", ->
+ tmpl = "
+
+ "
+
+ div = $("
").html(tmpl)
+ select = div.find("select")
+
+ select.chosen
+ include_group_label_in_selected: true
+
+ # open the drop
+ container = div.find(".chosen-container")
+ container.trigger("mousedown")
+
+ xss_option = container.find(".active-result").last()
+ expect(xss_option.html()).toBe "an xss option"
+
+ # trigger the selection of the xss option
+ xss_option.trigger("mouseup")
+
+ # make sure the script tags are escaped correctly
+ label_html = container.find("a.chosen-single").html()
+ expect(label_html).toContain('</script><script>console.log(1)</script>')
diff --git a/spec/proto/bugfixes.spec.coffee b/spec/proto/bugfixes.spec.coffee
new file mode 100644
index 00000000000..004285de502
--- /dev/null
+++ b/spec/proto/bugfixes.spec.coffee
@@ -0,0 +1,32 @@
+describe "Bugfixes", ->
+ it "https://github.com/harvesthq/chosen/issues/2996 - XSS Vulnerability with `include_group_label_in_selected: true`", ->
+ tmpl = "
+
+ "
+ div = new Element("div")
+ document.body.insert(div)
+ div.innerHTML = tmpl
+
+ select = div.down("select")
+ new Chosen select,
+ include_group_label_in_selected: true
+
+ # open the drop
+ container = div.down(".chosen-container")
+ simulant.fire(container, "mousedown") # open the drop
+
+ xss_option = container.select(".active-result").last()
+ expect(xss_option.innerHTML).toBe "an xss option"
+
+ # trigger the selection of the xss option
+ simulant.fire(xss_option, "mouseup")
+
+ # make sure the script tags are escaped correctly
+ label_html = container.down("a.chosen-single").innerHTML
+ expect(label_html).toContain('</script><script>console.log(1)</script>')
+