Skip to content

Commit d34c592

Browse files
fix(core): use a bounded whitespace prefix in attribute-strip regexes
CodeQL flags the \s* prefix as polynomial backtracking on attacker-controlled input (js/polynomial-redos). A single \s is enough: the attribute always has whitespace before it inside a tag.
1 parent 0cfebb9 commit d34c592

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

packages/core/src/compiler/timingCompiler.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ function compileTag(
116116

117117
// Strip an unparsable data-end so the normal missing-data-end flow below
118118
// recomputes or resolves it instead of leaving the garbage value in place.
119+
// Single \s (not \s*): the attribute always has whitespace before it
120+
// inside a tag, and an unbounded prefix backtracks polynomially on
121+
// attacker-controlled input (CodeQL js/polynomial-redos).
119122
const dataEndStr = getAttr(result, "data-end");
120123
if (dataEndStr !== null && !Number.isFinite(parseFloat(dataEndStr))) {
121-
result = result.replace(/\s*data-end=["'][^"']*["']/, "");
124+
result = result.replace(/\sdata-end=["'][^"']*["']/, "");
122125
}
123126

124127
// 1. Compute data-end from data-start + data-duration
@@ -128,7 +131,8 @@ function compileTag(
128131
if (durationStr !== null && !Number.isFinite(duration)) {
129132
// Unparsable data-duration: drop it and fall through to the
130133
// unresolved path so the caller's resolver supplies the real one.
131-
result = result.replace(/\s*data-duration=["'][^"']*["']/, "");
134+
// Single \s for the same reason as the data-end strip above.
135+
result = result.replace(/\sdata-duration=["'][^"']*["']/, "");
132136
}
133137
if (Number.isFinite(duration)) {
134138
const end = start + duration;

0 commit comments

Comments
 (0)