Skip to content

Commit 2c8ad28

Browse files
Copilotpethers
andauthored
fix: add escapeRegex helper to prevent regex injection in extractDataAttr/extractSpanText
Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/e2c0e6bd-7c8e-45cd-be30-579cad326206 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
1 parent 6e2bdee commit 2c8ad28

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

scripts/fetch-calendar.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ export function parseCalendarListItem(attrs: string, body: string): CalendarEven
470470
// HTML extraction helpers
471471
// ---------------------------------------------------------------------------
472472

473+
/** Escape a string for safe use in a `new RegExp(...)` constructor. */
474+
function escapeRegex(s: string): string {
475+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
476+
}
477+
473478
/** Extract the `datetime` attribute from a `<time>` element. */
474479
function extractDatetime(html: string): string | null {
475480
const m = html.match(/<time\b[^>]*\bdatetime=(["'])(.*?)\1/i);
@@ -478,7 +483,7 @@ function extractDatetime(html: string): string | null {
478483

479484
/** Extract a `data-{attr}` attribute value from a tag's attribute string. */
480485
function extractDataAttr(attrs: string, name: string): string | null {
481-
const re = new RegExp(`\\bdata-${name}\\s*=\\s*(["'])(.*?)\\1`, 'i');
486+
const re = new RegExp(`\\bdata-${escapeRegex(name)}\\s*=\\s*(["'])(.*?)\\1`, 'i');
482487
const m = attrs.match(re);
483488
return m && m[2]?.trim() ? m[2].trim() : null;
484489
}
@@ -494,8 +499,9 @@ function hasCalendarItemClass(attrs: string): boolean {
494499
* Uses a simple, non-greedy regex that covers the common markup pattern.
495500
*/
496501
function extractSpanText(html: string, name: string): string | null {
502+
const safe = escapeRegex(name);
497503
const re = new RegExp(
498-
`<span\\b[^>]*\\bclass\\s*=\\s*(["'])[^"']*${name}[^"']*\\1[^>]*>([\\s\\S]*?)<\\/span>`,
504+
`<span\\b[^>]*\\bclass\\s*=\\s*(["'])[^"']*${safe}[^"']*\\1[^>]*>([\\s\\S]*?)<\\/span>`,
499505
'i',
500506
);
501507
const m = html.match(re);

0 commit comments

Comments
 (0)