Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

JS: Why does SanitizingRegExpTest treat /^...$/m as a whole-string check?

Aperta
#22,845 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
45/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
javascript
Ambito
security

Direzione di ricerca

Start with javascript/ql/lib/semmle/javascript/Regexp.qll, especially isFullyAnchoredTerm, isMultiline, and maybeMultiline, then trace how isGenericRegExpSanitizer feeds SanitizingRegExpTest in javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll. Check the relevant JavaScript security query tests for anchored regular expressions with and without the m flag. Done means multiline anchored checks no longer suppress taint findings while non-multiline anchored checks retain their current behavior.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

question

Description of the issue

JavaScript taint-tracking queries treat a test against a regular expression anchored with ^ and $ as a check of the whole string, also when the regular expression has the m flag. I'm wondering whether this is intended, because with m, ^ and $ also match at line boundaries, so any string that contains one matching line passes the check: /^[\w.-]+$/m.test("x\ntouch /tmp/marker") is true.

Affected sanitizer

SanitizingRegExpTest, which is "considered to be a sanitizer for all configurations", uses RegExp::isGenericRegExpSanitizer for re.test(x), re.exec(x), x.match(re) and x.matchAll(re). For the true outcome, that predicate only requires isFullyAnchoredTerm, which looks for a leading RegExpCaret and a trailing RegExpDollar. The flags of the regular expression are not consulted, although the same module has isMultiline and maybeMultiline.

Steps to reproduce

const cp = require("child_process");
const app = require("express")();

app.get("/a", (req, res) => {
  const dir = req.query.dir;
  if (/^[\w.-]+$/m.test(dir)) {
    cp.exec("ls " + dir); // not reported
  }
  res.send("ok");
});

app.get("/b", (req, res) => {
  const dir = req.query.dir;
  if (/^[\w.-]+$/.test(dir)) {
    cp.exec("ls " + dir); // not reported (correct: no newline can pass)
  }
  res.send("ok");
});

app.get("/c", (req, res) => {
  const dir = req.query.dir;
  cp.exec("ls " + dir); // reported
  res.send("ok");
});

app.get("/d", (req, res) => {
  const name = req.query.name;
  if (/^\w+$/m.test(name)) {
    res.send("<p>Hello " + name + "</p>"); // not reported
  } else {
    res.send("bad name");
  }
});

app.get("/e", (req, res) => {
  res.send("<p>Hello " + req.query.name + "</p>"); // reported
});

app.listen(3000);

With javascript-security-extended.qls, only /c (js/command-line-injection) and /e (js/reflected-xss) are reported. /a and /d are not, although at runtime their checks do not restrict the input:

  • dir = "x\ntouch /tmp/marker" (sent as ?dir=x%0Atouch%20/tmp/marker) passes the check in /a, and cp.exec("ls x\ntouch /tmp/marker") runs touch /tmp/marker as a second command. The file is created.
  • name = "x\n<script>alert(1)</script>" passes the check in /d, and the script element is sent in the response.

Without the m flag (/b), the check does restrict the input, so not reporting it is right.

The same mistake has led to real vulnerabilities, e.g. GHSA-3px3-54cx-rmw9 (CVE-2026-83609, @xmldom/xmldom 0.9.0–0.9.11), where an anchored validation regular expression was compiled with the m flag and a name with an embedded line terminator passed the check.

Question

Is it intended that the m flag is ignored here? Would it be reasonable to stop treating an anchored regular expression as a whole-string check when it has the m flag?

Environment

  • CodeQL CLI 2.27.2 (codeql/javascript-queries 2.4.7)
  • CodeQL repository commit for the links above: 781e068896eb7a1a104f1378e8f3f68a1074a015 (the files are unchanged since 2.27.2)
  • Node.js v24.18.0 on Linux/amd64
Lingua principale
CodeQL
Stelle
10.2k
Fork
2.1k
Merge medio
2g 18h
PR unite (30g)
142

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di github/codeql

Tutte le issue di github/codeql

Issue simili

Altre issue su Security

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.