There seems to be much interest lately in input filtering in PHP, especially in cross site scripting prevention. I’ve always preferred input validation to input filtering, but I am giving filtering a new examination. My problem with filtering is with usability. The comments to this post are a good example. There are obviously some usability issues going on here.
I think the fundamental problem with input filtering and especially XSS filtering is that it violates the principle of least surprise. User input is silently modified without the user’s knowledge. If the violation is innocent, then the software surprises the user. This is bad. At least with validation, the user gets a heads up on the problem.
Let me try to name and enumerate some scenarios:
This is what WordPress did in the example post. It simply accepted the user input and silently changed it. The filtered value is stored directly into the database. The original input is lost. There is no preview. I think this has to be a usability worse case scenario.
Filter with Preview
This scenario adds a preview capability to the last. The filter is still applied. A validation failure or explicit preview button causes the form values to be re-displayed and a preview panel to be shown. However, the previous input value is silently modified and sent back to the user. The user may or may not realize that his original input has been changed during the round trip.
This is also seems like a usability problem, but every once and a while it happens to me when entering legitimate input into professionally written programs.
Filter with Buffered Preview
This scenario adds an additional buffer to the last. The filter is applied, but the original input is sent back to the user in the form field. However, the preview panel shows the modified value.
I don’t really see this very often outside of fields with a dedicated markup language (for example BBCode).
Filter with Forced Preview
The input value is silently filtered. However, the user is forced to preview the output at least once. Its up to the user to notice the results of the filter.
I think slashdot does this.
Filter with Confirmation
A stricter variation of Forced Preview where as the last stage, the user must confirm their input once without the ability to change it. It is up to the user to notice the results of the filter.
I think this is popular as the last stage of a wizard style interface.
Filter with Confirmation and Warning
The filter is applied and the user’s input is changed, however, the user is warned exactly which value was changed by the filter.
I don’t think I’ve ever seen this one.
The program notifies the user that the input value is bad, but does not modify it. The user must change the value to proceed.
I tend to use this one. I escape all output, so I don’t worry too much about displaying XSS in the preview panel.
Obviously, you can mix and match scenarios for different input rules and fields. I’m sure there are other scenarios. Please suggest some.
I guess I’ve been programming for about 23 years now. The longer I do it, the more reluctant I am to be strict with user input. Ultra sanitized, ultra structured data may seem attractive to the programmer, but its a pain for the user and its only a matter of time before a legitimate exception comes along. A European phone number, the 51rst state, a canadian postal code, a new millennium, etc. The exception is the rule. Understandably, XSS must be prevented, but its easy to go too far.
Which of these scenarios do you think are best from the user’s perspective? From the programmers perspective?