Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[JavaScript] Find Invocation Nodes without resolved callees that belong to external libraries #18901

Answered by mbg
jghebre asked this question in Q&A
Discussion options

Hi 👋,

I'm working on a project and I need a way to determine if Invocations nodes, without any found callees, originate from an external library. I'm not sure if there exists a mechanism to determine this information due to the callee not being found.

To my knowledge, for JavaScript, CodeQL does not analyze the node_modules by default and contains modeling of certain popular external libraries like express.

For example in this code:

var url = require('fast-url-parser');
.
.
.
var path = url.parse(request.url).pathname

Running this query:

from DataFlow::InvokeNode node
 where not exists(node.getACallee(0)) 
 select node, ...

Correctly finds the callee parse as not being found. However there are many invocation nodes without found callees throughout most packages and I just want to focus on the nodes that relate to external libraries.

I've looked into libraries like import semmle.javascript.dependencies.Dependencies to implement this but haven't found anything that worked yet.

Thanks!

You must be logged in to vote

Does this do the job for you:

import javascript
import semmle.javascript.ApiGraphs
select API::moduleImport(_).getMember(_).getACall()

With your test code, this gets me the three calls to the three external function calls. If you want to additionally check that there's no callee, then you could do something like this:

import javascript
import semmle.javascript.ApiGraphs
from DataFlow::CallNode external
where external = API::moduleImport(_).getMember(_).getACall()
and not exists (external.getACallee(0))
select external

Replies: 1 comment 3 replies

Comment options

Hi @jghebre 👋🏻

Would you be able to give an example of the sort of nodes you would want to exclude?

You must be logged in to vote
3 replies
Comment options

Hi, thanks for responding!

Here is a quick example I made:

// Third-Party
import catMe from 'cat-me';
import figlet from 'figlet';
import randomstring from 'randomstring';
// First Party
const far = "farwell";
const obj = {
 [far](name) {
 return `Goodbye, ${name}!`;
 }
}
function add(a, b) {
 return a + b;
}
function multiply(a, b) {
 return a * b;
}
(async function main() {
 // Calls to Third-Party Functions
 console.log(catMe(), "\n"); 
 console.log("Third-Party Call #2 (figlet):");
 console.log(figlet.textSync("Hello World!"), "\n"); 
 console.log("Third-Party Call #3 (randomstring):");
 console.log(randomstring.generate(8), "\n"); 
 // Calls to First-Party Functions
 const funcName = "farewell";
 console.log(obj.farwell("Bob"), "\n");
 const functionArray = [add, multiply];
 console.log(functionArray[0](3, 4), "\n");
 const { externalFunction } = await import('./extraFirstParty.js');
 console.log(externalFunction("Hello!"), "\n");
})();

The six calls here are not found by CodeQL:
image

I'm trying to find a way to filter the Third party calls (catMe, figlet, randomstring) from the first party calls (obj.farwell("Bob"), functionArray[0](3, 4), externalFunction("Hello!"))

For my use case I only care about calls without resolved callees from third party libraries. I'm not sure the limit to which this is possible due to the fact that these calls are not resolved.

Comment options

mbg Mar 3, 2025
Maintainer

Does this do the job for you:

import javascript
import semmle.javascript.ApiGraphs
select API::moduleImport(_).getMember(_).getACall()

With your test code, this gets me the three calls to the three external function calls. If you want to additionally check that there's no callee, then you could do something like this:

import javascript
import semmle.javascript.ApiGraphs
from DataFlow::CallNode external
where external = API::moduleImport(_).getMember(_).getACall()
and not exists (external.getACallee(0))
select external
Answer selected by jghebre
Comment options

Yep works on all my cases so far. I think this is it, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /