-
Notifications
You must be signed in to change notification settings - Fork 1.9k
-
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!
Beta Was this translation helpful? Give feedback.
All reactions
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
-
Hi @jghebre 👋🏻
Would you be able to give an example of the sort of nodes you would want to exclude?
Beta Was this translation helpful? Give feedback.
All reactions
-
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.
Beta Was this translation helpful? Give feedback.
All reactions
-
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
Beta Was this translation helpful? Give feedback.
All reactions
-
Yep works on all my cases so far. I think this is it, thank you!
Beta Was this translation helpful? Give feedback.
All reactions
-
🎉 1