<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?</title>
    <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?</title>
      <description>&lt;p&gt;Recently I wrote about &lt;a href="http://blog.moertel.com/articles/2006/10/10/unit-testing-is-a-tool-not-a-goal"&gt;unit testing being a tool, not a goal in
itself&lt;/a&gt;.
I argued that unit testing was not a reliable way to fight
certain kinds of common coding errors and, therefore, that unit testing
ought to be supplemented with other tools.&lt;/p&gt;


	&lt;p&gt;To support my argument, I gave an example of a common, important
coding error that unit testing does a bad job of helping programmers
control.  That error is failing to manage and escape strings
properly: the &amp;#8220;strings problem.&amp;#8221;  It is the mother of &lt;span class="caps"&gt;XSS&lt;/span&gt; and
&lt;span class="caps"&gt;SQL&lt;/span&gt;-injection security vulnerabilities, not to mention the cause of
legions of broken links and bad &lt;span class="caps"&gt;HTML&lt;/span&gt; on the web.&lt;/p&gt;


	&lt;p&gt;If you think I&amp;#8217;m overstating the problem, or if you think that unit
testing is a good way of solving it, let me show you how easy it is
for even smart developers to get it wrong.&lt;/p&gt;


	&lt;p&gt;Consider &lt;a href="http://rubyonrails.com/"&gt;Ruby on
Rails&lt;/a&gt;, a great framework
for developing web applications.
Rails has an extensive suite of unit tests, and the &lt;a href="http://dev.rubyonrails.org/"&gt;Rails development guidelines&lt;/a&gt; require that changes to Rails be accompanied by unit tests that &amp;#8220;prove [the] change works.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Now consider that one of Rails&amp;#8217;s most-used and &lt;a href="http://blog.moertel.com/articles/2005/05/08/taking-the-unsafe-gets-out-of-rails"&gt;most-scrutinized&lt;/a&gt; methods &amp;#8211; the venerable &lt;code&gt;link_to&lt;/code&gt; helper &amp;#8211; contains a fundamental string-escaping error:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require 'rubygems'
require_gem 'rails'
include ActionView::Helpers::UrlHelper

url = "http://example.com?ohms_law?volt=1&amp;#38;amp=3" 
puts link_to("TEST", url)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The code, when executed, prints the following &lt;span class="caps"&gt;HTML&lt;/span&gt; snippet:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt;a href="http://example.com?ohms_law?volt=1&amp;#38;amp=3"&amp;gt;TEST&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The &lt;span class="caps"&gt;HTML&lt;/span&gt; snippet represents a hypertext link.  The link should point
to the &lt;span class="caps"&gt;URL&lt;/span&gt; given in the code, but because the &lt;span class="caps"&gt;URL&lt;/span&gt; was not properly
escaped when it was converted into &lt;span class="caps"&gt;HTML&lt;/span&gt; by the &lt;code&gt;link_to&lt;/code&gt; helper, the
link is broken:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;CORRECT:  http://example.com?ohms_law?volt=1&amp;#38;amp=3
LINK_TO:  http://example.com?ohms_law?volt=1&amp;#38;=3
                                             ^ oops
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Here&amp;#8217;s what&amp;#8217;s going on.  Because the &lt;span class="caps"&gt;URL&lt;/span&gt; was not escaped, web browsers
misinterpret its &amp;#8220;amp&amp;#8221; parameter as a character-entity reference,
which gets gobbled up when the link&amp;#8217;s &lt;code&gt;href&lt;/code&gt; attribute is parsed.
(To see this for yourself, save the output of the Ruby code into an
&lt;span class="caps"&gt;HTML&lt;/span&gt; file, open the file with your favorite web browser, and see where
the link points.)&lt;/p&gt;


	&lt;p&gt;Now, how come the unit tests didn&amp;#8217;t catch this problem?
It turns out, the tests got it wrong, too, by expecting
broken output:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;# in url_helper_test.rb

def test_link_tag_with_query
  assert_dom_equal \
    "&amp;lt;a href=\"http://www.example.com?q1=v1&amp;amp;amp;q2=v2\"&amp;gt;Hello&amp;lt;/a&amp;gt;",
    link_to("Hello", "http://www.example.com?q1=v1&amp;amp;amp;q2=v2")
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The point isn&amp;#8217;t that the Rails developers are dumb.  The point is that
the Rails developers are smart.  If &lt;em&gt;they&lt;/em&gt; can&amp;#8217;t get the strings
problem right, even with all their brains and all their unit testing,
what reason does &lt;em&gt;any&lt;/em&gt; programmer have to think that unit testing is going
to solve this problem reliably?&lt;/p&gt;


	&lt;p&gt;If, then, you want to solve the strings problem &amp;#8211; and you really,
seriously &lt;em&gt;ought&lt;/em&gt; to want to solve the strings problem &amp;#8211; you should
consider options beyond unit testing.&lt;/p&gt;


&lt;div class="update"&gt;

	&lt;p&gt;&lt;strong&gt;Update 2007-09-04:&lt;/strong&gt; I just noticed that the documentation for
&lt;em&gt;link_to&lt;/em&gt; has been revised to state that if you pass a
string as its &lt;em&gt;options&lt;/em&gt; parameter, the string will be interpreted not
as a &lt;span class="caps"&gt;URL&lt;/span&gt; but as an &lt;span class="caps"&gt;HTML&lt;/span&gt; &lt;em&gt;href&lt;/em&gt; attribute value, that is, an
&lt;span class="caps"&gt;HTML&lt;/span&gt;-encoded &lt;span class="caps"&gt;URL&lt;/span&gt;.  The old documentation:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt; &lt;code&gt;def link_to(name, options = {}, html_options = nil, *parms)&lt;/code&gt;&lt;br/&gt;Creates a link tag of
the given &lt;em&gt;name&lt;/em&gt; using an &lt;span class="caps"&gt;URL&lt;/span&gt; created by the set of &lt;em&gt;options&lt;/em&gt;.... It&amp;#8217;s
also possible to pass a string instead of an options hash to get a
link tag that just points without consideration.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The relevant part of the revised documentation:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;It&amp;#8217;s also possible to pass a string instead of an options hash to
get a link tag that uses the value of the string as the href for the
link.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;So, according to the updated documentation, the test I described in my
article is actually correct.  Does this mean that string-handling code
is Rails is worry free?  The existence of helper methods like &lt;a href="http://dev.rubyonrails.org/changeset/5321"&gt;&lt;em&gt;fix_double_escape&lt;/em&gt;&lt;/a&gt;
suggests the answer is no.&lt;/p&gt;


&lt;/div&gt;</description>
      <pubDate>Thu, 12 Oct 2006 16:06:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:03f6d26c-1207-4022-a970-b80231721ea6</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe</link>
      <category>programming</category>
      <category>testing</category>
      <category>rails</category>
      <category>rails</category>
      <category>testing</category>
      <category>strings</category>
      <category>problem</category>
      <category>escaping</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/184</trackback:ping>
    </item>
    <item>
      <title>"If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?" by Tom Moertel</title>
      <description>&lt;p&gt;Samuel,&lt;/p&gt;


	&lt;p&gt;Thanks for your comments.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not sure that you accurately understand my claims.  If you have
not seen it (and it seems like you have not), please read my article
&lt;a href="http://blog.moertel.com/articles/2006/10/10/unit-testing-is-a-tool-not-a-goal"&gt;Unit testing is a tool, not a
goal&lt;/a&gt;,
which explains what I believe.&lt;/p&gt;


	&lt;p&gt;To be clear, I&amp;#8217;m not saying that unit testing is bad, or that the
problem with bad code is the practice of unit testing.  I&amp;#8217;m saying
that unit testing should not be our focus.  Our focus ought to be
confidence in our code.  For many kinds of situations, unit testing is
an efficient way to establish that confidence.  For others, the
strings problem being one of them, unit testing doesn&amp;#8217;t work so well.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Based on reading this article, I&amp;#8217;m going to predict that the Haskell-based solution is to use &amp;#8220;newtype&amp;#8221; on String to identify unescaped versus escaped strings &amp;#8230;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;It&amp;#8217;s actually a bit more complex (involving type classes, newtypes for different kinds of strings, and Template Haskell), but that&amp;#8217;s the gist of it.  Please read &lt;a href="http://blog.moertel.com/articles/2006/10/18/a-type-based-solution-to-the-strings-problem"&gt;A type-based solution to the strings problem&lt;/a&gt; if you&amp;#8217;re interested.&lt;/p&gt;


	&lt;p&gt;Cheers,&lt;br /&gt;
Tom&lt;/p&gt;</description>
      <pubDate>Sun, 11 Mar 2007 00:33:51 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:dc89ab07-79b7-45d4-92d0-f28683c6c58d</guid>
      <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe#comment-411</link>
    </item>
    <item>
      <title>"If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?" by Samuel</title>
      <description>&lt;p&gt;The problem is inadequate specification.  Unit tests can back up specifications, but if the specs are wrong, the unit tests necessarily must also be wrong.&lt;/p&gt;


	&lt;p&gt;The problem IS NOT the practice of unit testing.  It&amp;#8217;s with the client&amp;#8217;s expectation of how link_to works.&lt;/p&gt;


	&lt;p&gt;Your arguments against unit testing so far have been thin and vacuous.&lt;/p&gt;


	&lt;p&gt;However, I agree overall that unit tests aren&amp;#8217;t for everything.  Unit tests are best at isolating &amp;#8220;corner cases&amp;#8221;, but do relatively little for the &amp;#8220;common cases.&amp;#8221;  For example, to prove the correctness of a 2048-bit modulo integer multiplication routine, for example, you&amp;#8217;d never want to use unit tests.  :)&lt;/p&gt;


	&lt;p&gt;What I&amp;#8217;m saying is that your thesis is good, but the supporting argument is bad.&lt;/p&gt;


	&lt;p&gt;Based on reading this article, I&amp;#8217;m going to predict that the Haskell-based solution is to use &amp;#8220;newtype&amp;#8221; on String to identify unescaped versus escaped strings, thus making it &lt;strong&gt;patently&lt;/strong&gt; clear to the coder (and the compiler) what is expected of the function.  This DOES have the effect of reducing unnecessary unit tests.  But it won&amp;#8217;t eliminate unit tests entirely.&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s always been a major war between the &amp;#8220;formal methods&amp;#8221; and &amp;#8220;unit testing&amp;#8221; camps.  The truth is, as in all chaotic systems, the interesting parts are in the interfaces between the two camps.  If you want excellent code coverage AND provably correct code, you must use BOTH techniques.&lt;/p&gt;</description>
      <pubDate>Sat, 10 Mar 2007 13:25:57 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6289d03e-67c9-40be-a0f1-072bccd85f06</guid>
      <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe#comment-410</link>
    </item>
    <item>
      <title>"If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?" by Tom Moertel</title>
      <description>&lt;p&gt;John, what other sort of solution was possible?  Take a look at &lt;a href="http://blog.moertel.com/articles/2006/10/18/a-type-based-solution-to-the-strings-problem"&gt;a type-based solution to the strings problem&lt;/a&gt; for one.&lt;/p&gt;


	&lt;p&gt;Cheers! &amp;#8212;Tom&lt;/p&gt;</description>
      <pubDate>Mon, 05 Feb 2007 11:07:48 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ba07d673-a6e0-46c5-978a-8f5771b15e0d</guid>
      <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe#comment-361</link>
    </item>
    <item>
      <title>"If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?" by John Nowak</title>
      <description>&lt;p&gt;Aye.. What other sort of solution was possible here? Whoever wrote the test expected broken behaviour. He tested for broken behaviour. His test passed, and hence, we got broken behaviour. No language can save a programmer from herself if she doesn&amp;#8217;t know what her own functions are supposed to be doing.&lt;/p&gt;</description>
      <pubDate>Mon, 05 Feb 2007 03:33:24 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3e38de30-744d-46f0-b3d5-6d9d50ffce87</guid>
      <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe#comment-359</link>
    </item>
    <item>
      <title>"If unit testing can't keep Rails safe from string-escaping problems, what makes you think it will keep your projects safe?" by Levi</title>
      <description>&lt;p&gt;Arg.  I was patiently awaiting your Haskell solution to this problem, and thought, when this article showed up in my feeds, that you were going to present it here.&lt;/p&gt;


	&lt;p&gt;I will now go back to waiting patiently. :)&lt;/p&gt;</description>
      <pubDate>Thu, 12 Oct 2006 17:19:13 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:be4e80c3-983f-4ab6-87c7-5684e6ad0b43</guid>
      <link>http://blog.moertel.com/articles/2006/10/12/if-unit-testing-cant-keep-rails-safe-from-string-escaping-problems-what-makes-you-think-it-will-keep-your-projects-safe#comment-185</link>
    </item>
  </channel>
</rss>
