From 4dcfb7b703c9f5863ca0e1db181b56b49b0a6c98 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:06:12 +0000 Subject: [PATCH 1/3] Initial plan From db3f61c016a3a8545550204ec00066d389d80f6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:08:11 +0000 Subject: [PATCH 2/3] Replace innerHTML with secure DOM APIs to prevent XSS vulnerabilities Co-authored-by: rwoll <11915034+rwoll@users.noreply.github.com> --- app.js | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/app.js b/app.js index 2448fa2..570fe2c 100644 --- a/app.js +++ b/app.js @@ -76,16 +76,28 @@ function renderUpcomingDates() { const container = document.getElementById('upcoming-dates'); const dates = getNextPatchTuesdays(12); - container.innerHTML = dates.map((date, index) => { + // Clear existing content + container.replaceChildren(); + + dates.forEach((date, index) => { const daysAway = getDaysAway(date); const isFirst = index === 0; - return ` -
- ${formatDate(date)} - ${formatDaysAway(daysAway)} -
- `; - }).join(''); + + const dateItem = document.createElement('div'); + dateItem.className = isFirst ? 'date-item highlight' : 'date-item'; + + const dateSpan = document.createElement('span'); + dateSpan.className = 'date'; + dateSpan.textContent = formatDate(date); + + const badgeSpan = document.createElement('span'); + badgeSpan.className = isFirst ? 'badge primary' : 'badge'; + badgeSpan.textContent = formatDaysAway(daysAway); + + dateItem.appendChild(dateSpan); + dateItem.appendChild(badgeSpan); + container.appendChild(dateItem); + }); } /** @@ -107,19 +119,19 @@ function populateSelectors() { 'July', 'August', 'September', 'October', 'November', 'December' ]; - monthSelect.innerHTML = months.map((month, index) => - `` - ).join(''); + // Clear existing options and populate months + monthSelect.replaceChildren(); + months.forEach((month, index) => { + const option = new Option(month, index, index === defaultMonth, index === defaultMonth); + monthSelect.add(option); + }); // Populate years (5 years before to 10 years after current year) - const years = []; + yearSelect.replaceChildren(); for (let y = currentYear - 5; y <= currentYear + 10; y++) { - years.push(y); + const option = new Option(y, y, y === defaultYear, y === defaultYear); + yearSelect.add(option); } - - yearSelect.innerHTML = years.map(year => - `` - ).join(''); } /** From c0c26624f82d24a8fb67696f4eb073c69202f5ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:09:25 +0000 Subject: [PATCH 3/3] Refactor Option constructor calls for clarity Co-authored-by: rwoll <11915034+rwoll@users.noreply.github.com> --- app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 570fe2c..b96f179 100644 --- a/app.js +++ b/app.js @@ -122,14 +122,16 @@ function populateSelectors() { // Clear existing options and populate months monthSelect.replaceChildren(); months.forEach((month, index) => { - const option = new Option(month, index, index === defaultMonth, index === defaultMonth); + const isSelected = index === defaultMonth; + const option = new Option(month, index, isSelected, isSelected); monthSelect.add(option); }); // Populate years (5 years before to 10 years after current year) yearSelect.replaceChildren(); for (let y = currentYear - 5; y <= currentYear + 10; y++) { - const option = new Option(y, y, y === defaultYear, y === defaultYear); + const isSelected = y === defaultYear; + const option = new Option(y, y, isSelected, isSelected); yearSelect.add(option); } }