Comments are available

Sun 24 August 2014
tags: meta

I got round to implementing the comment system in the last few days. There were a few things to think about in the implementation, such as how to make comments work both with and without javascript, as well as how the backend should fit together. I've put some notes on the implementation below.

Comment Submission (client side)

The details for the comment are filled out in an HTML form at the bottom of the post. If javascript is enabled then clicking the "submit" button runs a javascript function which sends an asychronous POST. If javascript is not enabled then the POST request is sent as normal by the browser. All client-side data validation is done with HTML5 form elements, which means that form data is validated even with javascript disabled.

Comment Submission (server side)

The POST request is picked up by a PHP script on the server which collects the form data. The script sanitizes the form data and emails it to me as JSON in a MIME attachment. The comment text is written into the email body so that I can quickly verify the comment content.

The PHP script will return a simple page confirming reception of the comment, and a link back to the original post. In the case where the form was submitted via an AJAX request, JSON is returned so that it the confirmation can be displayed by client-side javascript.

Comment Moderation and Deployment

Once I get the email containing the comment I can check that it's not spam and then add it to the website. Of course I don't manually add the comment to the website source, but have a script which does this for me. All I have to do is forward the email on to blog-comments@josephweston.org, which I reserve for the purpose of receiving moderated comments. A cron job periodically checks for new email at this address, adds the attached comments to the blog source code and then deploys the updated version to the webserver. Everything being stored in git repositories means that I've got a complete history of any changes made and can always roll back any errors.

Security Considerations

Adding comments to the blog opens it up to a class of security vulnerabilities known as "cross-site scripting", or "XSS". If someone makes a comment on a post with some javascript code between <script> tags, and if I then embed that raw comment into the post's webpage, then anyone viewing the page would automatically run that javascript in their browser. For josephweston.org this would probably be more a nuisance than anything else, as viewers don't have any sensitive data associated with this domain. If the javascript engine itself has vulnerabilites, however, then an attacker could potentially access information associated with other domains (e.g. auth tokens for banking websites / email open in the same browser session), or even break out of the sandboxed javascript engine entirely. Better to try and avoid such problems rather than rationalise them! To try and mitigate this, all external content is run through the Python markdown module with safe mode enabled. This should escape all HTML in the input, but still allow comments to be marked up using Markdown syntax.

As mentioned above, all comments that I validate are forwarded to a secondary email address where they are picked up and pushed to the website by a cron job. Now, email is not a particularly secure protocol by itself; as it stands anyone who sends an email to blog-comments@josephweston.org with a correctly formatted JSON attachment could bypass my validation mechanism altogether! My answer to this is pretty simply: use GnuPG to sign the JSON attachments. Every time I forward a validated comment to the blog-comments address I sign all the parts of the email with my private key. these signatures are then checked by the cron job before it adds the comment.

Conclusion

I got comments working on the blog using a combination of PHP, email and GnuPG. The comment submission works both with and without javascript and client-side form validation is done using modern HTML5 form elements.