4 ms·
One of my devs recently pitched an idea to me that I can't stop thinking about. Strong Params requires you to enumerate all params on the server. But why could
by latortuga 4y ago
One of my devs recently pitched an idea to me that I can't stop thinking about.
Strong Params requires you to enumerate all params on the server. But why couldn't you know what are valid params while building your form? You could serialize the params shape in the form builder and include it in your post payload, signed by the app secret to avoid tampering.
It should have done this from the beginning!
- jherdman 4y agoBecause a well crafted response could write whatever they wanted to your DB as you’ve given the client too much control. If I know, for instance, an admin is identified by an `is_admin` flag, I could add this to the allowed params and send my flag. Bam. I’m now an admin. I know the example is a bit simplistic, but it wouldn’t take long to comb your app for a real world example where this would be problematic.
- matthewmacleod 4y agoThat’s the point of the signature the above poster suggested - if you use the app secret to generate a signature of the valid parameters, then the client can’t edit this list without invalidating the signature and there is no risk of them modifying other fields. If your secret is compromised such that this becomes possible, you have way bigger problems. I’m not super keen myself as I prefer the implementation to be much more explicit than magic, but there doesn’t seem to be an obvious security hole here.
- latortuga 4y agoPrecisely. Strong Params is a canonical violation of DRY. When you build your form, you fill it with fields that are allowed to be filled out and submitted. Then you have to duplicate that work in the controller for no obvious benefit. As for "more explicit than magic" I prefer to think of this as "automatic" or "conventional" rather than magic. Much of Rails' "magic" is this exact kind of thing, allowing the right thing to automatically happen with the ability to step in or override manually when the convention isn't what you want. I get why you'd want it to be more explicit. I think that this feature was invented to solve a security problem and the solution was to give devs more work to do. There's no obvious reason why it couldn't be automatically taken care of for the dev and it would definitely make maintenance and legacy app upgrades smoother.
- Izkata 4y agoThese attacks work by modifying values, not adding parameters. Sounds like they would still work. Besides, you still have to validate the signature server-side, so it's not like it's saving any work. Validation just gets split up between generating the signature, a network round-trip, and validating the signature.
- derefr 4y ago> so it's not like it's saving any work The "work" the GP is trying to save here isn't CPU cycles, but rather developer labor — the redundant labor of writing both a form view that describes form inputs, and a form-value schema validator to be called from the controller that receives the form's submitted input values. Generating the signature, and validating the signature, would both be done transparently by middleware components of the framework, with no marginal developer labor required per form.
- Izkata 4y agoDjango forms already do that, and because of product requirements around design everyone I know who has used it has found it more of a pain than just doing the forms directly. You're just going to be in the HTML/CSS anyway to make it look right. Only for internal pages, where we didn't have bother with UI design, was it worthwhile.
- jdkoeck 4y agoNo idea why you're getting downvoted. It seems obvious to me too that you still have to validate server-side, so signing the form validation schema on the frontend is a waste of time.
- ghiculescu 4y agoThis wouldn’t work for APIs or controllers that you make requests to via JS, but for the default use case of forms it’s an _incredible_ idea. It would probably be not too hard to do as a gem - you inject a hidden field when form_with is called and you define a new method on params so the controller can indicate that this approach is being used.
- pmontra 4y agoI'm not sure that I understood your suggestion. What if the the client is curl -F name=Ryan -F age=34 ? How would I sign that request and why?
- mnutt 4y agoIt would only work for routes that only accept rails form_for input, and would reject requests without the signature.
- derefr 4y agoYou're talking about pure validation, though. dry-schema and the like, though, are more like in-memory ETL libraries for form data: they don't just describe a valid parameters shape, but also what — and how — to extract from those parameters, and an (implied) data-structure shape + typings to put the results into. I can see how you could generate the Extract step of an ETL process (i.e. a validation specification) purely from the form HTML itself. But I'm not sure where you'd stuff the information required to do the Transform or Load steps. It isn't cleanly separable into per-component data attributes.
- jeremyevans 4y agoThere is a Ruby form library named Forme that works this way for Roda and Sequel (https://forme.jeremyevans.net/files/README_rdoc.html#label-Roda+forme_set+plugin https://forme.jeremyevans.net/files/README_rdoc.html#label-R...). As you expect, this makes handling normal HTML form submissions much easier.
- claudiug 4y agojust want to say Roda and Sequel deserve a better marketing, you need a dhh, as they are great!