Protect against mass assignment vulnerabilities with a smarter params
object in the controller.
Install this plugin by grabbing the zip file from the latest release in the Releases tab on GitHub, placing it in the plugins folder of your CFWheels application, and reloading your app.
Next, add a call to the strongParams
controller intializer in your base
controllers/Controller.cfc
:
function init() {
strongParams();
}
Your model will now expect all mass assignment of properties from form posts and GET
parameters to
be cleared by the require
and permit
methods.
Any model method that accepts a struct of properties (or a set of named arguments) to set on the
model will not work if you pass that struct directly from params
:
// Throws an exception if `params.user` came from the URL or a form post.
user = model("user").new(params.user);
// Works fine.
user = model("user").new(name: "Andrew", isAdmin: true);
// Also works fine.
userParams = { name="Andrew", isAdmin=true };
user = model("user").new(userParams);
The model will accept a struct of parameters from the params
object if you call its require
and
permit
methods:
// Works fine! BUT this will only accept `name` and not `isAdmin` from a form post.
user = model("user").new(params.require("user").permit("name"));
A common pattern is to split the require
/permit
logic into a separate private method in your
controller:
function create() {
user = model("user").new(userParams());
if (user.save()) {
redirectTo(route: "user", key: user.key());
} else {
renderPage(action: "new");
}
}
private struct function userParams() {
return params.require("user").permit("name");
}
You then have a clean way to expand upon mass assignment logic based on permissions or whatever logic you need:
private struct function userParams() {
local.p = ["name"];
// User admins can set the `isAdmin` property from the form, but normal users cannot.
if (hasPermission("user-admin")) {
ArrayAppend(local.p, "isAdmin");
}
return params.require("user").permit(ArrayToList(local.p));
}
If you (for whatever reason) don't care about the parameters passed in via mass assignment, you can
use the permitAll
method on the params
object:
private struct function userParams() {
return params.require("user").permitAll();
}
The MIT License (MIT)
Copyright (c) 2017 Liquifusion Studios