# ActionController::Parameters .each returns an unsafe hash

ActionController::Parameters#each returns an unfiltered unsafe hash, letting unpermitted params like is_admin slip past strong-parameter expectations into mass assignment.

- Payout: hidden
- Severity: medium
- Program: Ruby on Rails
- Found by: abuisman
- Disclosed: 2020-05-18
- CVE: CVE-2020-8164
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/292797
- Library page: https://bugbountylibrary.com/r/h1%3A292797
- Tags: area:web domain:web impact:privesc kind:bounty platform:hackerone sev:medium tech:ruby technique:source-review vuln:access-control

**Target:** ActionController::Parameters (actionpack strong_parameters)
**Root cause:** each is delegated to to_unsafe_h internally, returning a plain Hash of all params regardless of permitted state, unlike select which returns a Parameters object with permitted: false.
**Steps:**
1. Create params = ActionController::Parameters.new(city: 'Nijmegen', country: 'Netherlands', language: 'Dutch')
2. Observe params.to_h raises UnfilteredParameters, params.permit(:city).to_h returns only permitted keys
3. Call `params.each {}` and observe it returns the full unfiltered hash including unpermitted keys
4. Compare with `params.select { true }` which returns a Parameters object with permitted: false
**How found:** Noticed inconsistency between to_h (raises on unpermitted) and each (silently returns unsafe hash), then contrasted with select's permitted: false behavior.
**Exploitation:** Attacker adds extra parameters (e.g. `is_admin: true`) to a request; a controller method that iterates params via each and passes the resulting hash to a model update causes mass assignment of the unpermitted attribute, bypassing authorization.
**Insight:** Audit Rails controllers for `.each` on params feeding into model updates or hash construction; each silently bypasses strong-parameter filtering where to_h would raise, so grep for `params.each` in update/create paths.

