This weekend I spent some quality time with HTTP Cookie Specs ( RFC 2109 and RFC 2695 ), and looked closely how at the cookie parsing and handling is done in three Perl frameworks: Titanium, Catalyst and Mojo. Titanium uses CGI::Cookie by default, while Catalyst uses CGI::Simple::Cookie and Mojo uses built-in modules including Mojo::Cookie::Request.

I'll look at these solutions through the filters of Standards, Security, and Convenience.

Standards: Max-Age, Set-Cookie2 and commas

Max-Age is cookie attribute which gives the expiration time as a relative value. This is considered a more secure replacement for the "Expires" header, which gives the time as an absolute value, making it vulnerable to clock skew on the user's systems. CGI.pm and Mojo support it, but CGI::Simple does not. This is potentially an issue for Catalyst users, if they believe they have Max-Age support because the documentation refers them to CGI::Cookie, but they actually don't because they are using CGI::Simple::Cookie.

Set-Cookie2 is a standard from 2000 to replace Set-Cookie, which became a standard in 1997. Mojo is the only of the three that supports it. However, Set-Cookie2 never caught on. Firefox 3 doesn't even support it, and neither does IE 6. Still, I like the idea of deciding for myself about supporting new standards, rather than having tools that only support older standards. Mojo wins here.

The RFCs say that servers should accept a comma as well as semicolon between cookie values. CGI.pm and Mojo comply here, CGI::Simple does not. (I've submitted a patch to address this, along with a few other places I felt CGI::Simple cookie parsing lagged CGI.pm)

Security

CGI::Simple cookies are potentially less secure because they lack "Max-Age" support. Mojo's cookie implementation appears to be vulnerable to an injection attack where untrusted data in a cookie value can write a new HTTP body. I have notified the developers of my findings there. CGI.pm and CGI::Simple both avoid the injection attack by URI-encoding the cookie values, (a spec-compliant solution).

Convenience

CGI.pm and CGI::Simple share several convenient user interface features which Mojo currently lacks. They allow you to set multiple-values for a single cookie, including setting a hashref. They also provide a convenient shorthand for giving expiration times, like "+10m" for "10 months in the future". Mojo lacks these features. If you have a Catalyst app that uses the multiple-values features, a port to Mojo could mean a painful cookie transition, since Mojo does not have a built-in understanding of the format CGI.pm uses to store cookie values. (This detail is not dictated by the cookie spec so both value formats are "spec compliant").

Conclusions

Sebastian Riedel, the Mojo author, promotes Mojo as being focused on standards. From my findings here, I have to say that I agree that Mojo is a leader here, currently at the expense of a potentially serious security issue, and lacking some usability features that the others offer.

CGI::Simple has a reputation but being a lighter and better engineered version of CGI.pm. Certainly the overall the design and focus of CGI::Simple is an improvement. But the reality is that CGI::Simple was forked from CGI.pm in 2001. CGI.pm has received many improvements since then including improved cookie handling, like adding support for "Max-Age". However, CGI::Simple doesn't seem to make a point of tracking and merging improvements that originate in CGI.pm. CGI::Simple is perhaps more like a lighter, tighter alternative to CGI.pm as it existed several years ago.

The mature-but-maligned CGI.pm comes out fairing the best for cooking handling in my opinion. It did not have any of the potential security issues I found with the other two, and it has a range of convenient methods for cookie access.

But as a final note, I encourage to you check with the specific projects for the most current information, as some of the deficiencies I found here may already be addressed.

Using rsnapshot with systemd

Published on August 26, 2016