Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Calls to `LinkifyIt.match()` are no longer incorrectly identified as regular expression operations.
14 changes: 14 additions & 0 deletions javascript/ql/lib/semmle/javascript/Regexp.qll
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,18 @@ private predicate isMatchObjectProperty(string name) {
name in ["length", "index", "input", "groups"]
}

/** Gets an API node representing a `LinkifyIt` instance. */
private API::Node linkifyItInstance() {
result = API::moduleImport("linkify-it").getMember("LinkifyIt").getInstance()
or
result = API::moduleImport("linkify-it").getMember("linkifyit").getReturn()
or
// Before version 6, the module export was the factory function.
result = API::moduleImport("linkify-it").getReturn()
or
result = linkifyItInstance().getMember(["add", "set", "tlds"]).getReturn()
}

/** Holds if `call` is a call to `match` whose result is used in a way that is incompatible with Match objects. */
overlay[global]
private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) {
Expand All @@ -1006,6 +1018,8 @@ private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) {
call.asExpr() = any(ExprStmt stmt).getExpr()
or
call = API::moduleImport("sinon").getMember("match").getACall()
or
call = linkifyItInstance().getMember("match").getACall()
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
| tst-IncompleteHostnameRegExp.js:3:3:3:28 | ^http:\\/\\/test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:3:2:3:29 | /^http: ... le.com/ | here |
| tst-IncompleteHostnameRegExp.js:6:3:6:28 | ^http:\\/\\/test.example.net | This regular expression has an unescaped '.' before 'example.net', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:6:2:6:29 | /^http: ... le.net/ | here |
| tst-IncompleteHostnameRegExp.js:7:3:7:42 | ^http:\\/\\/test.(example-a\|example-b).com | This regular expression has an unescaped '.' before '(example-a\|example-b).com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:7:2:7:43 | /^http: ... b).com/ | here |
| tst-IncompleteHostnameRegExp.js:8:3:8:30 | ^http:\\/\\/(.+).example.com\\/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:8:2:8:31 | /^http: ... .com\\// | here |
| tst-IncompleteHostnameRegExp.js:8:3:8:30 | ^http:\\/\\/(.+).example.com\\/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example.com' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:8:2:8:31 | /^http: ... .com\\// | here |
| tst-IncompleteHostnameRegExp.js:10:3:10:39 | ^http:\\/\\/(?:.+)\\.test\\.example.com\\/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example.com' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:10:2:10:40 | /^http: ... .com\\// | here |
| tst-IncompleteHostnameRegExp.js:11:3:11:36 | ^http:\\/\\/test.example.com\\/(?:.*) | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:11:2:11:37 | /^http: ... (?:.*)/ | here |
| tst-IncompleteHostnameRegExp.js:12:14:12:37 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:12:13:12:38 | "^http: ... le.com" | here |
| tst-IncompleteHostnameRegExp.js:13:15:13:38 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:13:14:13:39 | "^http: ... le.com" | here |
| tst-IncompleteHostnameRegExp.js:16:23:16:46 | ^http://test.example.com | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:16:13:16:50 | id(id(i ... com"))) | here |
| tst-IncompleteHostnameRegExp.js:20:18:20:34 | ^test.example.com | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:21:13:21:26 | `${hostname}$` | here |
| tst-IncompleteHostnameRegExp.js:23:28:23:44 | test.example.com$ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:24:13:24:27 | domain.hostname | here |
| tst-IncompleteHostnameRegExp.js:29:24:29:40 | test.example.com$ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:27:21:27:35 | domain.hostname | here |
| tst-IncompleteHostnameRegExp.js:31:31:31:47 | test.example.com$ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:33:21:33:35 | domain.hostname | here |
| tst-IncompleteHostnameRegExp.js:38:3:38:53 | ^(https?:)?\\/\\/((service\|www).)?example.com(?=$\|\\/) | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:38:2:38:54 | /^(http ... =$\|\\/)/ | here |
| tst-IncompleteHostnameRegExp.js:39:3:39:43 | ^(http\|https):\\/\\/www.example.com\\/p\\/f\\/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:39:2:39:44 | /^(http ... p\\/f\\// | here |
| tst-IncompleteHostnameRegExp.js:40:5:40:30 | http:\\/\\/sub.example.com\\/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:40:2:40:33 | /^(http ... om\\/)/g | here |
| tst-IncompleteHostnameRegExp.js:41:3:41:29 | ^https?:\\/\\/api.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:41:2:41:30 | /^https ... le.com/ | here |
| tst-IncompleteHostnameRegExp.js:42:42:42:48 | ^https?://.+\\.example\\.com/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example\\.com/' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:42:13:42:71 | '^http: ... \\.com/' | here |
| tst-IncompleteHostnameRegExp.js:44:3:44:32 | ^https:\\/\\/[a-z]*.example.com$ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:44:2:44:33 | /^https ... e.com$/ | here |
| tst-IncompleteHostnameRegExp.js:45:32:45:45 | .+.example.net | This regular expression has an unescaped '.' before 'example.net', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:45:9:45:101 | '^proto ... ernal)' | here |
| tst-IncompleteHostnameRegExp.js:45:47:45:62 | .+.example-a.com | This regular expression has an unescaped '.' before 'example-a.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:45:9:45:101 | '^proto ... ernal)' | here |
| tst-IncompleteHostnameRegExp.js:45:64:45:79 | .+.example-b.com | This regular expression has an unescaped '.' before 'example-b.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:45:9:45:101 | '^proto ... ernal)' | here |
| tst-IncompleteHostnameRegExp.js:49:42:49:47 | ^https?://.+.example\\.com/ | This regular expression has an unescaped '.' before 'example\\.com/', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:49:13:49:69 | '^http: ... \\.com/' | here |
| tst-IncompleteHostnameRegExp.js:49:42:49:47 | ^https?://.+.example\\.com/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example\\.com/' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:49:13:49:69 | '^http: ... \\.com/' | here |
| tst-IncompleteHostnameRegExp.js:54:14:54:35 | test.example.com$ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:54:13:54:36 | 'test.' ... e.com$' | here |
| tst-IncompleteHostnameRegExp.js:56:14:56:38 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:56:13:56:39 | '^http: ... le.com' | here |
| tst-IncompleteHostnameRegExp.js:60:5:60:20 | foo.example\\.com | This regular expression has an unescaped '.' before 'example\\.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:60:2:60:32 | /^(foo. ... ever)$/ | here |
| tst-IncompleteHostnameRegExp.js:62:18:62:41 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:62:17:62:42 | "^http: ... le.com" | here |
| tst-IncompleteHostnameRegExp.js:5:3:5:28 | ^http:\\/\\/test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:5:2:5:29 | /^http: ... le.com/ | here |
| tst-IncompleteHostnameRegExp.js:8:3:8:28 | ^http:\\/\\/test.example.net | This regular expression has an unescaped '.' before 'example.net', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:8:2:8:29 | /^http: ... le.net/ | here |
| tst-IncompleteHostnameRegExp.js:9:3:9:42 | ^http:\\/\\/test.(example-a\|example-b).com | This regular expression has an unescaped '.' before '(example-a\|example-b).com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:9:2:9:43 | /^http: ... b).com/ | here |
| tst-IncompleteHostnameRegExp.js:10:3:10:30 | ^http:\\/\\/(.+).example.com\\/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:10:2:10:31 | /^http: ... .com\\// | here |
| tst-IncompleteHostnameRegExp.js:10:3:10:30 | ^http:\\/\\/(.+).example.com\\/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example.com' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:10:2:10:31 | /^http: ... .com\\// | here |
| tst-IncompleteHostnameRegExp.js:12:3:12:39 | ^http:\\/\\/(?:.+)\\.test\\.example.com\\/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example.com' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:12:2:12:40 | /^http: ... .com\\// | here |
| tst-IncompleteHostnameRegExp.js:13:3:13:36 | ^http:\\/\\/test.example.com\\/(?:.*) | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:13:2:13:37 | /^http: ... (?:.*)/ | here |
| tst-IncompleteHostnameRegExp.js:14:14:14:37 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:14:13:14:38 | "^http: ... le.com" | here |
| tst-IncompleteHostnameRegExp.js:15:15:15:38 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:15:14:15:39 | "^http: ... le.com" | here |
| tst-IncompleteHostnameRegExp.js:18:23:18:46 | ^http://test.example.com | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:18:13:18:50 | id(id(i ... com"))) | here |
| tst-IncompleteHostnameRegExp.js:22:18:22:34 | ^test.example.com | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:23:13:23:26 | `${hostname}$` | here |
| tst-IncompleteHostnameRegExp.js:25:28:25:44 | test.example.com$ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:26:13:26:27 | domain.hostname | here |
| tst-IncompleteHostnameRegExp.js:31:24:31:40 | test.example.com$ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:29:21:29:35 | domain.hostname | here |
| tst-IncompleteHostnameRegExp.js:33:31:33:47 | test.example.com$ | This string, which is used as a regular expression $@, has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:35:21:35:35 | domain.hostname | here |
| tst-IncompleteHostnameRegExp.js:40:3:40:53 | ^(https?:)?\\/\\/((service\|www).)?example.com(?=$\|\\/) | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:40:2:40:54 | /^(http ... =$\|\\/)/ | here |
| tst-IncompleteHostnameRegExp.js:41:3:41:43 | ^(http\|https):\\/\\/www.example.com\\/p\\/f\\/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:41:2:41:44 | /^(http ... p\\/f\\// | here |
| tst-IncompleteHostnameRegExp.js:42:5:42:30 | http:\\/\\/sub.example.com\\/ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:42:2:42:33 | /^(http ... om\\/)/g | here |
| tst-IncompleteHostnameRegExp.js:43:3:43:29 | ^https?:\\/\\/api.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:43:2:43:30 | /^https ... le.com/ | here |
| tst-IncompleteHostnameRegExp.js:44:42:44:48 | ^https?://.+\\.example\\.com/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example\\.com/' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:44:13:44:71 | '^http: ... \\.com/' | here |
| tst-IncompleteHostnameRegExp.js:46:3:46:32 | ^https:\\/\\/[a-z]*.example.com$ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:46:2:46:33 | /^https ... e.com$/ | here |
| tst-IncompleteHostnameRegExp.js:47:32:47:45 | .+.example.net | This regular expression has an unescaped '.' before 'example.net', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:47:9:47:101 | '^proto ... ernal)' | here |
| tst-IncompleteHostnameRegExp.js:47:47:47:62 | .+.example-a.com | This regular expression has an unescaped '.' before 'example-a.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:47:9:47:101 | '^proto ... ernal)' | here |
| tst-IncompleteHostnameRegExp.js:47:64:47:79 | .+.example-b.com | This regular expression has an unescaped '.' before 'example-b.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:47:9:47:101 | '^proto ... ernal)' | here |
| tst-IncompleteHostnameRegExp.js:51:42:51:47 | ^https?://.+.example\\.com/ | This regular expression has an unescaped '.' before 'example\\.com/', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:51:13:51:69 | '^http: ... \\.com/' | here |
| tst-IncompleteHostnameRegExp.js:51:42:51:47 | ^https?://.+.example\\.com/ | This regular expression has an unrestricted wildcard '.+' which may cause 'example\\.com/' to be matched anywhere in the URL, outside the hostname. | tst-IncompleteHostnameRegExp.js:51:13:51:69 | '^http: ... \\.com/' | here |
| tst-IncompleteHostnameRegExp.js:56:14:56:35 | test.example.com$ | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:56:13:56:36 | 'test.' ... e.com$' | here |
| tst-IncompleteHostnameRegExp.js:58:14:58:38 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:58:13:58:39 | '^http: ... le.com' | here |
| tst-IncompleteHostnameRegExp.js:62:5:62:20 | foo.example\\.com | This regular expression has an unescaped '.' before 'example\\.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:62:2:62:32 | /^(foo. ... ever)$/ | here |
| tst-IncompleteHostnameRegExp.js:64:18:64:41 | ^http://test.example.com | This regular expression has an unescaped '.' before 'example.com', so it might match more hosts than expected. | tst-IncompleteHostnameRegExp.js:64:17:64:42 | "^http: ... le.com" | here |
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { LinkifyIt, linkifyit } from "linkify-it";

(function() {
/^http:\/\/example.com/;
/^http:\/\/test.example.com/; // $ Alert
Expand Down Expand Up @@ -64,4 +66,8 @@
const sinon = require('sinon');
const megacliteUrl = "https://a.b.com";
sinon.assert.calledWith(postStub.firstCall, sinon.match(megacliteUrl));

const scanner = new LinkifyIt().add("ftp:", null).set({ fuzzyLink: false }).tlds("onion", true);
if (scanner.match(megacliteUrl)) {}
if (linkifyit().match(megacliteUrl)) {}
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const sinon = require('sinon');
const { LinkifyIt } = require("linkify-it");
const legacyLinkifyIt = require("linkify-it");

function testFunction() {
const megacliteUrl = "https://a.b.com";
sinon.assert.calledWith(postStub.firstCall, sinon.match(megacliteUrl));
console.log(new LinkifyIt().set({ fuzzyLink: false }).match(megacliteUrl));
console.log(legacyLinkifyIt().match(megacliteUrl));
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ app.get('/findKey', function(req, res) {
var safeKey = _.escapeRegExp(key);
var re = new RegExp("\\b" + safeKey + "=(.*)\n");
});

var { LinkifyIt } = require("linkify-it");

app.get('/findLinks', function(req, res) {
var text = req.param("text");
var scanner = new LinkifyIt().set({ fuzzyLink: false });
// OK - LinkifyIt scans text; its argument is not a regular expression.
var matches = scanner.match(text);
res.json(matches);
});