# Confidential data of users and limited metadata of programs and reports accessible via GraphQL

HackerOne's GraphQL `nodes` connection field bypassed attribute-level authorization, exposing PII of all users and internal metadata of private programs.

- Payout: $20,000
- Severity: critical
- Program: HackerOne
- Found by: yashrs
- Disclosed: 2019-02-03
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/489146
- Library page: https://bugbountylibrary.com/r/h1%3A489146
- Tags: area:web3 domain:api impact:data-leak impact:pii-leak kind:bounty platform:hackerone sev:critical tech:graphql technique:source-review vuln:access-control vuln:info-disclosure

**Target:** GraphQL endpoint (hackerone.com)
**Root cause:** Migration to class-based graphql-ruby added a `nodes` field on every connection that returned an ActiveRecord::Relation instead of scrubbed stale objects; attribute-level authorization instrumentation assumed the parent was already sanitized and skipped scrubbing.
**Steps:**
1. Send GraphQL query `{ users() { nodes { _id email otp_backup_codes account_recovery_phone_number totp_enabled facebook_user_id } } }` to hackerone.com GraphQL endpoint
2. Observe sensitive fields returned for all users, bypassing the authorization applied on the `edges { node }` path
3. Enumerate teams and reports connections via `nodes` to retrieve internal triage notes, policies, and private program metadata
**How found:** Reporter noticed the new `nodes` field on connection types and tested whether it enforced the same attribute-level authorization as `edges { node }`; it did not, returning raw sensitive attributes.
**Exploitation:** Unauthenticated/any user queries the `nodes` field on users, teams, and reports connections; because the returned ActiveRecord::Relation is treated as pre-scrubbed, attribute-level authorization is skipped and confidential fields (emails, OTP backup hashes, recovery phone numbers, internal triage notes, private program policies) are serialized directly.
**Escalation:** Chained across users, teams, and reports connections to widen exposure from per-user PII to internal program metadata and private program policies.
**Insight:** When a GraphQL library upgrade adds convenience fields (e.g. Relay `nodes`) to every connection, test each new field against the authorization path used by the canonical `edges { node }` field — helper fields often bypass per-attribute scrubbing because they return lazy relations instead of materialized objects.

