CVE-2022-29531: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: An issue was discovered in MISP before 2.4.158. There is stored XSS in the event graph via a tag name.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2022-04-20T23:15Z
Repository: https://github.com/MISP/MISP
Language: PHP
Files changed: app/Controller/AppController.php, app/webroot/js/action_table.js
Commit date: 2022-04-18 00:49:21 +0200
Commit message: fix: [security] stored XSS fixed in event graph

- unsanitised javascript insertion of tag name in the filters

- as reported by Dawid Czarnecki of Zigrin Security on behalf of the Luxembourg Army

Diff: diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php
index bdc05ac47353..99ada8318973 100755
--- a/app/Controller/AppController.php
+++ b/app/Controller/AppController.php
@@ -32,11 +32,11 @@ class AppController extends Controller
      */
     public $defaultModel = '';
 
     public $helpers = array('OrgImg', 'FontAwesome', 'UserName');
 
-    private $__queryVersion = '138';
+    private $__queryVersion = '139';
     public $pyMispVersion = '2.4.157';
     public $phpmin = '7.2';
     public $phprec = '7.4';
     public $phptoonew = '8.0';
     public $pythonmin = '3.6';
diff --git a/app/webroot/js/action_table.js b/app/webroot/js/action_table.js
index 96a45b5bb373..2bd54af97925 100644
--- a/app/webroot/js/action_table.js
+++ b/app/webroot/js/action_table.js
@@ -1,371 +1,371 @@
 class ActionTable {
-	constructor(options) {
-		this.__globalCounter = 0;
-		this.options = options;
-		this.id = options.id;
-		this.container = options.container;
-		this.classes = options.classes;
-		this.table_title = options.title;
-		this.header = options.header;
-		this.onAddition = options.onAddition;
-		this.onRemove = options.onRemove;
-		this.header.push("Action");
-		this.row_num = this.header.length;
-		this.data = options.data === undefined ? [] : options.data;
-		this.tr_id_mapping = {};
-		this.control_items = options.control_items;
-		this.header_action_button = options.header_action_button === undefined ? {} : options.header_action_button;
-		if (options.header_action_button !== undefined) {
-			this.header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
-			this.additionEnabled = this.header_action_button.additionEnabled === undefined ? true : this.header_action_button.additionEnabled;
-			this.additionButtonDisabled = this.header_action_button.disabled === undefined ? false : this.header_action_button.disabled;
-		} else {
-			this.header_action_button_style = {};
-			this.additionEnabled = true;
-			this.additionButtonDisabled = false;
-		}
-
-		this.row_action_button = options.row_action_button === undefined ? {} : options.row_action_button;
-		if (options.row_action_button !== undefined) {
-			this.row_action_button_style = this.row_action_button.style === undefined ? {} : this.row_action_button.style;
-			this.removalEnabled = this.row_action_button.removalEnabled === undefined ? true : this.row_action_button.removalEnabled;
-		} else {
-			this.row_action_button_style = {};
-			this.removalEnabled = true;
-		}
-
-		this.selects = {};
-
-		this.__create_table();
-	}
-
-	__get_uniq_index() {
-		this.__globalCounter++;
-		return this.__globalCounter-1;
-	}
-
-	add_row(row) {
-		if (!this.__data_already_exists(row)) {
-			var id = this.__add_row(row);
-			this.tr_id_mapping[this.data.length] = id;
-			this.data.push(row);
-		}
-	}
-
-	delete_row(row_id) {
-		var tr = document.getElementById(row_id);
-		var array = this.__get_array_from_DOM_row(tr);
-		var data_index = this.__find_array_index(array, this.data);
-		tr.outerHTML = "";
-		this.data.splice(data_index, 1);
-	}
-
-	delete_row_index(row_pos) {
-		var tr = this.get_DOM_row(row_pos);
-		var array = this.__get_array_from_DOM_row(tr);
-		var data_index = this.__find_array_index(array, this.data);
-		tr.outerHTML = "";
-		this.data.splice(data_index, 1);
-	}
-
-	get_DOM_row(row_pos) {
-		var row_id = this.tr_id_mapping[row_pos];
-		var tr = document.getElementById(row_id);
-		return tr;
-	}
-
-	get_data() {
-		return this.data;
-	}
-
-	clear_table() {
-		var dataLength = this.data.length;
-		for (var i=0; i<dataLength; i++) {
-			this.delete_row_index(i);
-		}
-	}
-
-	set_table_data(data) {
-		this.clear_table();
-		for (var i in data) {
-			this.add_row(data[i]);
-		}
-	}
-
-	add_options(id, values) {
-		var select = this.selects[id];
-		var selected_value = select.value;
-		select.innerHTML = ""; // ensure uniqueness
-		this.__add_options_to_select(select, values);
-		select.value = selected_value;
-	}
-
-	__get_array_from_DOM_row(tr) {
-		var children = tr.children;
-		var array = [];
-		for (var i = 0; i < children.length-1; i++) {
-			array.push(children[i].innerText);
-		}
-		return array;
-	}
-
-	__data_already_exists(data) {
-		return this.__find_array_index(data, this.data) >= 0;
-	}
-
-	__find_array_index(value, array) {
-		for (var i in array) {
-			if (JSON.stringify(array[i]) === JSON.stringify(value)) { // compare array
-				return i;
-			}
-		}
-		return -1;
-	}
-
-	__create_table() {
-		if (this.table_title !== undefined) {
-			var label = document.createElement('label');
-			label.innerHTML = this.table_title;
-			this.container.appendChild(label);
-		}
-		this.form = document.createElement('form');
-		this.table = document.createElement('table');
-		this.table.classList.add("table", "table-bordered", "action-table");
-		if (this.classes !== undefined) {
-			for (var i in this.classes) {
-				this.table.classList.add(this.classes[i]);
-			}
-		}
-		this.thead = document.createElement('thead');
-		this.tbody = document.createElement('tbody');
-		var trHead = document.createElement('tr');
-		for (var col of this.header) {
-			var th = document.createElement('th');
-			th.innerHTML = col;
-			trHead.appendChild(th);
-		}
-		this.thead.appendChild(trHead);
-
-		this.__add_control_row();
-
-		for (var row of this.data) {
-			this.__add_row(row);
-		}
-		this.table.appendChild(this.thead);
-		this.table.appendChild(this.tbody);
-		this.form.appendChild(this.table);
-		this.container.appendChild(this.form);
-	}
-
-	__add_row(row) {
-		var tr = document.createElement('tr');
-		tr.id = "tr_" + this.__uuidv4();
-		for (var col of row) {
-			var td = document.createElement('td');
-			td.innerHTML = col;
-			tr.appendChild(td);
-		}
-		this.__add_action_button(tr);
-		this.tbody.appendChild(tr);
-		return tr.id;
-	}
-
-	__add_control_row() {
-		var tr = document.createElement('tr');
-		for (var itemOption of this.control_items) {
-			var td = document.createElement('td');
-			var item = this.__add_control_item(itemOption);
-			if (itemOption.colspan !== undefined) {
-				td.colSpan = itemOption.colspan;
-			}
-			td.appendChild(item);
-			tr.appendChild(td);
-		}
-		var td = document.createElement('td');
-
-		var btn = document.createElement('button');
-		var header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
-		if (header_action_button_style.type !== undefined) {
-			btn.classList.add("btn", "btn-"+header_action_button_style.type);
-		} else {
-			btn.classList.add("btn", "btn-primary");
-		}
-		if (header_action_button_style.tooltip !== undefined) {
-			btn.title = header_action_button_style.tooltip;
-		}
-		if (header_action_button_style.icon !== undefined) {
-			btn.innerHTML = '<span class="fa '+header_action_button_style.icon+'"></span>';
-		} else {
-			btn.innerHTML = '<span class="fa fa-plus-square"></span>';
-		}
-		btn.type = "button";
-		btn.disabled = this.additionButtonDisabled;
-
-		var that = this;
-		btn.addEventListener("click", function(evt) {
-			var data = [];
-			for (var elem of that.form.elements) {
-				if (elem.classList.contains('form-group')) {
-					data.push(elem.value);
-				}
-			}
-			if (that.additionEnabled) {
-				that.add_row(data);
-			}
-			if (that.onAddition !== undefined) {
-				that.onAddition(data, that);
-			}
-		});
-
-		td.appendChild(btn);
-
-		tr.appendChild(td);
-		this.thead.appendChild(tr);
-	}
-
-	__add_control_item(options) {
-		var item;
-		switch(options.DOMType) {
-			case "select":
-				item = this.__create_select(options.item_options);
-				this.selects[item.id] = item;
-				break;
-			case "input":
-				item = this.__create_input(options.item_options);
-				break;
-			case "empty":
-				item = this.__create_empty(options.item_options);
-				break;
-			default:
-				break;
-		}
-		return item;
-	}
-
-	__add_action_button(tr) {
-		var that = this;
-		var td = document.createElement('td');
-		var btn = document.createElement('button');
-		btn.classList.add("btn", "btn-danger");
-		btn.innerHTML = '<span class="fa fa-trash"></span>';
-		btn.type = "button";
-		btn.setAttribute('rowID', tr.id);
-		if (that.row_action_button_style.tooltip !== undefined) {
-			btn.title = that.row_action_button_style.tooltip;
-		}
-		if (that.row_action_button_style.style !== undefined) {
-			btn.style = that.row_action_button_style.style;
-		}
-		var that = this;
-		btn.addEventListener("click", function(evt) {
-			if (that.onRemove !== undefined) {
-				var tr = document.getElementById(this.getAttribute('rowID'));
-				var data = that.__get_array_from_DOM_row(tr);
-				that.onRemove(data, that);
-			}
-			if (that.removalEnabled) {
-				that.delete_row(this.getAttribute('rowID'));
-			}
-		});
-		td.appendChild(btn);
-
-		if (that.row_action_button.others !== undefined) {
-			for (var i in that.row_action_button.others) {
-				var newBtnOptions = that.row_action_button.others[i];
-
-				var btn_style = newBtnOptions.style !== undefined ? newBtnOptions.style : {};
-				var btn = document.createElement('button');
-				btn.type = "button";
-				if (btn_style.type !== undefined) {
-					btn.classList.add("btn", "btn-"+btn_style.type);
-				} else {
-					btn.classList.add("btn", "btn-primary");
-				}
-				if (btn_style.icon !== undefined) {
-					btn.innerHTML = '<span class="fa '+btn_style.icon+'"></span>';
-				} else {
-					btn.innerHTML = '<span class="fa fa-check"></span>';
-				}
-				if (btn_style.title !== undefined) {
-					btn.title = btn_style.title;
-				}
-				if (btn_style.style !== undefined) {
-					btn.style = btn_style.style+"margin-left: 3px";
-				} else {
-					btn.style = "margin-left: 3px";
-				}
-				btn.setAttribute('rowID', tr.id);
-				if (newBtnOptions.event !== undefined) {
-					btn.addEventListener("click", function(evt) {
-						var tr = document.getElementById(this.getAttribute('rowID'));
-						var data = that.__get_array_from_DOM_row(tr);
-						newBtnOptions.event(data, that);
-					});
-				}
-				td.appendChild(btn);
-			}
-		}
-
-		tr.appendChild(td);
-	}
-
-	__create_empty(options) {
-		var empty = document.createElement('span');
-		empty.classList.add("form-group");
-		empty.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
-		return empty;
-	}
-
-	__create_input(options) {
-		var input = document.createElement('input');
-		input.classList.add("form-group");
-		input.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
-		if (options.style !== undefined) {
-			input.style = options.style;
-		}
-		if (options.placeholder !== undefined) {
-			input.placeholder = options.placeholder;
-		}
-		if (options.disabled !== undefined) {
-			input.disabled = options.disabled;
-		}
-		if (options.typeahead !== undefined) {
-			var typeaheadOption = options.typeahead;
-			$('#'+input.id).typeahead(typeaheadOption);
-		}
-		return input;
-	}
-
-	__create_select(select_options) {
-		var select = document.createElement('select');
-		select.classList.add("form-group");
-		select.id = select_options.id !== undefined ? select_options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
-		select.style.width = "100%";
-		this.__add_options_to_select(select, select_options.options);
-		if(select_options.default !== undefined) {
-			select.value = select_options.default;
-		}
-		return select;
-	}
-
-	__add_options_to_select(select, options) {
-		for(var value of options) {
-			var option = document.createElement('option');
-			if (Array.isArray(value)) { // array of type [value, text]
-				option.value = value[1];
-				option.innerHTML = value[1];
-			} else { // only value, text=value
-				option.value = value;
-				option.innerHTML = value;
-			}
-			select.appendChild(option);
-		}
-	}
-
-	__uuidv4() {
-		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
-			var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
-			return v.toString(16);
-		});
-	}
+    constructor(options) {
+        this.__globalCounter = 0;
+        this.options = options;
+        this.id = options.id;
+        this.container = options.container;
+        this.classes = options.classes;
+        this.table_title = options.title;
+        this.header = options.header;
+        this.onAddition = options.onAddition;
+        this.onRemove = options.onRemove;
+        this.header.push("Action");
+        this.row_num = this.header.length;
+        this.data = options.data === undefined ? [] : options.data;
+        this.tr_id_mapping = {};
+        this.control_items = options.control_items;
+        this.header_action_button = options.header_action_button === undefined ? {} : options.header_action_button;
+        if (options.header_action_button !== undefined) {
+            this.header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
+            this.additionEnabled = this.header_action_button.additionEnabled === undefined ? true : this.header_action_button.additionEnabled;
+            this.additionButtonDisabled = this.header_action_button.disabled === undefined ? false : this.header_action_button.disabled;
+        } else {
+            this.header_action_button_style = {};
+            this.additionEnabled = true;
+            this.additionButtonDisabled = false;
+        }
+
+        this.row_action_button = options.row_action_button === undefined ? {} : options.row_action_button;
+        if (options.row_action_button !== undefined) {
+            this.row_action_button_style = this.row_action_button.style === undefined ? {} : this.row_action_button.style;
+            this.removalEnabled = this.row_action_button.removalEnabled === undefined ? true : this.row_action_button.removalEnabled;
+        } else {
+            this.row_action_button_style = {};
+            this.removalEnabled = true;
+        }
+
+        this.selects = {};
+
+        this.__create_table();
+    }
+
+    __get_uniq_index() {
+        this.__globalCounter++;
+        return this.__globalCounter-1;
+    }
+
+    add_row(row) {
+        if (!this.__data_already_exists(row)) {
+            var id = this.__add_row(row);
+            this.tr_id_mapping[this.data.length] = id;
+            this.data.push(row);
+        }
+    }
+
+    delete_row(row_id) {
+        var tr = document.getElementById(row_id);
+        var array = this.__get_array_from_DOM_row(tr);
+        var data_index = this.__find_array_index(array, this.data);
+        tr.outerHTML = "";
+        this.data.splice(data_index, 1);
+    }
+
+    delete_row_index(row_pos) {
+        var tr = this.get_DOM_row(row_pos);
+        var array = this.__get_array_from_DOM_row(tr);
+        var data_index = this.__find_array_index(array, this.data);
+        tr.outerHTML = "";
+        this.data.splice(data_index, 1);
+    }
+
+    get_DOM_row(row_pos) {
+        var row_id = this.tr_id_mapping[row_pos];
+        var tr = document.getElementById(row_id);
+        return tr;
+    }
+
+    get_data() {
+        return this.data;
+    }
+
+    clear_table() {
+        var dataLength = this.data.length;
+        for (var i=0; i<dataLength; i++) {
+            this.delete_row_index(i);
+        }
+    }
+
+    set_table_data(data) {
+        this.clear_table();
+        for (var i in data) {
+            this.add_row(data[i]);
+        }
+    }
+
+    add_options(id, values) {
+        var select = this.selects[id];
+        var selected_value = select.value;
+        select.innerHTML = ""; // ensure uniqueness
+        this.__add_options_to_select(select, values);
+        select.value = selected_value;
+    }
+
+    __get_array_from_DOM_row(tr) {
+        var children = tr.children;
+        var array = [];
+        for (var i = 0; i < children.length-1; i++) {
+            array.push(children[i].innerText);
+        }
+        return array;
+    }
+
+    __data_already_exists(data) {
+        return this.__find_array_index(data, this.data) >= 0;
+    }
+
+    __find_array_index(value, array) {
+        for (var i in array) {
+            if (JSON.stringify(array[i]) === JSON.stringify(value)) { // compare array
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    __create_table() {
+        if (this.table_title !== undefined) {
+            var label = document.createElement('label');
+            label.innerHTML = this.table_title;
+            this.container.appendChild(label);
+        }
+        this.form = document.createElement('form');
+        this.table = document.createElement('table');
+        this.table.classList.add("table", "table-bordered", "action-table");
+        if (this.classes !== undefined) {
+            for (var i in this.classes) {
+                this.table.classList.add(this.classes[i]);
+            }
+        }
+        this.thead = document.createElement('thead');
+        this.tbody = document.createElement('tbody');
+        var trHead = document.createElement('tr');
+        for (var col of this.header) {
+            var th = document.createElement('th');
+            th.innerHTML = col;
+            trHead.appendChild(th);
+        }
+        this.thead.appendChild(trHead);
+
+        this.__add_control_row();
+
+        for (var row of this.data) {
+            this.__add_row(row);
+        }
+        this.table.appendChild(this.thead);
+        this.table.appendChild(this.tbody);
+        this.form.appendChild(this.table);
+        this.container.appendChild(this.form);
+    }
+
+    __add_row(row) {
+        var tr = document.createElement('tr');
+        tr.id = "tr_" + this.__uuidv4();
+        for (var col of row) {
+            var td = document.createElement('td');
+            td.innerHTML = col;
+            tr.appendChild(td);
+        }
+        this.__add_action_button(tr);
+        this.tbody.appendChild(tr);
+        return tr.id;
+    }
+
+    __add_control_row() {
+        var tr = document.createElement('tr');
+        for (var itemOption of this.control_items) {
+            var td = document.createElement('td');
+            var item = this.__add_control_item(itemOption);
+            if (itemOption.colspan !== undefined) {
+                td.colSpan = itemOption.colspan;
+            }
+            td.appendChild(item);
+            tr.appendChild(td);
+        }
+        var td = document.createElement('td');
+
+        var btn = document.createElement('button');
+        var header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
+        if (header_action_button_style.type !== undefined) {
+            btn.classList.add("btn", "btn-"+header_action_button_style.type);
+        } else {
+            btn.classList.add("btn", "btn-primary");
+        }
+        if (header_action_button_style.tooltip !== undefined) {
+            btn.title = header_action_button_style.tooltip;
+        }
+        if (header_action_button_style.icon !== undefined) {
+            btn.innerHTML = '<span class="fa '+header_action_button_style.icon+'"></span>';
+        } else {
+            btn.innerHTML = '<span class="fa fa-plus-square"></span>';
+        }
+        btn.type = "button";
+        btn.disabled = this.additionButtonDisabled;
+
+        var that = this;
+        btn.addEventListener("click", function(evt) {
+            var data = [];
+            for (var elem of that.form.elements) {
+                if (elem.classList.contains('form-group')) {
+                    data.push(elem.value);
+                }
+            }
+            if (that.additionEnabled) {
+                that.add_row(data);
+            }
+            if (that.onAddition !== undefined) {
+                that.onAddition(data, that);
+            }
+        });
+
+        td.appendChild(btn);
+
+        tr.appendChild(td);
+        this.thead.appendChild(tr);
+    }
+
+    __add_control_item(options) {
+        var item;
+        switch(options.DOMType) {
+            case "select":
+                item = this.__create_select(options.item_options);
+                this.selects[item.id] = item;
+                break;
+            case "input":
+                item = this.__create_input(options.item_options);
+                break;
+            case "empty":
+                item = this.__create_empty(options.item_options);
+                break;
+            default:
+                break;
+        }
+        return item;
+    }
+
+    __add_action_button(tr) {
+        var that = this;
+        var td = document.createElement('td');
+        var btn = document.createElement('button');
+        btn.classList.add("btn", "btn-danger");
+        btn.innerHTML = '<span class="fa fa-trash"></span>';
+        btn.type = "button";
+        btn.setAttribute('rowID', tr.id);
+        if (that.row_action_button_style.tooltip !== undefined) {
+            btn.title = that.row_action_button_style.tooltip;
+        }
+        if (that.row_action_button_style.style !== undefined) {
+            btn.style = that.row_action_button_style.style;
+        }
+        var that = this;
+        btn.addEventListener("click", function(evt) {
+            if (that.onRemove !== undefined) {
+                var tr = document.getElementById(this.getAttribute('rowID'));
+                var data = that.__get_array_from_DOM_row(tr);
+                that.onRemove(data, that);
+            }
+            if (that.removalEnabled) {
+                that.delete_row(this.getAttribute('rowID'));
+            }
+        });
+        td.appendChild(btn);
+
+        if (that.row_action_button.others !== undefined) {
+            for (var i in that.row_action_button.others) {
+                var newBtnOptions = that.row_action_button.others[i];
+
+                var btn_style = newBtnOptions.style !== undefined ? newBtnOptions.style : {};
+                var btn = document.createElement('button');
+                btn.type = "button";
+                if (btn_style.type !== undefined) {
+                    btn.classList.add("btn", "btn-"+btn_style.type);
+                } else {
+                    btn.classList.add("btn", "btn-primary");
+                }
+                if (btn_style.icon !== undefined) {
+                    btn.innerHTML = '<span class="fa '+btn_style.icon+'"></span>';
+                } else {
+                    btn.innerHTML = '<span class="fa fa-check"></span>';
+                }
+                if (btn_style.title !== undefined) {
+                    btn.title = btn_style.title;
+                }
+                if (btn_style.style !== undefined) {
+                    btn.style = btn_style.style+"margin-left: 3px";
+                } else {
+                    btn.style = "margin-left: 3px";
+                }
+                btn.setAttribute('rowID', tr.id);
+                if (newBtnOptions.event !== undefined) {
+                    btn.addEventListener("click", function(evt) {
+                        var tr = document.getElementById(this.getAttribute('rowID'));
+                        var data = that.__get_array_from_DOM_row(tr);
+                        newBtnOptions.event(data, that);
+                    });
+                }
+                td.appendChild(btn);
+            }
+        }
+
+        tr.appendChild(td);
+    }
+
+    __create_empty(options) {
+        var empty = document.createElement('span');
+        empty.classList.add("form-group");
+        empty.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
+        return empty;
+    }
+
+    __create_input(options) {
+        var input = document.createElement('input');
+        input.classList.add("form-group");
+        input.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
+        if (options.style !== undefined) {
+            input.style = options.style;
+        }
+        if (options.placeholder !== undefined) {
+            input.placeholder = options.placeholder;
+        }
+        if (options.disabled !== undefined) {
+            input.disabled = options.disabled;
+        }
+        if (options.typeahead !== undefined) {
+            var typeaheadOption = options.typeahead;
+            $('#'+input.id).typeahead(typeaheadOption);
+        }
+        return input;
+    }
+
+    __create_select(select_options) {
+        var select = document.createElement('select');
+        select.classList.add("form-group");
+        select.id = select_options.id !== undefined ? select_options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
+        select.style.width = "100%";
+        this.__add_options_to_select(select, select_options.options);
+        if(select_options.default !== undefined) {
+            select.value = select_options.default;
+        }
+        return select;
+    }
+
+    __add_options_to_select(select, options) {
+        for(var value of options) {
+            var option = document.createElement('option');
+            if (Array.isArray(value)) { // array of type [value, text]
+                option.value = value[1];
+                option.textContent = value[1];
+            } else { // only value, text=value
+                option.value = value;
+                option.textContent = value;
+            }
+            select.appendChild(option);
+        }
+    }
+
+    __uuidv4() {
+        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+            return v.toString(16);
+        });
+    }
 }

Vulnerable code:     private $__queryVersion = '138';
	constructor(options) {
		this.__globalCounter = 0;
		this.options = options;
		this.id = options.id;
		this.container = options.container;
		this.classes = options.classes;
		this.table_title = options.title;
		this.header = options.header;
		this.onAddition = options.onAddition;
		this.onRemove = options.onRemove;
		this.header.push("Action");
		this.row_num = this.header.length;
		this.data = options.data === undefined ? [] : options.data;
		this.tr_id_mapping = {};
		this.control_items = options.control_items;
		this.header_action_button = options.header_action_button === undefined ? {} : options.header_action_button;
		if (options.header_action_button !== undefined) {
			this.header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
			this.additionEnabled = this.header_action_button.additionEnabled === undefined ? true : this.header_action_button.additionEnabled;
			this.additionButtonDisabled = this.header_action_button.disabled === undefined ? false : this.header_action_button.disabled;
		} else {
			this.header_action_button_style = {};
			this.additionEnabled = true;
			this.additionButtonDisabled = false;
		}

		this.row_action_button = options.row_action_button === undefined ? {} : options.row_action_button;
		if (options.row_action_button !== undefined) {
			this.row_action_button_style = this.row_action_button.style === undefined ? {} : this.row_action_button.style;
			this.removalEnabled = this.row_action_button.removalEnabled === undefined ? true : this.row_action_button.removalEnabled;
		} else {
			this.row_action_button_style = {};
			this.removalEnabled = true;
		}

		this.selects = {};

		this.__create_table();
	}

	__get_uniq_index() {
		this.__globalCounter++;
		return this.__globalCounter-1;
	}

	add_row(row) {
		if (!this.__data_already_exists(row)) {
			var id = this.__add_row(row);
			this.tr_id_mapping[this.data.length] = id;
			this.data.push(row);
		}
	}

	delete_row(row_id) {
		var tr = document.getElementById(row_id);
		var array = this.__get_array_from_DOM_row(tr);
		var data_index = this.__find_array_index(array, this.data);
		tr.outerHTML = "";
		this.data.splice(data_index, 1);
	}

	delete_row_index(row_pos) {
		var tr = this.get_DOM_row(row_pos);
		var array = this.__get_array_from_DOM_row(tr);
		var data_index = this.__find_array_index(array, this.data);
		tr.outerHTML = "";
		this.data.splice(data_index, 1);
	}

	get_DOM_row(row_pos) {
		var row_id = this.tr_id_mapping[row_pos];
		var tr = document.getElementById(row_id);
		return tr;
	}

	get_data() {
		return this.data;
	}

	clear_table() {
		var dataLength = this.data.length;
		for (var i=0; i<dataLength; i++) {
			this.delete_row_index(i);
		}
	}

	set_table_data(data) {
		this.clear_table();
		for (var i in data) {
			this.add_row(data[i]);
		}
	}

	add_options(id, values) {
		var select = this.selects[id];
		var selected_value = select.value;
		select.innerHTML = ""; // ensure uniqueness
		this.__add_options_to_select(select, values);
		select.value = selected_value;
	}

	__get_array_from_DOM_row(tr) {
		var children = tr.children;
		var array = [];
		for (var i = 0; i < children.length-1; i++) {
			array.push(children[i].innerText);
		}
		return array;
	}

	__data_already_exists(data) {
		return this.__find_array_index(data, this.data) >= 0;
	}

	__find_array_index(value, array) {
		for (var i in array) {
			if (JSON.stringify(array[i]) === JSON.stringify(value)) { // compare array
				return i;
			}
		}
		return -1;
	}

	__create_table() {
		if (this.table_title !== undefined) {
			var label = document.createElement('label');
			label.innerHTML = this.table_title;
			this.container.appendChild(label);
		}
		this.form = document.createElement('form');
		this.table = document.createElement('table');
		this.table.classList.add("table", "table-bordered", "action-table");
		if (this.classes !== undefined) {
			for (var i in this.classes) {
				this.table.classList.add(this.classes[i]);
			}
		}
		this.thead = document.createElement('thead');
		this.tbody = document.createElement('tbody');
		var trHead = document.createElement('tr');
		for (var col of this.header) {
			var th = document.createElement('th');
			th.innerHTML = col;
			trHead.appendChild(th);
		}
		this.thead.appendChild(trHead);

		this.__add_control_row();

		for (var row of this.data) {
			this.__add_row(row);
		}
		this.table.appendChild(this.thead);
		this.table.appendChild(this.tbody);
		this.form.appendChild(this.table);
		this.container.appendChild(this.form);
	}

	__add_row(row) {
		var tr = document.createElement('tr');
		tr.id = "tr_" + this.__uuidv4();
		for (var col of row) {
			var td = document.createElement('td');
			td.innerHTML = col;
			tr.appendChild(td);
		}
		this.__add_action_button(tr);
		this.tbody.appendChild(tr);
		return tr.id;
	}

	__add_control_row() {
		var tr = document.createElement('tr');
		for (var itemOption of this.control_items) {
			var td = document.createElement('td');
			var item = this.__add_control_item(itemOption);
			if (itemOption.colspan !== undefined) {
				td.colSpan = itemOption.colspan;
			}
			td.appendChild(item);
			tr.appendChild(td);
		}
		var td = document.createElement('td');

		var btn = document.createElement('button');
		var header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
		if (header_action_button_style.type !== undefined) {
			btn.classList.add("btn", "btn-"+header_action_button_style.type);
		} else {
			btn.classList.add("btn", "btn-primary");
		}
		if (header_action_button_style.tooltip !== undefined) {
			btn.title = header_action_button_style.tooltip;
		}
		if (header_action_button_style.icon !== undefined) {
			btn.innerHTML = '<span class="fa '+header_action_button_style.icon+'"></span>';
		} else {
			btn.innerHTML = '<span class="fa fa-plus-square"></span>';
		}
		btn.type = "button";
		btn.disabled = this.additionButtonDisabled;

		var that = this;
		btn.addEventListener("click", function(evt) {
			var data = [];
			for (var elem of that.form.elements) {
				if (elem.classList.contains('form-group')) {
					data.push(elem.value);
				}
			}
			if (that.additionEnabled) {
				that.add_row(data);
			}
			if (that.onAddition !== undefined) {
				that.onAddition(data, that);
			}
		});

		td.appendChild(btn);

		tr.appendChild(td);
		this.thead.appendChild(tr);
	}

	__add_control_item(options) {
		var item;
		switch(options.DOMType) {
			case "select":
				item = this.__create_select(options.item_options);
				this.selects[item.id] = item;
				break;
			case "input":
				item = this.__create_input(options.item_options);
				break;
			case "empty":
				item = this.__create_empty(options.item_options);
				break;
			default:
				break;
		}
		return item;
	}

	__add_action_button(tr) {
		var that = this;
		var td = document.createElement('td');
		var btn = document.createElement('button');
		btn.classList.add("btn", "btn-danger");
		btn.innerHTML = '<span class="fa fa-trash"></span>';
		btn.type = "button";
		btn.setAttribute('rowID', tr.id);
		if (that.row_action_button_style.tooltip !== undefined) {
			btn.title = that.row_action_button_style.tooltip;
		}
		if (that.row_action_button_style.style !== undefined) {
			btn.style = that.row_action_button_style.style;
		}
		var that = this;
		btn.addEventListener("click", function(evt) {
			if (that.onRemove !== undefined) {
				var tr = document.getElementById(this.getAttribute('rowID'));
				var data = that.__get_array_from_DOM_row(tr);
				that.onRemove(data, that);
			}
			if (that.removalEnabled) {
				that.delete_row(this.getAttribute('rowID'));
			}
		});
		td.appendChild(btn);

		if (that.row_action_button.others !== undefined) {
			for (var i in that.row_action_button.others) {
				var newBtnOptions = that.row_action_button.others[i];

				var btn_style = newBtnOptions.style !== undefined ? newBtnOptions.style : {};
				var btn = document.createElement('button');
				btn.type = "button";
				if (btn_style.type !== undefined) {
					btn.classList.add("btn", "btn-"+btn_style.type);
				} else {
					btn.classList.add("btn", "btn-primary");
				}
				if (btn_style.icon !== undefined) {
					btn.innerHTML = '<span class="fa '+btn_style.icon+'"></span>';
				} else {
					btn.innerHTML = '<span class="fa fa-check"></span>';
				}
				if (btn_style.title !== undefined) {
					btn.title = btn_style.title;
				}
				if (btn_style.style !== undefined) {
					btn.style = btn_style.style+"margin-left: 3px";
				} else {
					btn.style = "margin-left: 3px";
				}
				btn.setAttribute('rowID', tr.id);
				if (newBtnOptions.event !== undefined) {
					btn.addEventListener("click", function(evt) {
						var tr = document.getElementById(this.getAttribute('rowID'));
						var data = that.__get_array_from_DOM_row(tr);
						newBtnOptions.event(data, that);
					});
				}
				td.appendChild(btn);
			}
		}

		tr.appendChild(td);
	}

	__create_empty(options) {
		var empty = document.createElement('span');
		empty.classList.add("form-group");
		empty.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
		return empty;
	}

	__create_input(options) {
		var input = document.createElement('input');
		input.classList.add("form-group");
		input.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
		if (options.style !== undefined) {
			input.style = options.style;
		}
		if (options.placeholder !== undefined) {
			input.placeholder = options.placeholder;
		}
		if (options.disabled !== undefined) {
			input.disabled = options.disabled;
		}
		if (options.typeahead !== undefined) {
			var typeaheadOption = options.typeahead;
			$('#'+input.id).typeahead(typeaheadOption);
		}
		return input;
	}

	__create_select(select_options) {
		var select = document.createElement('select');
		select.classList.add("form-group");
		select.id = select_options.id !== undefined ? select_options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
		select.style.width = "100%";
		this.__add_options_to_select(select, select_options.options);
		if(select_options.default !== undefined) {
			select.value = select_options.default;
		}
		return select;
	}

	__add_options_to_select(select, options) {
		for(var value of options) {
			var option = document.createElement('option');
			if (Array.isArray(value)) { // array of type [value, text]
				option.value = value[1];
				option.innerHTML = value[1];
			} else { // only value, text=value
				option.value = value;
				option.innerHTML = value;
			}
			select.appendChild(option);
		}
	}

	__uuidv4() {
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
			var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
			return v.toString(16);
		});
	}
Fixed code:     private $__queryVersion = '139';
    constructor(options) {
        this.__globalCounter = 0;
        this.options = options;
        this.id = options.id;
        this.container = options.container;
        this.classes = options.classes;
        this.table_title = options.title;
        this.header = options.header;
        this.onAddition = options.onAddition;
        this.onRemove = options.onRemove;
        this.header.push("Action");
        this.row_num = this.header.length;
        this.data = options.data === undefined ? [] : options.data;
        this.tr_id_mapping = {};
        this.control_items = options.control_items;
        this.header_action_button = options.header_action_button === undefined ? {} : options.header_action_button;
        if (options.header_action_button !== undefined) {
            this.header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
            this.additionEnabled = this.header_action_button.additionEnabled === undefined ? true : this.header_action_button.additionEnabled;
            this.additionButtonDisabled = this.header_action_button.disabled === undefined ? false : this.header_action_button.disabled;
        } else {
            this.header_action_button_style = {};
            this.additionEnabled = true;
            this.additionButtonDisabled = false;
        }

        this.row_action_button = options.row_action_button === undefined ? {} : options.row_action_button;
        if (options.row_action_button !== undefined) {
            this.row_action_button_style = this.row_action_button.style === undefined ? {} : this.row_action_button.style;
            this.removalEnabled = this.row_action_button.removalEnabled === undefined ? true : this.row_action_button.removalEnabled;
        } else {
            this.row_action_button_style = {};
            this.removalEnabled = true;
        }

        this.selects = {};

        this.__create_table();
    }

    __get_uniq_index() {
        this.__globalCounter++;
        return this.__globalCounter-1;
    }

    add_row(row) {
        if (!this.__data_already_exists(row)) {
            var id = this.__add_row(row);
            this.tr_id_mapping[this.data.length] = id;
            this.data.push(row);
        }
    }

    delete_row(row_id) {
        var tr = document.getElementById(row_id);
        var array = this.__get_array_from_DOM_row(tr);
        var data_index = this.__find_array_index(array, this.data);
        tr.outerHTML = "";
        this.data.splice(data_index, 1);
    }

    delete_row_index(row_pos) {
        var tr = this.get_DOM_row(row_pos);
        var array = this.__get_array_from_DOM_row(tr);
        var data_index = this.__find_array_index(array, this.data);
        tr.outerHTML = "";
        this.data.splice(data_index, 1);
    }

    get_DOM_row(row_pos) {
        var row_id = this.tr_id_mapping[row_pos];
        var tr = document.getElementById(row_id);
        return tr;
    }

    get_data() {
        return this.data;
    }

    clear_table() {
        var dataLength = this.data.length;
        for (var i=0; i<dataLength; i++) {
            this.delete_row_index(i);
        }
    }

    set_table_data(data) {
        this.clear_table();
        for (var i in data) {
            this.add_row(data[i]);
        }
    }

    add_options(id, values) {
        var select = this.selects[id];
        var selected_value = select.value;
        select.innerHTML = ""; // ensure uniqueness
        this.__add_options_to_select(select, values);
        select.value = selected_value;
    }

    __get_array_from_DOM_row(tr) {
        var children = tr.children;
        var array = [];
        for (var i = 0; i < children.length-1; i++) {
            array.push(children[i].innerText);
        }
        return array;
    }

    __data_already_exists(data) {
        return this.__find_array_index(data, this.data) >= 0;
    }

    __find_array_index(value, array) {
        for (var i in array) {
            if (JSON.stringify(array[i]) === JSON.stringify(value)) { // compare array
                return i;
            }
        }
        return -1;
    }

    __create_table() {
        if (this.table_title !== undefined) {
            var label = document.createElement('label');
            label.innerHTML = this.table_title;
            this.container.appendChild(label);
        }
        this.form = document.createElement('form');
        this.table = document.createElement('table');
        this.table.classList.add("table", "table-bordered", "action-table");
        if (this.classes !== undefined) {
            for (var i in this.classes) {
                this.table.classList.add(this.classes[i]);
            }
        }
        this.thead = document.createElement('thead');
        this.tbody = document.createElement('tbody');
        var trHead = document.createElement('tr');
        for (var col of this.header) {
            var th = document.createElement('th');
            th.innerHTML = col;
            trHead.appendChild(th);
        }
        this.thead.appendChild(trHead);

        this.__add_control_row();

        for (var row of this.data) {
            this.__add_row(row);
        }
        this.table.appendChild(this.thead);
        this.table.appendChild(this.tbody);
        this.form.appendChild(this.table);
        this.container.appendChild(this.form);
    }

    __add_row(row) {
        var tr = document.createElement('tr');
        tr.id = "tr_" + this.__uuidv4();
        for (var col of row) {
            var td = document.createElement('td');
            td.innerHTML = col;
            tr.appendChild(td);
        }
        this.__add_action_button(tr);
        this.tbody.appendChild(tr);
        return tr.id;
    }

    __add_control_row() {
        var tr = document.createElement('tr');
        for (var itemOption of this.control_items) {
            var td = document.createElement('td');
            var item = this.__add_control_item(itemOption);
            if (itemOption.colspan !== undefined) {
                td.colSpan = itemOption.colspan;
            }
            td.appendChild(item);
            tr.appendChild(td);
        }
        var td = document.createElement('td');

        var btn = document.createElement('button');
        var header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style;
        if (header_action_button_style.type !== undefined) {
            btn.classList.add("btn", "btn-"+header_action_button_style.type);
        } else {
            btn.classList.add("btn", "btn-primary");
        }
        if (header_action_button_style.tooltip !== undefined) {
            btn.title = header_action_button_style.tooltip;
        }
        if (header_action_button_style.icon !== undefined) {
            btn.innerHTML = '<span class="fa '+header_action_button_style.icon+'"></span>';
        } else {
            btn.innerHTML = '<span class="fa fa-plus-square"></span>';
        }
        btn.type = "button";
        btn.disabled = this.additionButtonDisabled;

        var that = this;
        btn.addEventListener("click", function(evt) {
            var data = [];
            for (var elem of that.form.elements) {
                if (elem.classList.contains('form-group')) {
                    data.push(elem.value);
                }
            }
            if (that.additionEnabled) {
                that.add_row(data);
            }
            if (that.onAddition !== undefined) {
                that.onAddition(data, that);
            }
        });

        td.appendChild(btn);

        tr.appendChild(td);
        this.thead.appendChild(tr);
    }

    __add_control_item(options) {
        var item;
        switch(options.DOMType) {
            case "select":
                item = this.__create_select(options.item_options);
                this.selects[item.id] = item;
                break;
            case "input":
                item = this.__create_input(options.item_options);
                break;
            case "empty":
                item = this.__create_empty(options.item_options);
                break;
            default:
                break;
        }
        return item;
    }

    __add_action_button(tr) {
        var that = this;
        var td = document.createElement('td');
        var btn = document.createElement('button');
        btn.classList.add("btn", "btn-danger");
        btn.innerHTML = '<span class="fa fa-trash"></span>';
        btn.type = "button";
        btn.setAttribute('rowID', tr.id);
        if (that.row_action_button_style.tooltip !== undefined) {
            btn.title = that.row_action_button_style.tooltip;
        }
        if (that.row_action_button_style.style !== undefined) {
            btn.style = that.row_action_button_style.style;
        }
        var that = this;
        btn.addEventListener("click", function(evt) {
            if (that.onRemove !== undefined) {
                var tr = document.getElementById(this.getAttribute('rowID'));
                var data = that.__get_array_from_DOM_row(tr);
                that.onRemove(data, that);
            }
            if (that.removalEnabled) {
                that.delete_row(this.getAttribute('rowID'));
            }
        });
        td.appendChild(btn);

        if (that.row_action_button.others !== undefined) {
            for (var i in that.row_action_button.others) {
                var newBtnOptions = that.row_action_button.others[i];

                var btn_style = newBtnOptions.style !== undefined ? newBtnOptions.style : {};
                var btn = document.createElement('button');
                btn.type = "button";
                if (btn_style.type !== undefined) {
                    btn.classList.add("btn", "btn-"+btn_style.type);
                } else {
                    btn.classList.add("btn", "btn-primary");
                }
                if (btn_style.icon !== undefined) {
                    btn.innerHTML = '<span class="fa '+btn_style.icon+'"></span>';
                } else {
                    btn.innerHTML = '<span class="fa fa-check"></span>';
                }
                if (btn_style.title !== undefined) {
                    btn.title = btn_style.title;
                }
                if (btn_style.style !== undefined) {
                    btn.style = btn_style.style+"margin-left: 3px";
                } else {
                    btn.style = "margin-left: 3px";
                }
                btn.setAttribute('rowID', tr.id);
                if (newBtnOptions.event !== undefined) {
                    btn.addEventListener("click", function(evt) {
                        var tr = document.getElementById(this.getAttribute('rowID'));
                        var data = that.__get_array_from_DOM_row(tr);
                        newBtnOptions.event(data, that);
                    });
                }
                td.appendChild(btn);
            }
        }

        tr.appendChild(td);
    }

    __create_empty(options) {
        var empty = document.createElement('span');
        empty.classList.add("form-group");
        empty.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
        return empty;
    }

    __create_input(options) {
        var input = document.createElement('input');
        input.classList.add("form-group");
        input.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
        if (options.style !== undefined) {
            input.style = options.style;
        }
        if (options.placeholder !== undefined) {
            input.placeholder = options.placeholder;
        }
        if (options.disabled !== undefined) {
            input.disabled = options.disabled;
        }
        if (options.typeahead !== undefined) {
            var typeaheadOption = options.typeahead;
            $('#'+input.id).typeahead(typeaheadOption);
        }
        return input;
    }

    __create_select(select_options) {
        var select = document.createElement('select');
        select.classList.add("form-group");
        select.id = select_options.id !== undefined ? select_options.id : 'actionTable_controlSelect_'+this.__get_uniq_index();
        select.style.width = "100%";
        this.__add_options_to_select(select, select_options.options);
        if(select_options.default !== undefined) {
            select.value = select_options.default;
        }
        return select;
    }

    __add_options_to_select(select, options) {
        for(var value of options) {
            var option = document.createElement('option');
            if (Array.isArray(value)) { // array of type [value, text]
                option.value = value[1];
                option.textContent = value[1];
            } else { // only value, text=value
                option.value = value;
                option.textContent = value;
            }
            select.appendChild(option);
        }
    }

    __uuidv4() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }