"Sanitizing" means cleaning, desinfecting or getting rid of unwanted stuff.
In this aspect it means "keeping users from inserting garbage into our application".
Most bugs from amateur programmers come from this specific problem, they expect every user to have good intentions and only type/send what is expected of them.
Not every user is good. Not every user will write a number in the age field of a form.
app.get("/customer/:id", function(req,res){ sqlPool.query("SELECT * FROM customer WHERE id="+req.params.id, function(err,response){ if(err){ res.status(500).send("ERROR!"); return; } res.status(200).json(response[0]); }); });This piece of code is from an NodeJS Express application. It returns the customer object from the database if a GET request was sent to /customer/1.
app.get("/customer/:id", function(req,res){ const id = req.params.id; if(!id){ res.status(400).send("No ID provided."); return; } if(isNaN(parseInt(id))){ res.status(422).send("ID is not a number."); return; } [...] });Now a user with bad intentions can't send SQL Injections or other weird stuff anymore. This also makes the application more stable, because not checking for wrong/missing input could throw errors later down in the code.
The bad code example in question is the following:
net.Receive("policeArmory",function(len,ply) local wepClass = net.ReadString() local player = net.ReadEntity() player:Give(wepName) end)I have found this code on a GMod server once. This is a piece of serverside code that enables players who work for the police to get weapons from the armory.
net.Start("policeArmory") net.WriteString("m9k_davycrocket") net.WriteEntity(LocalPlayer()) net.SendToServer()
local allowedWeapons = { ["weapon_m16"] = true, ["weapon_glock"] = true, ["weapon_mp5"] = true } net.Receive("policeArmory",function(len,ply) local wepClass = net.ReadString() if not IsValid(ply) then return end if not ply:IsPlayer() then return end if not ply:Alive() then return end if not (ply:Team() == "Police") then return end if not allowedWeapons[wepClass] then return end ply:Give(wepClass) if not ply.armory_timeout then ply:Give(wepClass) ply.armory_timeout = CurTime()+120 else if CurTime() < ply.armory_timeout then return end ply:Give(wepClass) ply.armory_timeout = CurTime()+120 end end)Ofcourse you don't have to do all of these checks. They have been split up to one per line to make it more readable.
This can be a bit difficult to fully understand at first, but it gets easier the more you use it.
The most important thing to look out for is the connection to human input. You don't have to check if an internal function actually returns what it should be, but you have to check if a user sends the data you expect him to send.
A small checklist you could use for securing your application: