HexBrain

HackerOne · Report #4000185

HackerOne Code sends live password-reset tokens to Segment in automatic page events

Validstatus
lowseverity
$200bounty
115upvotes
24 Sept 2026disclosed

How it was found

Opening a real HackerOne Code password-reset link automatically sends the complete unused 64-character reset token to Segment as the page loads, before the reset form is submitted. The token appears in context.page.search, context.page.url, properties.search, and properties.url. The current client parses the first query key as the reset credential and later supplies that exact value to the password-reset API, so this is active authentication material rather than an unused route value. I reproduced the issue with four fresh tokens from my researcher-owned account: every Segment request returned HTTP 200, every matching token then reset the account with HTTP 200, the old password returned HTTP 401, and the new password returned HTTP 200. In a returning browser profile, the fresh unused token event had the same anonymousId that Segment had already received with the controlled account email and user ID, and I successfully redeemed that token about 17 seconds later. A queryless /password-reset control still sent a page event, but its search fields were empty and its URL fields contained no token.

Steps To Reproduce

  1. Create or use a HackerOne Code account that you own.
  2. Start browser developer tools or an intercepting proxy in a persistent browser profile. Set X-Bug-Bounty: HackerOne-1rhino2 on all HackerOne Code requests before testing.
  3. Request and complete one password reset in that profile. After the successful reset, record the Segment identify event containing the controlled account email, user ID, and anonymousId.
  4. Request a new password-reset link for the same account.
  5. Open that exact new link in the same browser profile, but do not submit the form yet.
  6. Inspect the automatic Segment page event. The complete unused token appears in all four fields listed above, its anonymousId matches the earlier identify event, and the Segment ingestion endpoint returns HTTP 200.
  7. Enter the account email and a new password, then submit the form.
  8. Confirm that the reset returns HTTP 200, the old password returns HTTP 401, and a login with the new password returns HTTP 200.
  9. As a control, open /password-reset without a query value in a fresh browser profile. The page event is still sent, but its search fields are empty and its URL fields contain no token.

Root Cause And Scope

The in-scope HackerOne Code client loads Segment and calls analytics.page() without first removing the secret-bearing query value. I did not probe Segment or access a Segment dashboard. Segment only received the request automatically generated by the in-scope application.

The attached evidence contains redacted correlation records for all four fresh tokens, the queryless control, the returning-browser identity correlation, current client source excerpts, file hashes, and test metadata. Raw token values, the test email, passwords, cookies, and session values are excluded.

No customer account, customer program, report, or customer data was accessed. All password resets and login checks used one researcher-owned HackerOne Code developer account.

Supporting References

Twilio Segment documents that its Source Debugger Raw view displays the complete event JSON it receives:

https://www.twilio.com/docs/segment/connections/sources/debugger

Segment also documents that source events can be routed to connected destinations:

https://www.twilio.com/docs/segment/guides/filtering-data

The closest public reports I found were HackerOne reports #342693 and #787160, which involved token leakage through Referer headers. This report affects a different asset and mechanism: HackerOne Code inserts the reset token directly into an automatic analytics POST as the page loads.

Impact

Opening a HackerOne Code password-reset link discloses the still-valid reset token to Segment before the user submits the reset form. For a returning browser, the token-bearing event uses the same anonymousId that was already identified with the account email and user ID. Anyone with timely read access to the paired Segment events, or to a downstream destination receiving both events, could join the token to the account and choose a new password while the token remains valid. I am rating this Low because exploitation requires access to that telemetry during the reset token's validity window.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original