Developer Hacks Own Rails App Using One Hidden Input
GJ Hewitt, creator of RepBoard, discovered a critical vulnerability in his Ruby on Rails app caused by an overlooked parameter and disabled CSRF protection.

Stock photo for illustration only, not from the actual event
- GJ Hewitt audited his Ruby on Rails app RepBoard and uncovered significant security flaws.
- Devise permitted the reviewable parameter to be updated via forms without explicit UI rendering.
- Disabled CSRF protection in configuration files left the deployed application exposed to attacks.
GJ Hewitt, a software developer building RepBoard—a Ruby on Rails application designed to give freelancers a portable reputation profile—shared his security audit experience on Dev.to. The application features freelancers with public profiles and clients who log in to leave reviews, with the distinction between the two roles managed by a single boolean column on the users table named reviewable.
For authentication, he utilized Devise and configured application_controller.rb to permit account_update parameters including display_name, reviewable, bio, slug, and avatar_url. The security oversight lay in the fact that permitting a parameter has no relation to whether it is displayed on a form; Rails accepts whatever arrives in the request. By signing in as a client, opening account settings, using devtools to insert a hidden input field user[reviewable] with a value of 1, and submitting with their own password, a client could instantly elevate their privileges to become a freelancer.

Stock photo for illustration only, not from the actual event
The fix took roughly ten seconds by removing reviewable from the permitted list in devise_parameter_sanitizer. Hewitt noted that the parameter list functions more like a guest list at a door, admitting anyone named on it. Furthermore, an audit of review creation revealed that while it checked if the author was a client, it never verified if the recipient was a freelancer, allowing clients to review other clients or themselves simply by editing a hidden form field.
This case highlights the fundamental distinction between validation and authorization in software architecture. Validation asks whether a record is valid based on data rules—such as requiring reviewers to be clients and reviewees to be freelancers—which belong in the model to enforce constraints globally across console sessions, rake tasks, and controllers. In contrast, service objects only protect the specific execution path routed through them, making proper model-level validations essential for preventing logic vulnerabilities.
When he added model validations and ran rake sample_data to reload his development database, the application crashed immediately because his seed file generated data that violated these newly enforced rules, such as freelancers reviewing freelancers fifty times over. This demonstrated that test fixtures must accurately reflect application constraints, or one of them is misrepresenting the system.
Upon investigating a configuration file inherited from his starter template at config/initializers/appdev_rails_settings.rb, he discovered that Rails.application.config.action_controller.default_protect_from_forgery was set to false. While acceptable in course sandboxes, leaving cross-site request forgery protection turned off on a deployed production app—combined with the privilege escalation vulnerability—meant a malicious page could alter a logged-in user's account type without any user interaction.
Hewitt concluded that a passing security scan only means a scanner found nothing, not that vulnerabilities do not exist. He advised developers utilizing bootcamp or course starter templates to thoroughly inspect their configuration initializers on day one rather than treating configuration directories as static furniture.
Source: Dev.to
Found something wrong in this article? Report an issue with this article
Comments
Leave a Comment