Security Tip: Sensitive Model Attributes
[Tip#8] We need to be careful of sensitive data and where it gets passed around, especially when it relates to models and Javascript.
Traditionally our database models are stored and contained on the server, and we can throw whatever data into them - including sensitive data. However, javascript frameworks like Vue.js, Inertia.js, and even Livewire, make it easy to interact with your models directly in the browser, and if it’s in the browser, it’s publicly visible.
It’s not just javascript frameworks which will do this too! I recently discovered one of my models was leaked on a page in my app because I had passed it into a Blade component, but forgotten to tell Blade it was a prop, not an attribute. So Blade treated it as an attribute and serialized it into the HTML!! It’s super simple to accidently sensitive leak data through models if you’re passing them around the view or javascript layers.
The risk here is simple: if you store sensitive data on your models and send these to the browser, it may end up in the browser, and someone could find it1.
We’re talking about password hashes2, dates of birth, API keys, secret messages, staff comments, etc. The list goes on and on… Basically anything that the person making the request shouldn’t have access to.
Lucky for us, Laravel makes it super easy to protect sensitive model attributes.
We can use the `$hidden`
property on our models to specify attributes which should be hidden when the model is turned into an Array or a JSON object:
class User extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = ['password', 'staff_comments'];
}
These attributes will be excluded when the model is turned into an Array or JSON, before being sent to the browser.
Alternatively, we can also use an allow list approach to define the fields we want to be included, blocking all other attributes:
class User extends Model
{
/**
* The attributes that should be visible in arrays.
*
* @var array
*/
protected $visible = ['first_name', 'last_name'];
}
As seen recently in the US when Social Security Numbers were exposed in the source code of a government website: https://www.itnews.com.au/news/us-governor-accuses-source-code-viewing-site-visitor-of-hacking-571312
You are hashing these, right???