# How to secure records?

**URL:** <https://www.ruby-forum.com/t/how-to-secure-records/65637>\
**Category:** Rails\
**Created:** [August 20, 2006, 3:34am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637 "2006-08-20T03:34:42Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 20, 2006, 3:34am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/1 "2006-08-20T03:34:42Z")

</div>

I have “users”, “company” and “contract” controllers, with the following  
relations:

class User \< ActiveRecord::Base  
has\_many :companies

class Company \< ActiveRecord::Base  
belongs\_to :user  
has\_many :contracts

class Contract \< ActiveRecord::Base  
belongs\_to :company

I had no problem using ruby to create management interface for it (and i  
started programming in ruby two weeks ago!!). What concerns me is  
security of records. Here’s what needs to be done:

1. actions like for example /company/edit/1 should raise error when  
Company with id=1 doesn’t belong to logged User (i’m using login  
generator gem), same for Contracts (ownership needs to be checked  
through Companies table).

2. system should be immune to hidden field abuse (like: download html  
for /company/edit/30, edit html and replace user\_id, visit from  
localhost, submit to overtake record)

How to do that?? Here’s what i found so far:

1. Use subselect/joins to check permission at the beginning of every  
chosen action in controller  
@contract=Contract.find\_by\_sql(‘select contract.\* from “contracts” r  
left join “companies” p on p.“id”=r.“company\_id” left join “users” …  
where user.“id”=’+@session[‘user’].id)  
if not found then raise error…  
working, but ugly as hell and i’m repeating myslef often in different  
actions.

2. Use :through property instead joins above (don’t know how to use it  
properly yet)

3. Use validates\_associated in model (doesnt protect from hidden field  
abuse, cannot work through many tables like  
Contract\>o----Company\>o----User - or can it??)

4. Write validation of ownership in model, not controller, similiar to  
validates\_associated but smarter

5. ??Some ready-to-use stuf maybe??

Thanks for advices.

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 20, 2006, 3:58am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/2 "2006-08-20T03:58:07Z")

</div>

This is a really basic response, but it may give you an idea.

When you call your ‘company/edit’ action, just do this:

@user = User.find(session[:user\_id]) # This assumes that you are using  
cookies to authenticate  
@company = @user.companies.find(params[:id])

This ensures that you are not editing companies out of scope for the  
owning  
user.

Does that help?

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 20, 2006, 4:18am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/3 "2006-08-20T04:18:19Z")

</div>

thanks for answer. that’s just how i’m doing it now.

question is - can such ownership check be moved to models?? so when we  
get :id or @params[‘contract’].id for example in Contract class  
subselect/join is performed to check if it really belongs to logged  
user, and if not error is raised.

why??

- because then scaffolded actions can be used for stuff like  
contract/update safely
- no code copy/paste in every action in controller
- one central ownership validation for controller is less error prone  
and easier to modify

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 20, 2006, 9:00am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/4 "2006-08-20T09:00:26Z")

</div>

Take a look at the authorization plugin:  
[http://www.writertopia.com/developers/authorization](http://www.writertopia.com/developers/authorization)

I especially like the authorization DSL.

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 20, 2006, 7:48am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/5 "2006-08-20T07:48:20Z")

</div>

Off the top of my head, I can’t see a way to do this. It seems to be  
out of  
the scope w/ the MVC here, and that the controller really needs to be  
handling this rather than the model.

Now, you could override the methods of your class so that they require  
an id  
to be passed to them for each action… but that sounds like a lot of  
extra  
work.

Maybe someone else has some insight here…

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 21, 2006, 9:46am UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/6 "2006-08-21T09:46:35Z")

</div>

This is best practice in Rails anyway, but you should protect certain  
attributes of your Model from being mass assigned - for example in the  
way you’ve defined below by editing a form source and resubmitting.

The way to do that is to use the attr\_protected command in your model  
to declare attributes that can only be set manually in your code. They  
cannot be set using bulk assignments from outside such as  
Model.create(params[:model]).

e.g.

class Company \< ActiveRecord::Base  
attr\_protected :user\_id  
end

Alternatively you can use attr\_accessible to explicitly declare which  
fields can be mass assigned from form query parameters. It’s up to you  
as to which of the opt-in or opt-out models you go for.

There’s more information on this in section 21.4 (“Creating Records  
Directly from Form Parameters”) in chapter 21 (“Securing Your Rails  
Application”) of the Agile Web D. with Rails book. It’s really  
worth reading as it covers this and many other factors in securing code

- if so, go for the 2nd Edition beta book available at Pragmatic  
Programmers as it is covering the more recent changes to the Rails  
codebase.

Ian

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 21, 2006, 3:43pm UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/7 "2006-08-21T15:43:26Z")

</div>

I’m not sure if this fits well to your problem, but did you have a look  
at [http://perens.com/FreeSoftware/ModelSecurity/](http://perens.com/FreeSoftware/ModelSecurity/) ? It’s not really  
maintained actively, but it seems quite stable anyway

cheers  
Martin

---

<div class="post-metadata">

**Author:** ![bbkr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/ce73a5/32.png) [@bbkr](https://www.ruby-forum.com/u/bbkr)\
**Post date:** [August 21, 2006, 3:02pm UTC](https://www.ruby-forum.com/t/how-to-secure-records/65637/8 "2006-08-21T15:02:25Z")

</div>

Along with attr\_protected and/or attr\_accessible to limit write access  
to fields from forms, you may be interested in the ScopedAccess plugin:

[http://habtm.com/articles/2006/02/22/nested-with\_scope](http://habtm.com/articles/2006/02/22/nested-with_scope)

…which essentially lets you apply a with\_scope clause as a filter at  
the controller level.

Bbkr I juz wrote:

> I have “users”, “company” and “contract” controllers, with the following  
> relations:
> 
> class User \< ActiveRecord::Base  
> has\_many :companies
> 
> class Company \< ActiveRecord::Base  
> belongs\_to :user  
> has\_many :contracts
> 
> class Contract \< ActiveRecord::Base  
> belongs\_to :company
> 
> I had no problem using ruby to create management interface for it (and i  
> started programming in ruby two weeks ago!!). What concerns me is  
> security of records. Here’s what needs to be done:
> 
> 1. actions like for example /company/edit/1 should raise error when  
> Company with id=1 doesn’t belong to logged User (i’m using login  
> generator gem), same for Contracts (ownership needs to be checked  
> through Companies table).
> 
> 2. system should be immune to hidden field abuse (like: download html  
> for /company/edit/30, edit html and replace user\_id, visit from  
> localhost, submit to overtake record)  
> … [snip]
