Skip to content

Commit 9820169

Browse files
🔒 fix: replace unsafe innerHTML assignments with replaceChildren()
Replaced all occurrences of unsafe `innerHTML = ""` and redundant child removal loops with the modern `Element.replaceChildren()` API in `options/options.js`. This addresses security hygiene issues and prevents potential XSS vectors while standardizing element clearing logic. Co-authored-by: cmuench <211294+cmuench@users.noreply.github.com>
1 parent a9ec388 commit 9820169

1 file changed

Lines changed: 8 additions & 18 deletions

File tree

options/options.js

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,11 @@ const loadWebhooks = async () => {
7272
const normalizedWebhooks = webhooks.map(normalizeWebhookRecord);
7373
const list = document.getElementById("webhook-list");
7474
const message = document.getElementById("no-webhooks-message");
75-
list.innerHTML = "";
76-
77-
// Clear the webhook list safely
78-
while (list.firstChild) {
79-
list.removeChild(list.firstChild);
80-
}
75+
list.replaceChildren();
8176

8277
// Populate group dropdown safely
8378
const groupSelect = document.getElementById("webhook-group");
84-
// Remove all children
85-
while (groupSelect.firstChild) {
86-
groupSelect.removeChild(groupSelect.firstChild);
87-
}
79+
groupSelect.replaceChildren();
8880
const defaultOption = document.createElement("option");
8981
defaultOption.value = "";
9082
defaultOption.selected = true;
@@ -167,7 +159,7 @@ const loadGroups = async () => {
167159
// Function to render groups in the group management modal
168160
const renderGroups = async () => {
169161
const groups = await loadGroups();
170-
groupsList.innerHTML = "";
162+
groupsList.replaceChildren();
171163

172164
groups.forEach(group => {
173165
const listItem = document.createElement("li");
@@ -326,9 +318,7 @@ const renderGroups = async () => {
326318
const groupSelect = document.getElementById("webhook-group");
327319
const selectedValue = groupSelect.value;
328320
// Clear existing options
329-
while (groupSelect.firstChild) {
330-
groupSelect.removeChild(groupSelect.firstChild);
331-
}
321+
groupSelect.replaceChildren();
332322

333323
// Create default option using DOM methods instead of innerHTML
334324
const defaultOption = document.createElement("option");
@@ -648,7 +638,7 @@ customPayloadInput.addEventListener('input', function(e) {
648638

649639
if (matchingVars.length > 0) {
650640
// Show autocomplete dropdown
651-
variablesAutocomplete.innerHTML = '';
641+
variablesAutocomplete.replaceChildren();
652642
variablesAutocomplete.classList.remove('hidden');
653643

654644
matchingVars.forEach(variable => {
@@ -732,7 +722,7 @@ customPayloadInput.addEventListener('keydown', function(e) {
732722
});
733723

734724
function renderHeaders() {
735-
headersListDiv.textContent = '';
725+
headersListDiv.replaceChildren();
736726
headers.forEach((header, idx) => {
737727
const div = document.createElement('div');
738728
div.style.display = 'flex';
@@ -831,7 +821,7 @@ function renderSelectors() {
831821
.filter((value) => value.length > 0)
832822
.slice(0, MAX_SELECTORS_PER_WEBHOOK);
833823

834-
selectorsList.textContent = '';
824+
selectorsList.replaceChildren();
835825
updateSelectorsCount();
836826
clearSelectorError();
837827

@@ -1351,7 +1341,7 @@ document.addEventListener("DOMContentLoaded", () => {
13511341
];
13521342

13531343
function renderEmojiGrid() {
1354-
emojiGrid.textContent = '';
1344+
emojiGrid.replaceChildren();
13551345
EMOJIS.forEach(e => {
13561346
const btn = document.createElement('button');
13571347
btn.type = 'button';

0 commit comments

Comments
 (0)