xml2json-unsafe-deserialization
Ast Rule: function call
xml2json-unsafe-deserialization
// Function to check that a module with name moduleName is imported into variable variableName
function isModuleImported(node, variableName, moduleName) {
// Get all the assignments and check to get an assignment like
// const variableName = require("moduleName");
const n = node.context.assignments.filter(a => a.left && a.left.astType === "string" && a.left.value === variableName);
if(n && n.length > 0 ){
const call = n[0].right;
if(call.astType === "functioncall" && call.arguments && call.arguments.values && call.arguments.values.length > 0) {
const arg = call.arguments.values[0].value;
if(arg.astType === "string" && (arg.value === `"${moduleName}"` || arg.value === `'${moduleName}'`)) {
return true;
}
}
}
return false;
}
function isValueString(value) {
if(!value){
return false;
}
const stringChar = ['"', "'", "`"];
if (value && value.length > 2){
return stringChar.some(v => {
if(value.charAt(value.length-1) === v && value.charAt(0) === v) {
return true;
}
});
}
return false;
}
// Function to check that a module with name moduleName is imported into variable variableName
function getVariableString(node, variableName) {
// Get all the assignments and check to get an assignment like
// const variableName = require("moduleName");
const n = node.context.assignments.filter(a => a.left && a.left.astType === "string" && a.left.value === variableName);
if(n && n.length > 0 ){
const right = n[0].right;
if(right.astType === "string") {
return right.value;
}
}
return null;
}
// main entrypoint
function visit(node) {
const functionName = node.functionName;
// the function name called is a member that has a parent and a name.
// Ideally, the name is toJson and the parent is a variable that imports
// the "xml2json" module.
if(functionName && functionName.astType === "member" && functionName.name.value === "toJson"){
if(functionName.parent && functionName.parent.astType === "string") {
const parentName = functionName.parent.value;
const isUsingModule = isModuleImported(node, parentName, "xml2json");
const firstArgument = node.arguments && node.arguments && node.arguments.values && node.arguments.values[0];
const isFirstArgumentString = isValueString(firstArgument.value.value) || isValueString(getVariableString(node, firstArgument.value.value));
if(isUsingModule && !isFirstArgumentString) {
const error = buildError(node.functionName.start.line, node.functionName.start.col, node.functionName.end.line, node.functionName.end.col, "unsafe deserialization", "CRITICAL", "SAFETY");
addError(error);
}
}
}
}
xml2json-use.js
Expected test result: has error
xml2json-no-error.js
Expected test result: no error
xml2json-no-error2.js
Expected test result: no error