Test what you understood — not what you memorized.
QUESTION 01 OF 05
In the 2012 GitHub breach, Egor Homakov added public_key[user_id]=4223 to his HTTP request. What made this exploit possible?
Correct — Rails' update_attributes(params[:public_key]) bound every incoming parameter to the model. There was no permit list restricting which fields could be written. Homakov added user_id to the form data, and Rails silently wrote it to the database, associating his SSH key with the Rails organization.
Not quite — Homakov was authenticated as himself the whole time. He didn't need admin credentials, SQL injection, or an unauthenticated endpoint. He exploited Rails' mass assignment feature: the API accepted and wrote any field he sent — including user_id, which should have been server-side only.
QUESTION 02 OF 05
What was wrong with Peloton's "private account" feature before it was fixed?
Correct — this is the core excessive data exposure failure. The frontend UI respected the privacy setting and hid sensitive fields. But the API returned the complete user object to anyone who called it directly. Bypassing the UI — by calling the API with an HTTP client — exposed all the "hidden" data.
Not quite — the problem wasn't cross-platform or a mass assignment on the privacy field. It was simpler and more fundamental: the API returned the full user object (including private fields) to any caller, regardless of the account's privacy setting. The setting only affected the UI display, not the API response.
QUESTION 03 OF 05
A developer adds a "resetToken" field to the user database model and the user serializer returns all model fields by default. What's the risk?
Correct — if the API returns an active password reset token in the user object, any attacker who can read that response can immediately take over the account. They use the leaked token to complete a password reset without ever requesting one. No email is sent. No notification is triggered. This is why internal tokens must never appear in API responses.
Not quite — the danger is on the read side. If the resetToken appears in the API response, anyone who can call the profile endpoint gets it. They can then complete a password reset without requesting one — silently, with no alert to the account owner. The fix: never include resetToken in any user-facing API response.
QUESTION 04 OF 05
Why is an allowlist safer than a blocklist for protecting against mass assignment?
Correct — this is the fundamental security principle of default-deny. An allowlist fails safe: if you forget to add a new field to the list, it's blocked. A blocklist fails open: if you forget to add a new sensitive field to the block list, it's accepted. Over time, as models grow, blocklists inevitably miss something.
Not quite — the key difference is the failure mode. With a blocklist, the default is "allow" — forgetting to block a new sensitive field means it's exposed. With an allowlist, the default is "deny" — forgetting to allow a new field means it's blocked. In security, failing safe (deny by default) is always preferred over failing open.
QUESTION 05 OF 05
In the OWASP dating app scenario, a user can get another user's fullName and recentLocation by using the "report user" feature. What type of failure is this?
Correct — the attacker is authenticated and calling an intended endpoint (report user). The problem isn't who they're calling it about (that's BOLA) or whether they're logged in (that's auth). The problem is what the endpoint returns: fullName and recentLocation are properties the reporting user should never be able to read. That's excessive data exposure — a property-level read failure.
Not quite — the attacker isn't writing anything (not mass assignment), isn't pretending to be someone else (not broken auth), and the object access itself may be legitimate (the report endpoint is designed to be called about any user). The failure is what's in the response: sensitive properties that shouldn't be returned to this caller. That's excessive data exposure — API3's read-side vulnerability.