Saturday, September 7, 2013

Non-Tainted Dart


I am pretty excited to see that Dart is taking security so seriously. I previously experienced this when I found that Dart severly restricts iframe communcation (for good reason). More recently, I have begun to see warnings of a different nature from my code:
Removing disallowed attribute <INPUT style="margin: -10px 4px;">
Any modern programming language ought to provide some protection from potentially untrusted data. It's a bit of hand-holding to be sure, but it's hand-holding that everyone concerned about protecting users ought to embrace. In other words, everyone ought to embrace it.

In all honesty, I wish that Dart would use a tainted model similar to Perl's -T option. In that model, any data from a user (e.g. from the web) would be marked as tainted. Any strings built from tainted data would itself be considered tainted. And any tainted data would throw an error it were used in a potentially dangerous operation (setting innerHtml, issuing a SQL command, etc).

In this case, I, the developer, am building the string with the questionable data in it:
  get _updateButton {
    return _update_button = new Element.html('''
        <button>
           <input
              checked
              type=checkbox
              title="$_update_tooltip"
              style="margin: -10px 4px;"/>
           Update
         </button>'''
      );
    // ...
  }
Now, if _update_tooltip contained data from the user (it doesn't), then I could understand this string being marked as potentially dangerous and in need of “de-tainting.” But I am hard-coding this as a developer and very much want that style applied, darn it. Without it, the display of the “Update” button is messed up and I get that annoying warning:




OK, enough griping. The motive behind the warning (and stripping of the attribute) is sound. Dart is trying to mitigate XSS attacks and this is a reasonabe approach to take. Ultimately I will move this particular style out into a stylesheet—there is no legitimate reason to have it here. But what if I did want it there?

One option is to remove the style from the string and place it into a method cascade:
  get _updateButton {
    return _update_button = new Element.html('''
        <button>
           <input
              checked
              type=checkbox
              title="$_update_tooltip"/>
           Update
         </button>'''
      )
      ..query('input').style.margin = '-10px 4px';
    // ...
  }
The double dot operator is a method cascade, which is among the coolest features of Dart. It calls the method—query() in this case—but returns the receiver of the method—the new element.

With that, I have eliminated my warning and have my style fixed:



OK, I suppose that was not too hard. But what if I really, really wanted that style implemented in the string. What options do I have?

Along with the change that introduced the warning, Dart also introduced some options for getting around it. The places in which the warning applies (innerHtml, new Element(), etc) also support overriding the default sanitizer and validator. The announcement on the mailing list included an example that used a null sanitizer:
class NullTreeSanitizer implements NodeTreeSanitizer {
  void sanitizeTree(node) {}
}
If I supply an instance of this class to the Element constructor:
  get _updateButton {
    return _update_button = new Element.html('''
        <button>
           <input
              checked
              type=checkbox
              title="$_update_tooltip"
              style="margin: -10px 4px;"/>
           Update
         </button>''',
        treeSanitizer: new NullTreeSanitizer()
      );
    // ...
  }
Then my style attribute still works and I get no complaints.

The documentation indicates that a node validator is required to override the default sanitization, but this is not the case—at least not yet. The null sanitizer is all that was needed. I can even include the old onClick attribute with my null sanitizer and not have any problems.

So, in the end, sanitizing strings seems a small price to pay for a safer web. I like that sanitizing is performed on a node in Dart. De-tainting strings in Perl and Ruby is done with regular expressions which can get a little awkward.

I still think that I would prefer a tainted model. Not so much for the convenience, but I appreciate it when Perl and Ruby remind me that, “hey this data is coming from outside and you might want to be cautious with it.” The Dart approach of “hey, you better be careful with anything you put in here” is still of definite benefit.

Now if you'll excuse me, I have some stylesheet work to do.


Day #867

2 comments:

  1. Perl's -w turns on warnings. I think you were looking for the script either having detected running setuid (effective and real uid not the same), or explicitly with the -T switch.

    ReplyDelete
    Replies
    1. Ah, shoot. You're right, of course. I was thinking of -T. Fixed.

      Thanks!

      Delete