Search code examples
htmlruby-on-railscoffeescriptxssjavascript-injection

Data-Attributes and Script Injection


For my rails application I use data-attributes rather extensively, as it was easy and the site was never expected to be finished or published, simply something I did for personal fun. A short example of the raw HTML would be

<span class="player-name" data-id="4" >Example Player</span>

I then could access the 'id' in coffeescript in the following way:

id = $('.player-name').data('id')

I was wondering if this utilization of data-attributes could potentially make the site susceptible to attacks through people editing the data-attribute in their developer console. Also if there is a better approach to accessing data in jQuery I would greatly appreciate it if someone could point me in the right direction. Thanks!


Solution

  • Yes, you're right. People can modify this. But this is hardly unique to data- attributes; people can modify anything and send any request with any parameters to your server.

    You should always validate data coming from clients. Always, always, always. Too often have I seen applications where I have an url such as http://example.com/orders/42 where modifying the 42 to 666 resulted in me viewing a stranger's order. Oops! With AJAX requests it takes a bit more effort to fake data, but not much. People can (and will!) modify anything on your client-side: URLs, HTML, JavaScript, CSS, etc. so it's always wrong to rely on that for security.

    In practice, this means that after getting an object from the database in your Rails app you should always check if the currently logged in user is allowed to view this object. For example, in a controller you might do something along the lines of:

    def show
        # Fetch it from the DB
        some_object = SomeObject.find params[:id]
    
        # Make sure the current user is authorized!
        raise if some_object.player_id != logged_in_player.id
    
        # ..your controller code..
    end
    

    I don't necessarily recommend you do this "manually" like in the above example. For Ruby on Rails there are two well-known gems to help with this:

    • Pundit; this is what I would recommend. It's simple, elegant, and flexible.
    • CanCan; also used a lot. It's more complicated than Pundit and I've found it doesn't actually provide more features. Your mileage may vary, though.