Ashutosh
Ashutosh

Reputation: 4675

Nodejs: Check request body for bad characters

I am using Nodejs + Express for my project.

I am trying to check if there are any invalid characters in req.body or not.

For this, I created following code:

In express.js

var badStrings = ["'", '"', '<', '>'];

if (hasBadInput(req.body)) {
    // Bad input detected
    return res.status(400).send("BAD REQUEST");
}

function hasBadInput(requestParams) {
    for (var key in requestParams) {
        var value = requestParams[key];

        if (value && isBadInput(value)) {
            return true;
        }
    }

    return false;
}

function isBadInput(value) {
    for (var i = 0; i < badStrings.length; i++) {
        value += ""; // convert to string

        if (value.indexOf(badStrings[i]) > -1) {
            return true;
        }
    }

    return false;
}

The problem with above code is that it cannot check bad characters for nested object.

Works with req.body like:

{
   "username": "abc",
   "password": "*****"
}

Does not work with req.body like:

{
   "user_id": "1",
   "sale": {
      "product_id": "24",
      "amount": "500"
   }
}

Above code will not check data in sale object. Also, nesting can be of any level.

Should I be using some kind of recursive code to check nested data?

I don't want to sanitize input as this is done from the app.

Upvotes: 0

Views: 569

Answers (1)

YouneL
YouneL

Reputation: 8369

You could use recursion in order to make hasBadInput function call it self if the current value is object:

function hasBadInput(requestParams) {
    for (var key in requestParams) {

        var value = requestParams[key];

        // if the current value is an object check it too
        if ( value !== null && typeof value === 'object' ) {
            if ( hasBadInput(value) ) return true; 
            // else next iteration
            continue;
        }

        if (value && isBadInput(value)) {
            return true;
        }
    }

    return false;
}

Working Demo:

var badStrings = ["'", '"', '<', '>'];

function hasBadInput(requestParams) {
    for (var key in requestParams) {

        var value = requestParams[key];

        // if the current value is an object check it too
        if ( value !== null && typeof value === 'object' ) {
            if ( hasBadInput(value) ) return true;
            continue;
        }

        if (value && isBadInput(value)) {
            return true;
        }
    }

    return false;
}

function isBadInput(value) {
    for (var i = 0; i < badStrings.length; i++) {
        value += ""; // convert to string

        if (value.indexOf(badStrings[i]) > -1) {
            return true;
        }
    }

    return false;
}

// test 

var res = hasBadInput({
   "username": "abc",
   "password": "*****"
}); 

console.log(res); // should be false

res = hasBadInput({
   "username": "abc>",
   "password": "*****>"
}); // true

console.log(res); // should be true

res = hasBadInput({
   "user_id": "1",
   "sale": {
      "product_id": "24",
      "amount": "500"
   }
}); 

console.log(res); // should be false

res = hasBadInput({
   "user_id": "1",
   "sale": {
      "product_id": "24",
      "amount": "<500>"
   }
});

console.log(res); // should be true

res = hasBadInput({
   "user_id": "1",
   "sale": {
      "product_id": "24",
      "amount": "500"
   },
   "sale1": {
      "product_id": "24",
      "amount": "500"
   }
}); // false

console.log(res); // should be false

res = hasBadInput({
   "user_id": "1",
   "sale": {
      "product_id": "24",
      "amount": "500"
   },
   "sale1": {
      "product_id": "24",
      "amount": "<500>"
   }
}); // true

console.log(res); // should be true

res = hasBadInput({
   "user_id": "1",
   "sale": {
      "product_id": "24",
      "amount": "500"
   },
   "sale1": {
      "product_id": "24",
      "amount": "500",
      "sale2": {
          "product_id": "24",
          "amount": "<500>"
      }
   }
}); // true

console.log(res); // should be true

Upvotes: 1

Related Questions