How a Hacker Became a GitHub Org Owner with One Request
In 2012, a security researcher named Egor Homakov discovered a critical vulnerability in GitHub — one of the most important code hosting platforms in the world. He was able to add his SSH key to any GitHub repository, including Ruby on Rails' own repository, without authorization.
The vulnerability was mass assignment. GitHub's Rails application used a feature called attr_accessible to control which model attributes could be set via user input. The problem: the developers hadn't properly configured it on certain models. Homakov sent a carefully crafted request that included hidden fields — fields the app never intended users to set — and Rails dutifully saved them to the database.
POST /github/repos/rails/rails/keys Content-Type: application/x-www-form-urlencoded # Normal: add your key to YOUR repo public_key[key]=ssh-rsa+AAAA... # Exploit: add your key to the RAILS repo by including the repo owner field public_key[key]=ssh-rsa+AAAA...&public_key[user_id]=4223
user_id field was never meant to be user-controlled — but the Rails model blindly accepted all parameters in the request body.GitHub suspended Homakov's account (then apologized and reinstated it). Rails shipped a fix. The vulnerability became one of the most famous examples of mass assignment in modern web security.
What is mass assignment?
Mass assignment happens when a web framework automatically maps all fields in an HTTP request body directly to a database model or object — without filtering which fields should be user-controllable.
// ✅ SAFE — explicit allowlist
const { username, email } = req.body;
user.username = username;
user.email = email;
// ❌ VULNERABLE — spread entire body
Object.assign(user, req.body); // Node.js
User.update(params) // Rails (without strong params)
user.__dict__.update(request.json()) // Python/Flask
What is the root cause of mass assignment vulnerabilities?