Skip to content

Commit

Permalink
Fix XSS vulnerability in filter and multi-select widget
Browse files Browse the repository at this point in the history
Fixes #2985, Closes #2894, Closes #2987
  • Loading branch information
mshibuya committed Feb 17, 2018
1 parent 1f9c72d commit 44f09ed
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 65 deletions.
182 changes: 123 additions & 59 deletions app/assets/javascripts/rails_admin/ra.filter-box.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,90 +19,154 @@

switch(field_type) {
case 'boolean':
var control = '<select class="input-sm form-control" name="' + value_name + '">' +
'<option value="_discard">...</option>' +
'<option value="true"' + (field_value == "true" ? 'selected="selected"' : '') + '>' + RailsAdmin.I18n.t("true") + '</option>' +
'<option value="false"' + (field_value == "false" ? 'selected="selected"' : '') + '>' + RailsAdmin.I18n.t("false") + '</option>' +
'<option disabled="disabled">---------</option>' +
'<option ' + (field_value == "_present" ? 'selected="selected"' : '') + ' value="_present">' + RailsAdmin.I18n.t("is_present") + '</option>' +
'<option ' + (field_value == "_blank" ? 'selected="selected"' : '') + ' value="_blank" >' + RailsAdmin.I18n.t("is_blank") + '</option>' +
'</select>';
control = $('<select class="input-sm form-control"></select>')
.prop('name', value_name)
.append('<option value="_discard">...</option>')
.append($('<option value="true"></option>').prop('selected', field_value == "true").text(RailsAdmin.I18n.t("true")))
.append($('<option value="false"></option>').prop('selected', field_value == "false").text(RailsAdmin.I18n.t("false")))
.append('<option disabled="disabled">---------</option>')
.append($('<option value="_present"></option>').prop('selected', field_value == "_present").text(RailsAdmin.I18n.t("is_present")))
.append($('<option value="_blank"></option>').prop('selected', field_value == "_blank").text(RailsAdmin.I18n.t("is_blank")));
break;
case 'date':
additional_control =
'<input size="20" class="date additional-fieldset default input-sm form-control" style="display:' + ((!field_operator || field_operator == "default") ? 'inline-block' : 'none') + ';" type="text" name="' + value_name + '[]" value="' + (field_value[0] || '') + '" /> ' +
'<input size="20" placeholder="-∞" class="date additional-fieldset between input-sm form-control" style="display:' + ((field_operator == "between") ? 'inline-block' : 'none') + ';" type="text" name="' + value_name + '[]" value="' + (field_value[1] || '') + '" /> ' +
'<input size="20" placeholder="∞" class="date additional-fieldset between input-sm form-control" style="display:' + ((field_operator == "between") ? 'inline-block' : 'none') + ';" type="text" name="' + value_name + '[]" value="' + (field_value[2] || '') + '" />';
$('<input size="20" class="date additional-fieldset default input-sm form-control" type="text" />')
.css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
.prop('name', value_name + '[]')
.prop('value', field_value[0] || '')
.add(
$('<input size="20" placeholder="-∞" class="date additional-fieldset between input-sm form-control" type="text" />')
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
.prop('name', value_name + '[]')
.prop('value', field_value[1] || '')
)
.add(
$('<input size="20" placeholder="∞" class="date additional-fieldset between input-sm form-control" type="text" />')
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
.prop('name', value_name + '[]')
.prop('value', field_value[2] || '')
);
case 'datetime':
case 'timestamp':
control = control || '<select class="switch-additionnal-fieldsets input-sm form-control" name="' + operator_name + '">' +
'<option ' + (field_operator == "default" ? 'selected="selected"' : '') + ' data-additional-fieldset="default" value="default">' + RailsAdmin.I18n.t("date") + '</option>' +
'<option ' + (field_operator == "between" ? 'selected="selected"' : '') + ' data-additional-fieldset="between" value="between">' + RailsAdmin.I18n.t("between_and_") + '</option>' +
'<option ' + (field_operator == "today" ? 'selected="selected"' : '') + ' value="today">' + RailsAdmin.I18n.t("today") + '</option>' +
'<option ' + (field_operator == "yesterday" ? 'selected="selected"' : '') + ' value="yesterday">' + RailsAdmin.I18n.t("yesterday") + '</option>' +
'<option ' + (field_operator == "this_week" ? 'selected="selected"' : '') + ' value="this_week">' + RailsAdmin.I18n.t("this_week") + '</option>' +
'<option ' + (field_operator == "last_week" ? 'selected="selected"' : '') + ' value="last_week">' + RailsAdmin.I18n.t("last_week") + '</option>' +
'<option disabled="disabled">---------</option>' +
'<option ' + (field_operator == "_not_null" ? 'selected="selected"' : '') + ' value="_not_null">' + RailsAdmin.I18n.t("is_present") + '</option>' +
'<option ' + (field_operator == "_null" ? 'selected="selected"' : '') + ' value="_null" >' + RailsAdmin.I18n.t("is_blank") + '</option>' +
'</select>'
control = control || $('<select class="switch-additionnal-fieldsets input-sm form-control"></select>')
.prop('name', operator_name)
.append($('<option data-additional-fieldset="default" value="default"></option>').prop('selected', field_operator == "default").text(RailsAdmin.I18n.t("date")))
.append($('<option data-additional-fieldset="between" value="between"></option>').prop('selected', field_operator == "between").text(RailsAdmin.I18n.t("between_and_")))
.append($('<option value="today"></option>').prop('selected', field_operator == "today").text(RailsAdmin.I18n.t("today")))
.append($('<option value="yesterday"></option>').prop('selected', field_operator == "yesterday").text(RailsAdmin.I18n.t("yesterday")))
.append($('<option value="this_week"></option>').prop('selected', field_operator == "this_week").text(RailsAdmin.I18n.t("this_week")))
.append($('<option value="last_week"></option>').prop('selected', field_operator == "last_week").text(RailsAdmin.I18n.t("last_week")))
.append('<option disabled="disabled">---------</option>')
.append($('<option value="_not_null"></option>').prop('selected', field_operator == "_not_null").text(RailsAdmin.I18n.t("is_present")))
.append($('<option value="_null"></option>').prop('selected', field_operator == "_null").text(RailsAdmin.I18n.t("is_blank")));
additional_control = additional_control ||
'<input size="25" class="datetime additional-fieldset default input-sm form-control" style="display:' + ((!field_operator || field_operator == "default") ? 'inline-block' : 'none') + ';" type="text" name="' + value_name + '[]" value="' + (field_value[0] || '') + '" /> ' +
'<input size="25" placeholder="-∞" class="datetime additional-fieldset between input-sm form-control" style="display:' + ((field_operator == "between") ? 'inline-block' : 'none') + ';" type="text" name="' + value_name + '[]" value="' + (field_value[1] || '') + '" /> ' +
'<input size="25" placeholder="∞" class="datetime additional-fieldset between input-sm form-control" style="display:' + ((field_operator == "between") ? 'inline-block' : 'none') + ';" type="text" name="' + value_name + '[]" value="' + (field_value[2] || '') + '" />';
$('<input size="25" class="datetime additional-fieldset default input-sm form-control" type="text" />')
.css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
.prop('name', value_name + '[]')
.prop('value', field_value[0] || '')
.add(
$('<input size="25" placeholder="-∞" class="datetime additional-fieldset between input-sm form-control" type="text" />')
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
.prop('name', value_name + '[]')
.prop('value', field_value[1] || '')
)
.add(
$('<input size="25" placeholder="∞" class="datetime additional-fieldset between input-sm form-control" type="text" />')
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
.prop('name', value_name + '[]')
.prop('value', field_value[2] || '')
);
break;
case 'enum':
var multiple_values = ((field_value instanceof Array) ? true : false)
control = '<select style="display:' + (multiple_values ? 'none' : 'inline-block') + '" ' + (multiple_values ? '' : 'name="' + value_name + '"') + ' data-name="' + value_name + '" class="select-single input-sm form-control">' +
'<option value="_discard">...</option>' +
'<option ' + (field_value == "_present" ? 'selected="selected"' : '') + ' value="_present">' + RailsAdmin.I18n.t("is_present") + '</option>' +
'<option ' + (field_value == "_blank" ? 'selected="selected"' : '') + ' value="_blank">' + RailsAdmin.I18n.t("is_blank") + '</option>' +
'<option disabled="disabled">---------</option>' +
select_options +
'</select>' +
'<select multiple="multiple" style="display:' + (multiple_values ? 'inline-block' : 'none') + '" ' + (multiple_values ? 'name="' + value_name + '[]"' : '') + ' data-name="' + value_name + '[]" class="select-multiple input-sm form-control">' +
select_options +
'</select> ' +
'<a href="#" class="switch-select"><i class="icon-' + (multiple_values ? 'minus' : 'plus') + '"></i></a>';
control = $('<select class="select-single input-sm form-control"></select>')
.css('display', multiple_values ? 'none' : 'inline-block')
.prop('name', multiple_values ? undefined : value_name)
.data('name', value_name)
.append('<option value="_discard">...</option>')
.append($('<option value="_present"></option>').prop('selected', field_value == "_present").text(RailsAdmin.I18n.t("is_present")))
.append($('<option value="_blank"></option>').prop('selected', field_value == "_blank").text(RailsAdmin.I18n.t("is_blank")))
.append('<option disabled="disabled">---------</option>')
.append(select_options)
.add(
$('<select multiple="multiple" class="select-multiple input-sm form-control"></select>')
.css('display', multiple_values ? 'inline-block' : 'none')
.prop('name', multiple_values ? value_name + '[]' : undefined)
.data('name', value_name + '[]')
.append(select_options)
)
.add(
$('<a href="#" class="switch-select"></a>')
.append($('<i></i>').addClass('icon-' + (multiple_values ? 'minus' : 'plus')))
);
break;
case 'string':
case 'text':
case 'belongs_to_association':
control = '<select class="switch-additionnal-fieldsets input-sm form-control" value="' + field_operator + '" name="' + operator_name + '">' +
'<option data-additional-fieldset="additional-fieldset"' + (field_operator == "like" ? 'selected="selected"' : '') + ' value="like">' + RailsAdmin.I18n.t("contains") + '</option>' +
'<option data-additional-fieldset="additional-fieldset"' + (field_operator == "is" ? 'selected="selected"' : '') + ' value="is">' + RailsAdmin.I18n.t("is_exactly") + '</option>' +
'<option data-additional-fieldset="additional-fieldset"' + (field_operator == "starts_with" ? 'selected="selected"' : '') + ' value="starts_with">' + RailsAdmin.I18n.t("starts_with") + '</option>' +
'<option data-additional-fieldset="additional-fieldset"' + (field_operator == "ends_with" ? 'selected="selected"' : '') + ' value="ends_with">' + RailsAdmin.I18n.t("ends_with") + '</option>' +
'<option disabled="disabled">---------</option>' +
'<option ' + (field_operator == "_not_null" ? 'selected="selected"' : '') + ' value="_not_null">' + RailsAdmin.I18n.t("is_present") + '</option>' +
'<option ' + (field_operator == "_null" ? 'selected="selected"' : '') + ' value="_null">' + RailsAdmin.I18n.t("is_blank") + '</option>' +
'</select>'
additional_control = '<input class="additional-fieldset input-sm form-control" style="display:' + (field_operator == "_blank" || field_operator == "_present" ? 'none' : 'inline-block') + ';" type="text" name="' + value_name + '" value="' + field_value + '" /> ';
control = $('<select class="switch-additionnal-fieldsets input-sm form-control"></select>')
.prop('value', field_operator)
.prop('name', operator_name)
.append('<option value="_discard">...</option>')
.append($('<option data-additional-fieldset="additional-fieldset" value="like"></option>').prop('selected', field_operator == "like").text(RailsAdmin.I18n.t("contains")))
.append($('<option data-additional-fieldset="additional-fieldset" value="is"></option>').prop('selected', field_operator == "is").text(RailsAdmin.I18n.t("is_exactly")))
.append($('<option data-additional-fieldset="additional-fieldset" value="starts_with"></option>').prop('selected', field_operator == "starts_with").text(RailsAdmin.I18n.t("starts_with")))
.append($('<option data-additional-fieldset="additional-fieldset" value="ends_with"></option>').prop('selected', field_operator == "ends_with").text(RailsAdmin.I18n.t("ends_with")))
.append('<option disabled="disabled">---------</option>')
.append($('<option value="_present"></option>').prop('selected', field_operator == "_present").text(RailsAdmin.I18n.t("is_present")))
.append($('<option value="_blank"></option>').prop('selected', field_operator == "_blank").text(RailsAdmin.I18n.t("is_blank")));
additional_control = $('<input class="additional-fieldset input-sm form-control" type="text" />')
.css('display', field_operator == "_present" || field_operator == "_blank" ? 'none' : 'inline-block')
.prop('name', value_name)
.prop('value', field_value);
break;
case 'integer':
case 'decimal':
case 'float':
control = '<select class="switch-additionnal-fieldsets input-sm form-control" name="' + operator_name + '">' +
'<option ' + (field_operator == "default" ? 'selected="selected"' : '') + ' data-additional-fieldset="default" value="default">' + RailsAdmin.I18n.t("number") + '</option>' +
'<option ' + (field_operator == "between" ? 'selected="selected"' : '') + ' data-additional-fieldset="between" value="between">' + RailsAdmin.I18n.t("between_and_") + '</option>' +
'<option disabled="disabled">---------</option>' +
'<option ' + (field_operator == "_not_null" ? 'selected="selected"' : '') + ' value="_not_null">' + RailsAdmin.I18n.t("is_present") +'</option>' +
'<option ' + (field_operator == "_null" ? 'selected="selected"' : '') + ' value="_null" >' + RailsAdmin.I18n.t("is_blank") + '</option>' +
'</select>'
control = $('<select class="switch-additionnal-fieldsets input-sm form-control"></select>')
.prop('name', operator_name)
.append($('<option data-additional-fieldset="default" value="default"></option>').prop('selected', field_operator == "default").text(RailsAdmin.I18n.t("number")))
.append($('<option data-additional-fieldset="between" value="between"></option>').prop('selected', field_operator == "between").text(RailsAdmin.I18n.t("between_and_")))
.append('<option disabled="disabled">---------</option>')
.append($('<option value="_not_null"></option>').prop('selected', field_operator == "_not_null").text(RailsAdmin.I18n.t("is_present")))
.append($('<option value="_null"></option>').prop('selected', field_operator == "_null").text(RailsAdmin.I18n.t("is_blank")));
additional_control =
'<input class="additional-fieldset default input-sm form-control" style="display:' + ((!field_operator || field_operator == "default") ? 'inline-block' : 'none') + ';" type="' + field_type + '" name="' + value_name + '[]" value="' + (field_value[0] || '') + '" /> ' +
'<input placeholder="-∞" class="additional-fieldset between input-sm form-control" style="display:' + ((field_operator == "between") ? 'inline-block' : 'none') + ';" type="' + field_type + '" name="' + value_name + '[]" value="' + (field_value[1] || '') + '" /> ' +
'<input placeholder="∞" class="additional-fieldset between input-sm form-control" style="display:' + ((field_operator == "between") ? 'inline-block' : 'none') + ';" type="' + field_type + '" name="' + value_name + '[]" value="' + (field_value[2] || '') + '" />';
$('<input class="additional-fieldset default input-sm form-control" type="text" />')
.css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
.prop('type', field_type)
.prop('name', value_name + '[]')
.prop('value', field_value[0] || '')
.add(
$('<input placeholder="-∞" class="additional-fieldset between input-sm form-control" />')
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
.prop('type', field_type)
.prop('name', value_name + '[]')
.prop('value', field_value[1] || '')
)
.add(
$('<input placeholder="∞" class="additional-fieldset between input-sm form-control" />')
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
.prop('type', field_type)
.prop('name', value_name + '[]')
.prop('value', field_value[2] || '')
);
break;
default:
control = '<input type="text" class="input-sm form-control" name="' + value_name + '" value="' + field_value + '"/> ';
control = $('<input type="text" class="input-sm form-control" />')
.prop('name', value_name)
.prop('value', field_value);
break;
}

var $content = $('<p>')
.addClass('filter form-search')
.append('<span class="label label-info form-label"><a href="#delete" class="delete"><i class="fa fa-trash-o fa-fw icon-white"></i>' + field_label + '</a></span>')
.append('&nbsp;' + control + '&nbsp;' + (additional_control || ''));
.append(
$('<span class="label label-info form-label"></span>')
.append($('<a href="#delete" class="delete"></a>').append('<i class="fa fa-trash-o fa-fw icon-white"></i>').append(document.createTextNode(field_label)))
)
.append('&nbsp;')
.append(control)
.append('&nbsp;')
.append(additional_control);

$('#filters_box').append($content);

Expand Down
Loading

0 comments on commit 44f09ed

Please sign in to comment.