Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian@packages.debian.org
Usertags: pu
[ Reason ]
Regex Denial of Service (CVE-2021-3803)
[ Impact ]
Medium vulnerability
[ Tests ]
Test passed
[ Risks ]
Low risk, patch isn't so complicated and test passed
[ Checklist ]
[X] *all* changes are documented in the d/changelog
[X] I reviewed all changes and I approve them
[X] attach debdiff against the package in (old)stable
[X] the issue is verified as fixed in unstable
[ Changes ]
Replace regex with hand-rolled parser
Cheers,
Yadd
diff --git a/debian/changelog b/debian/changelog
index b80a144..e2e201b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+node-nth-check (2.0.0-1+deb11u1) bullseye; urgency=medium
+
+ * Team upload
+ * Replace regex with hand-rolled parser (Closes: CVE-2021-3803)
+
+ -- Yadd Sat, 05 Feb 2022 12:42:20 +0100
+
node-nth-check (2.0.0-1) unstable; urgency=medium
* Team upload
diff --git a/debian/patches/CVE-2021-3803.patch
b/debian/patches/CVE-2021-3803.patch
new file mode 100644
index 000..da4870c
--- /dev/null
+++ b/debian/patches/CVE-2021-3803.patch
@@ -0,0 +1,107 @@
+Description: Replace regex with hand-rolled parser
+Author: Felix Böhm <188768+f...@users.noreply.github.com>
+Origin: upstream,
https://patch-diff.githubusercontent.com/raw/fb55/nth-check/pull/9.patch
+Bug: https://github.com/advisories/GHSA-rp65-9cf3-cjxr
+Forwarded: not-needed
+Reviewed-By: Yadd
+Last-Update: 2022-02-05
+
+--- a/src/parse.ts
b/src/parse.ts
+@@ -1,7 +1,9 @@
+ // Following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
+
+-// [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]?
+-const RE_NTH_ELEMENT = /^([+-]?\d*n)?\s*(?:([+-]?)\s*(\d+))?$/;
++// Whitespace as per https://www.w3.org/TR/selectors-3/#lex is " \t\r\n\f"
++const whitespace = new Set([9, 10, 12, 13, 32]);
++const ZERO = "0".charCodeAt(0);
++const NINE = "9".charCodeAt(0);
+
+ /**
+ * Parses an expression.
+@@ -19,24 +21,72 @@
+ return [2, 1];
+ }
+
+-const parsed = formula.match(RE_NTH_ELEMENT);
++// Parse [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]?
+
+-if (!parsed) {
++let idx = 0;
++
++let a = 0;
++let sign = readSign();
++let number = readNumber();
++
++if (idx < formula.length && formula.charAt(idx) === "n") {
++idx++;
++a = sign * (number ?? 1);
++
++skipWhitespace();
++
++if (idx < formula.length) {
++sign = readSign();
++skipWhitespace();
++number = readNumber();
++} else {
++sign = number = 0;
++}
++}
++
++// Throw if there is anything else
++if (number === null || idx < formula.length) {
+ throw new Error(`n-th rule couldn't be parsed ('${formula}')`);
+ }
+
+-let a;
++return [a, sign * number];
+
+-if (parsed[1]) {
+-a = parseInt(parsed[1], 10);
+-if (isNaN(a)) {
+-a = parsed[1].startsWith("-") ? -1 : 1;
++function readSign() {
++if (formula.charAt(idx) === "-") {
++idx++;
++return -1;
+ }
+-} else a = 0;
+
+-const b =
+-(parsed[2] === "-" ? -1 : 1) *
+-(parsed[3] ? parseInt(parsed[3], 10) : 0);
++if (formula.charAt(idx) === "+") {
++idx++;
++}
++
++return 1;
++}
+
+-return [a, b];
++function readNumber() {
++const start = idx;
++let value = 0;
++
++while (
++idx < formula.length &&
++formula.charCodeAt(idx) >= ZERO &&
++formula.charCodeAt(idx) <= NINE
++) {
++value = value * 10 + (formula.charCodeAt(idx) - ZERO);
++idx++;
++}
++
++// Return `null` if we didn't read anything.
++return idx === start ? null : value;
++}
++
++function skipWhitespace() {
++while (
++idx < formula.length &&
++whitespace.has(formula.charCodeAt(idx))
++) {
++idx++;
++}
++}
+ }
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 000..4ac3e54
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+CVE-2021-3803.patch