[ss-2015-026]: BUG Fix FormField error messages not being encoded safely

This commit is contained in:
Damian Mooyman 2015-11-11 15:18:26 +13:00
parent f290d869e0
commit bc1b2893ac
3 changed files with 51 additions and 1 deletions

View File

@ -0,0 +1,25 @@
# 3.2.1
## Upgrading
FormField validation messages generated by the `Validator` class will now be automatically XML
encoded before being rendered alongside an invalid field.
If a validation message in a custom `Validator` instance should be rendered as literal HTML,
then the $message parameter for `Validator::validationError` should be passed as an instance
of `HTMLText`
For example:
:::php
class MyCustomValidator extends Validator {
public function php($data) {
$this->validationError(
'EmailAddress',
DBField::create_field('HTMLText', "Invalid email. Please sign up at <a href='signup'>this page</a>")
);
}
}

View File

@ -1303,6 +1303,18 @@ class Form extends RequestHandler {
// Load errors into session and post back
$data = $this->getData();
// Encode validation messages as XML before saving into session state
// As per Form::addErrorMessage()
$errors = array_map(function($error) {
// Encode message as XML by default
if($error['message'] instanceof DBField) {
$error['message'] = $error['message']->forTemplate();;
} else {
$error['message'] = Convert::raw2xml($error['message']);
}
return $error;
}, $errors);
Session::set("FormInfo.{$this->FormName()}.errors", $errors);
Session::set("FormInfo.{$this->FormName()}.data", $data);

View File

@ -235,6 +235,7 @@ class FormTest extends FunctionalTest {
'FormTest_Controller/Form',
array(
'Email' => 'invalid',
'Number' => '<a href="http://mysite.com">link</a>' // XSS attempt
// leaving out "Required" field
)
);
@ -253,6 +254,17 @@ class FormTest extends FunctionalTest {
),
'Required fields show a notification on field when left blank'
);
$this->assertContains(
'&#039;&lt;a href=&quot;http://mysite.com&quot;&gt;link&lt;/a&gt;&#039; is not a number, only numbers can be accepted for this field',
$response->getBody(),
"Validation messages are safely XML encoded"
);
$this->assertNotContains(
'<a href="http://mysite.com">link</a>',
$response->getBody(),
"Unsafe content is not emitted directly inside the response body"
);
}
public function testSessionSuccessMessage() {
@ -685,7 +697,8 @@ class FormTest_Controller extends Controller implements TestOnly {
new FieldList(
new EmailField('Email'),
new TextField('SomeRequiredField'),
new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two'))
new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two')),
new NumericField('Number')
),
new FieldList(
new FormAction('doSubmit')