Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

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

Ouverte
#22,845 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
45/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
Active
Stack technique
javascript
Domaine
security

Piste de recherche

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.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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
Langage dominant
CodeQL
Étoiles
10.2k
Forks
2.1k
Merge moyen
2 j 18 h
PR mergées (30 j)
142

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de github/codeql

Toutes les issues de github/codeql

Issues similaires

Plus d'issues Security

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.