Preventing Cross-site Scripting (XSS) with CakePHP 2.x

Without proper care, developers can leave their CakePHP website open to cross-site scripting attacks. Controllers using scaffold functions do not take care to sanitize data, and leaves the website vulnerable. When using the bake tool in the console, it generates controllers as simple as the scaffold version. Some suggest storing the unsanitized data and escape the dangerous characters on output. In a perfect world I would agree with this approach, but it is easy to forget to sanitize output every time, or for an amateur developer to be ignorant of the dangers. A CakePHP motto is DRY (Don't repeat yourself) and in that spirit, I don't think it is efficient to sanitize data on each output.

CakePHP offered a utility called Sanitize, but it is deprecated as of CakePHP 2.4 and will be removed in CakePHP 3.0. There are a few possible solutions for saniziting the output:

  • Don't accept HTML input - Model validation can limit fields to alphaNumeric
  • Use a specialized library like HTML Purifier when outputting data
  • Htmlspecialchars() or h() - PHP function to safely output HTML elements. h() is a shortcut in CakePHP to this function.

Now that we have a way of cleaning the output we need to figure out where to do it in the process. We already know doing it manually every time we do a find or an output is repetitive and unnecessary. A few better options would be:

  • add() - Sanitize the data in the controller before saving
  • beforeSave() - Sanitize the data in the model callback before saving
  • afterFind() - Sanitize the data in the model callback after finding

The benefits of doing it before saving is that you never have to worry about it again. The drawback is that you may end up with bad data if your sanitizing function doesn't behave as you expected, or it corrupts the data somehow.