Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate mass-assignment security to strong_parameters #1609

Merged
merged 4 commits into from
Aug 6, 2014

Conversation

ferrous26
Copy link
Member

Ahead of the upgrade to Rails 4, this change removes the use of attr_accessible and attr_protected as mass assignment protection mechanisms in favour of whitelisting input attributes at the controller level.

See http://blog.markusproject.org/?p=5588 for more details.

All tests are passing, and some playing around with a local server seemed to work correctly. At this point I have some confidence that this is done correctly.

@@ -1,3 +1,7 @@
Dir.glob("app/models/*_submission_rule.rb").each do |rule|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer single-quoted strings when you don't need string interpolation or special symbols.

@lvwrence
Copy link
Contributor

So basically all controller actions that have to do with creating and editing resources have parameters go through the whitelist at resource_params, correct?

@ferrous26
Copy link
Member Author

@oneohtrix yes, the idea is to make sure that if you are just going to pass an arbitrary list of variables through initialize/update a model, the list should be filtered to only allow attributes which users should be allowed to modify. Obviously not a silver bullet, input still needs to be sanitized; this is just another layer of defence.

Alternatively, models can be, and in some cases are, updated like so

@annotation = TextAnnotation.create({
, which does not use strong parameters because it makes tis own list of which attributes to allow and extracts those attributes manually.


unless potential_rule && potential_rule.ancestors.include?(SubmissionRule)
raise I18n.t('assignment.not_valid_submission_rule',
type: params[:assignment][:submission_rule_attributes][:type])
raise SubmissionRule::InvalidRuleType.new(rule_name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Ruby style guide recommends raising through two arguments to raise instead of explicitly using the initializer:

raise SubmissionRule::InvalidRuleType, rulename

@david-yz-liu
Copy link
Contributor

@ferrous26 Thanks for doing this!

@zhangsu's last comment about the submission rules prompted me to do some digging... There's a lot of funny stuff going on with the submission rules, but one bug that your PR introduces for sure is that we lose the ability to "Remove" periods (all three rule types). That is, when you click the Remove checkbox and submit, the "Successful update" message is displayed, but the period is still there.

@david-yz-liu
Copy link
Contributor

@ferrous26 Here's another fun one: if section due dates are used, every time the settings page gets updated, redundant section due date entries are added into the database, and the redundancies are displayed after the page refreshes.

@ferrous26
Copy link
Member Author

So....submission rules are handled by a bunch of hacks:

    # Was the SubmissionRule changed?  If so, switch the type of the
    # SubmissionRule. This little conditional has to do some hack-y
    # workarounds, since accepts_nested_attributes_for is a little...dumb.

I played around with it a bit and found that what happens is that the code expects to nuke every period on a submission rule update, and then create new periods. However, the old periods were referencesd in the submitted parameters, and they would get filtered out by strong_parameters because I did not allow the id parameter on the period of the submission_rule_attributes of the assignment_attributes.

It seems weird that those values are getting submitted if they are not being changed, and they are not coming through with a _destroy marker to indicate they should be deleted. The only solution I can think of right now is just to rewrite the hacks to actually work properly with strong_parameters.

@david-yz-liu
Copy link
Contributor

Yeah, that's probably the best option. Is it possible to revert to the old params passing for the submission rules and merge the other changes, and then continue work on submission rules in another PR?

@ferrous26
Copy link
Member Author

Strong parameters is an all or nothing deal. There is an option to simply white list all input or a subset of input (without regard for what that subset actually contains).

Though, I can put the submission rule stuff in a separate commit, if that helps.

# the case of a mixture the input is a hash, and if there are no
# periods at all then the periods_attributes will be nil
periods = submission_rule_params[:periods_attributes]
periods = if periods.kind_of?(Hash)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer Object#is_a? over Object#kind_of?.

@ferrous26
Copy link
Member Author

@david-yz-liu GH-1622 and all submission rule updating funkiness that I could find has been addressed in c40f051

Ahead of the upgrade to Rails 4, this change removes the use of
attr_accessible and attr_protected as mass assignment protection
mechanisms in favour of whitelisting input attributes at the
controller level.

See http://blog.markusproject.org/?p=5588 for more details.
@david-yz-liu
Copy link
Contributor

@ferrous26 Nice job, thanks! Once you fix the bug with the dubplicating Section Due Dates, I will merge this.

They were not being properly whitelisted previously, and the
workaround did not check if the due dates already existed before
creating new due dates.

This fix allows Rails to simply Do The Right Thing.
@ferrous26
Copy link
Member Author

@david-yz-liu done

@ferrous26
Copy link
Member Author

There are some test failures now, but they appear to be false positives. I am looking into it now.

date = Time.parse(value['due_date'])
due_date =
new_assignment.section_due_dates
.find { |d| d.due_date == date}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer detect over find.
Space missing inside }.

And fix broken tests which were providing false failures.
date = Time.parse(value['due_date'])
due_date =
new_assignment.section_due_dates
.find { |d| d.due_date == date }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer detect over find.

@ferrous26
Copy link
Member Author

Ok, all fixed up now.

Though, I strongly disagree with Hound on the matter of #find vs. #detect. When did #detect get in vogue?

david-yz-liu pushed a commit that referenced this pull request Aug 6, 2014
Migrate mass-assignment security to strong_parameters
@david-yz-liu david-yz-liu merged commit 89a2a30 into MarkUsProject:master Aug 6, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants