Search code examples
filtervalidationwhitelistblacklist

blacklisting vs whitelisting in form's input filtering and validation


which is the preferred approach in sanitizing inputs coming from the user?

thank you!


Solution

  • I think whitelisting is the desired approach, however I never met a real whitelist HTML form validation. For example here is a symfony 1.x form with validation from the documentation:

    class ContactForm extends sfForm  
    {  
      protected static $subjects = array('Subject A', 'Subject B', 'Subject C');  
    
      public function configure()  
      {  
        $this->setWidgets(array(  
          'name'    => new sfWidgetFormInput(),  
          'email'   => new sfWidgetFormInput(),  
          'subject' => new sfWidgetFormSelect(array('choices' => self::$subjects)),  
          'message' => new sfWidgetFormTextarea(),  
        ));  
        $this->widgetSchema->setNameFormat('contact[%s]');  
    
        $this->setValidators(array(  
          'name'    => new sfValidatorString(array('required' => false)),  
          'email'   => new sfValidatorEmail(),  
          'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))),  
          'message' => new sfValidatorString(array('min_length' => 4)),  
        ));  
      }  
    } 
    

    What you cannot see, that it accepts new inputs without validation settings and it does not check the presence of inputs which are not registered in the form. So this is a blacklist input validation. By whitelist you would define an input validator first, and only after that bind an input field to that validator. By a blacklist approach like this, it is easy to forget to add a validator to an input, and it works perfectly without that, so you would not notice the vulnerability, only when it is too late...

    A hypothetical whitelist approach would look like something like this:

    class ContactController {
        /**
        * @input("name", type = "string", singleLine = true, required = false)
        * @input("email", type = "email")
        * @input("subject", type = "string", alternatives = ['Subject A', 'Subject B', 'Subject C'])
        * @input("message", type = "string", range = [4,])
        */
        public function post(Inputs $inputs){
            //automatically validates inputs
            //throws error when an input is not on the list
            //throws error when an input has invalid value
        }
    }
    
    /**
    * @controller(ContactController)
    * @method(post)
    */
    class ContactForm extends sfFormX {
    
      public function configure(InputsMeta $inputs)  
      {
        //automatically binds the form to the input list of the @controller.@method
        //throws error when the @controller.@method.@input is not defined for a widget
        $this->addWidgets(
          new sfWidgetFormInput($inputs->name),  
          new sfWidgetFormInput($inputs->email),  
          new sfWidgetFormSelect($inputs->subject),  
          new sfWidgetFormTextarea($inputs->message)
        );
        $this->widgetSchema->setNameFormat('contact[%s]');  
      }  
    }