Skip to main content  >
Hackerone logo
Hacktivity
Opportunities
Directory
Leaderboard
Learn more about HackerOne
Log in
#3000510
The /reports/:id.json endpoint discloses potentially sensitive user attributes when reporter summary is present
  • Share:
Timeline
avinash_
avinash_
submitted a report to HackerOne.
February 19, 2025, 10:52am UTC
Hi
The.json endpoint of any disclosed report is leaking reporter's email, OTP backup codes, reporter's phone number, "graphql_secret_token", tshirt size all the reporter account's internal details etc.
Code 51 BytesUnwrap lines Copy Download
1 GET /reports/█████.json HTTP/2 2Host: hackerone.com
  • I was checking Hackerone's disclosed report ██████████ and suddenly during check found .json point is leaking too much data of reporter ████ . I immediately reported it to you.
█████
  • PoC:- Leakage of data of reporter
█████ █████

Impact

Reporter H1 account private data disclosed
Show older activities
Avinash Kumar Yadav
avinash_
 posted a comment. 
February 20, 2025, 4:21pm UTC
Anyone listening?
Avinash Kumar Yadav
avinash_
 posted a comment. 
February 21, 2025, 2:59pm UTC
Not want to spam here but this report's severity is Critical, It should be remediated faster. Please check this report soon.
Jobert
Clear-verified badgeHacker that has completed both ID-verification and a background check.
jobert
HackerOne staff
 posted a comment. 
February 21, 2025, 4:45pm UTC
Thanks, we're on it.
Jobert
Clear-verified badgeHacker that has completed both ID-verification and a background check.
jobert
HackerOne staff
 changed the status to Triaged. 
February 21, 2025, 7:36pm UTC
Thanks again, @avinash_, we were able to reproduce the issue.
Jobert
Clear-verified badgeHacker that has completed both ID-verification and a background check.
jobert
HackerOne staff
 changed the status to Retesting
The reporter has been invited to perform a retest for $100. 
Updated February 21, 2025, 7:37pm UTC
We've deployed a fix. Would you mind checking whether you can still reproduce the vulnerability?
alfow
 filed a duplicate (#3005009) and was invited to participate in this report. 
February 21, 2025, 7:37pm UTC
yash_005
 filed a duplicate (#3004950) and was invited to participate in this report. 
February 21, 2025, 7:39pm UTC
cindy0103
 filed a duplicate (#3002335) and was invited to participate in this report. 
February 21, 2025, 7:43pm UTC
Avinash Kumar Yadav
avinash_
 completed a retest. 
Updated February 21, 2025, 8:49pm UTC

Retest finding result

  • Are you able to reproduce the vulnerability report?

    No, the fix works.

  • Please provide a short summary with the results of your retest

    I went to the same report and found the data is no more getting leaked under "summaries" section, in summaries section it is now detaling only few info about team/reporter like name, bio etc which is always in public. This new behaviour is intended and applicable for both Team and reporter. It seems it is fixed.
    ██████████
Avinash Kumar Yadav
avinash_
 posted a comment. 
Updated February 21, 2025, 8:50pm UTC
Hi @jobert - Thank you fo your super duper quick response and fix. The fix is too fast it is really appreciable.
Thank you for redacting sensitive things in report but Please redact the report id: ███ mentoned, it will show other peoples which user's data was leaked and mentioned in this report.
Please also redact the screenshot mentioned in "restest" summary.
Thanks again
HackerOne
 awarded $100 to avinash_ for completing the retest. 
February 21, 2025, 8:49pm UTC
Thanks for confirming the fix!
jobert
HackerOne staff
 closed the report and changed the status to Resolved. 
February 21, 2025, 8:49pm UTC
HackerOne
 rewarded avinash_ with a bounty. 
February 21, 2025, 9:03pm UTC
This was an awesome find, well done! You submitted this vulnerability less than 90 minutes after the change was deployed to production. We will follow up in the next few days with more details about the vulnerability.
jobert
HackerOne staff
 changed the report title from CRITICAL- Leakage of reporter's email, OTP backup codes, password change dates, phone number etc with disclosed report .json endpoint to The /reports/:id.json endpoint discloses potentially sensitive user attributes when reporter summary is present. 
February 21, 2025, 9:04pm UTC
Avinash Kumar Yadav
avinash_
 posted a comment. 
February 21, 2025, 9:07pm UTC
@jobert - Surprised, Thank you so much for this amazing bounty. 😊
jobert
HackerOne staff
 added weakness "Information Disclosure". 
February 21, 2025, 9:11pm UTC
Avinash Kumar Yadav
avinash_
 posted a comment. 
Updated April 1, 2025, 6:09pm UTC
Hi @jobert - I went through some of disclosed reports of H1, I've noticed one thing:- When in a report, there is summary written from team side then on opening .json endpoint of that report it is disclosing which participant from team member has posted the summary. For ex:-
The report:- https://hackerone.com/reports/2598548 , A summary has provided by Hackerone, UI shows it as:- "Summary By Hackerone"
Image F4080488: Screenshot_2025-02-22_at_4.12.48_PM.png 30.57 KiB
Zoom in Zoom out Copy Download
On opening .json endpoint of report, It is disclosing which participant from team side has posted the summary.
████████
Is disclosing this information publicly an intended behaviour?
Thanks!
attachmentsattachments
1 attachment
  • F4080488: Screenshot_2025-02-22_at_4.12.48_PM.png
Jobert
Clear-verified badgeHacker that has completed both ID-verification and a background check.
jobert
HackerOne staff
 posted a comment. 
February 22, 2025, 9:19pm UTC
No, that's intentional. Thanks for checking!
Jobert
Clear-verified badgeHacker that has completed both ID-verification and a background check.
jobert
HackerOne staff
 posted a comment. 
February 26, 2025, 6:35pm UTC
Hey @avinash_, we wanted to provide some context on the root cause of this issue and why it wasn't caught through automated testing.
On February 19, 2025 HackerOne upgraded from Rails 6.1.7.9 to Rails 7.1.5.1. Both versions offer the ability to serialize Ruby hashes into JSON. There is a slight difference between the way this works in both versions. Let’s assume we have the following Ruby hash:
Code 64 BytesUnwrap lines Copy Download
1hash = { 2 my_key: 'my_value', 3 'my_key' => 'my_other_value', 4}
This hash contains two keys with the same name, but one key is a symbol and the other a string. You can access them independently, as such:
Code 67 BytesUnwrap lines Copy Download
1hash[:my_key] 2# => 'my_value' 3 4hash['my_key'] 5# => 'my_other_value'
If to_json is called on this hash in Rails 6.1.7.9, the duplicate key is the one that is used in the JSON output:
Code 45 BytesUnwrap lines Copy Download
1hash.to_json 2# => {"my_key":"my_other_value"}
However, in Rails 7.1.5.1, this behavior changed due to the implementation of the ActiveSupport::JSON.encode method. Here is the output in Rails 7.1.5.1, which shows that the JSON output contains a duplicate key due to the fact that JSON does not distinguish between symbols and strings and ActiveSupport now treats them as unique keys:
Code 65 BytesUnwrap lines Copy Download
1hash.to_json 2# => {"my_key":"my_value","my_key":"my_other_value"}
This resulted in exposing sensitive data on the /reports/:id.json endpoint. Here is an excerpt of the jbuilder template that serializes report summaries:
Code 149 BytesUnwrap lines Copy Download
1json.merge!(summary.json_attributes) 2 3# ... 4 5if summary.persisted? 6 # … 7 json.user do 8 json.partial!('users/user', user: summary.user) 9 end 10end
The summary.json_attributes method was implemented as following:
Code 203 BytesUnwrap lines Copy Download
1class ReportSummary < ApplicationRecord 2 # ... 3 belongs_to :user 4 # ... 5 def json_attributes 6 { 7 id:, 8 category:, 9 content:, 10 updated_at:, 11 user:, 12 } 13 end 14 15 # ... 16end
The json_attributes method returns an instance of a User object with a symbol as its key, called “user”. When merging this into the jbuilder object, it implicitly calls to_json on this object, which serializes all the user attributes. These user attributes contain sensitive information such as email, unverified account recovery phone number, account backup codes, and GraphQL secret token.
When the template is being generated, it eventually calls json.user with a partial. The key that is appended to the hash is a string, not a symbol. In Rails 6.1.7.9, when the final hash would be serialized to a JSON string, it would only retain the key that was added last, which was the sanitized user partial. However, after the upgrade to Rails 7.1.5.1, it would retain both keys and, thus, the final JSON would contain a duplicate key; one with the user attributes and one with the user partial.
At HackerOne we have many automated tests, including tests that verify the JSON structure of this particular endpoint. However, none of these tests failed, which was unexpected. We use the approvals gem to verify JSON structures, often using code that looks similar to this:
Code 38 BytesUnwrap lines Copy Download
1verify(format: :json) { subject.body }
We verified that subject.body after the upgrade did indeed return a duplicate key. The reason why none of the tests failed is because verify parses the JSON again in order to normalize information like IDs, which may change between tests. When parsing JSON in Ruby, only the last instance of a duplicate key is returned:
Code 93 BytesUnwrap lines Copy Download
1JSON.parse('{"my_key":"my_value","my_key":"my_other_value"}') 2=> {"my_key"=>"my_other_value"}
This means that even though the view returned a duplicate key, tests didn’t fail because it would only see the last instance, which was the exact shape of the object prior to the upgrade.
Avinash Kumar Yadav
avinash_
 posted a comment. 
Updated February 28, 2025, 7:58am UTC
Hi @jobert - Sorry for the delay,
Thank you for providing such a great explanation about how and why this issue emerged?, So the villain here was the rails 7.1.5.1 implemented hash key-value pair, As I understood, The main issue is that JSON was not differentiate between symbols and string keys, leading to duplicate keys appearing in the serialized output. This change resulted in exposing sensitive user data at report's .json endpoint.
We use the approvals gem to verify JSON structures, often using code that looks similar to this:
Code 38 BytesUnwrap lines Copy Download
1verify(format: :json) { subject.body }
The approval gem parses json structure and comparing them with previous body here? , which is helping to compare and track if there is more data(sensitive/non-sensitive) is getting disclosed or not? Right?
I've few questions:-
  • Instead of doing single check Can HackerOne add additional checks which inspect raw JSON output here and other json endpoints? or this single "approvals gem" check is sufficient?
  • As you've indicated about to_json, Why HackerOne is not using as_json instead of to_json to avoid unexpected serialization behavior? Since as_json will return a hash before serialization and does not retain duplicate keys. I'm only asking this because I got some information about both calls in this blog: https://jonathanjulian.com/2010/04/rails-to_json-or-as_json/
  • (Optional question): Am I eligible for any swag? 😂
Again Thank you for all of your responses and clarification in this issue.
Regards,
Avinash Kumar Yadav
avinash_
 requested to disclose this report. 
March 11, 2025, 5:53am UTC
Hi @jobert - If everything is Ok then Let's disclose it, Thanks!
l n
jerboa
HackerOne staff
 agreed to disclose this report. 
April 1, 2025, 6:22pm UTC
Hi @avinash_
We've publicly disclosed your report on HackerOne. This aligns with our dedication to transparency and improving overall security. Thank you for your valuable contribution to a safer internet!
 This report has been disclosed. 
April 1, 2025, 6:23pm UTC
HackerOne
 has locked this report. 
April 1, 2025, 7:50pm UTC
Chris
h1_chriszo111
HackerOne staff
 posted a comment. 
April 4, 2025, 9:04am UTC
Hi Avinash, about your swag question: Please check your email inbox. If you don't see anything there, please let me know.
Reported on
February 19, 2025, 10:52am UTC
Reported by
avinash_
avinash_
Reported to
HackerOne
Managed
Participants
avinash_
h1_chriszo111
jerboa
jobert
cindy0103
yash_005
alfow
Report Id
#3000510
Resolved
Severity
Critical (9.2)

Disclosed
April 1, 2025, 6:23pm UTC
Weakness
Information Disclosure
CVE ID
None

Bounty
Hidden 

Account details
None