{"id":4000185,"global_id":"Z2lkOi8vaGFja2Vyb25lL1JlcG9ydC80MDAwMTg1","url":"https://hackerone.com/reports/4000185","title":"HackerOne Code sends live password-reset tokens to Segment in automatic page events","state":"Closed","substate":"resolved","severity_rating":"low","readable_substate":"Resolved","created_at":"2026-09-05T04:29:54.356Z","submitted_at":"2026-09-05T04:29:54.836Z","is_member_of_team?":false,"is_organization_group_member?":false,"is_triager?":false,"reporter":{"disabled":false,"username":"1rhino2","url":"/1rhino2","profile_picture_urls":{"small":"https://profile-photos.hackerone-user-content.com/variants/h1d00k3qx0lgut84ryy9vextnubi/47c72a82657a929c13ab24e11674f7e10ea2bf67b1b9e7116b522cd7ede42f15"},"is_me?":false,"cleared":false,"verified":true,"hackerone_triager":false,"hacker_mediation":false},"team":{"id":13,"url":"https://hackerone.com/security","handle":"security","profile_picture_urls":{"small":"https://profile-photos.hackerone-user-content.com/variants/000/000/013/fa942b9b1cbf4faf37482bf68458e1195aab9c02_original.png/b8e19a7691128fca51630d7f5b14644b91b3b45324f6fd488e36244d744fe35b","medium":"https://profile-photos.hackerone-user-content.com/variants/000/000/013/fa942b9b1cbf4faf37482bf68458e1195aab9c02_original.png/89f037b490baf3dcca1b84283f4c85141b64c213252a9c79b56c62bf903ab542"},"permissions":[],"submission_state":"open","default_currency":"usd","awards_miles":false,"offers_bounties":true,"state":"public_mode","only_cleared_hackers":false,"pentest_feature_enabled?":false,"pentest_retesting_ends_at":null,"profile":{"name":"HackerOne","twitter_handle":"Hacker0x01","website":"https://hackerone.com","about":"Vulnerability disclosure should be safe, transparent, and rewarding."}},"has_bounty?":true,"can_view_team":true,"can_view_report":true,"is_external_bug":false,"is_published":false,"is_participant":false,"has_collaborators":false,"submitted_by_team_member":false,"submitted_with_assistant":true,"stage":4,"public":true,"visibility":"full","cve_ids":[],"singular_disclosure_disabled":true,"disclosed_at":"2026-09-24T11:29:38.033Z","bug_reporter_agreed_on_going_public_at":"2026-09-21T20:40:35.284Z","team_member_agreed_on_going_public_at":"2026-09-24T11:29:37.638Z","comments_closed?":false,"facebook_team?":false,"team_private?":false,"vulnerability_information":"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.\n\n### Steps To Reproduce\n\n1. Create or use a HackerOne Code account that you own.\n2. 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.\n3. 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`.\n4. Request a new password-reset link for the same account.\n5. Open that exact new link in the same browser profile, but do not submit the form yet.\n6. 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.\n7. Enter the account email and a new password, then submit the form.\n8. Confirm that the reset returns HTTP 200, the old password returns HTTP 401, and a login with the new password returns HTTP 200.\n9. 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.\n\n### Root Cause And Scope\n\nThe 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.\n\nThe 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.\n\nNo customer account, customer program, report, or customer data was accessed. All password resets and login checks used one researcher-owned HackerOne Code developer account.\n\n### Supporting References\n\nTwilio Segment documents that its Source Debugger Raw view displays the complete event JSON it receives:\n\nhttps://www.twilio.com/docs/segment/connections/sources/debugger\n\nSegment also documents that source events can be routed to connected destinations:\n\nhttps://www.twilio.com/docs/segment/guides/filtering-data\n\nThe 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.\n\n## Impact\n\nOpening 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.","bounty_amount":"200.0","formatted_bounty":"$200","weakness":{"id":87,"name":"Insufficiently Protected Credentials"},"original_report_id":null,"original_report_url":null,"attachments":[{"id":6636691,"file_name":"HackerOne-Code-Segment-reset-token-attachments.zip","expiring_url":"https://hackerone-us-west-2-production-attachments.s3.us-west-2.amazonaws.com/defm7jm32y2ylhmo0kss8mra3jk8?response-content-disposition=attachment%3B%20filename%3D%22HackerOne-Code-Segment-reset-token-attachments.zip%22%3B%20filename%2A%3DUTF-8%27%27HackerOne-Code-Segment-reset-token-attachments.zip\u0026response-content-type=application%2Fzip\u0026X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=ASIAQGK6FURQ7OQ3MGT5%2F20261008%2Fus-west-2%2Fs3%2Faws4_request\u0026X-Amz-Date=20261008T005220Z\u0026X-Amz-Expires=3600\u0026X-Amz-Security-Token=IQoJb3JpZ2luX2VjEEwaCXVzLXdlc3QtMiJGMEQCIARzV%2BqEbjVTOk2G3s7CLIbym2UhlLivxhOa0dpDSI7jAiASYyOl2MGQIIgmUQTy6KKI71v8pyBxrjCweM3%2BW092miqyBQgUEAMaDDAxMzYxOTI3NDg0OSIMofjCwGKuD53x%2B7lQKo8FumQ4hV7ZRSG2miWB8BP2tGtXNYKNSUDbKC6VyDBdbO9LePJeMbaqm%2B0Q%2FJXFJf56fU6Fo5u2pOK3Ms4uUIPGGwCmF61ZbYcWd%2F5P1k2KF2OATDntX4%2FGfiCM5OagGYaoM7sDbZ48o3C0d2z3Jcg94U3lSqtS2wW6OTaW%2BRVx5kYiJyi0bMUN4LQbJeIphbDddu3jy633sRvjmt21zJy6GS7e7tVzzUyldPQ0W3MQVgoA8JN%2FsxjYMktqO2Bn9W4elOJEZACQJXLNmXhHm%2BZl%2BKWg74ebt%2FZHYCqKL6dwBcjuVIRjtfNAH7%2BO8EWbwfAYsjPOxhMBDy5Xulv6d2C38uG9FYVMPg93cmdoNHERqy6kZEbcgFjisL%2BsopOWKVKRjZjOesMViIwt38zcbfj3p%2FMHt%2BF%2FyFuQQb9HpfK0oVdLor1T8vQWQCsyhk6q7oOLu5eCNc2LO3m%2F5nEIMRho0GkUS88UrFcMROhdzfVKH%2B8TzgYLDF0uWkCJ2BNgnKhyVFSOikvnQcarwzFSaf5GqQS04hVvISe33xHHVCHo%2FL1BUFPvG%2B7Br%2FpQ%2BmwWJBq3ypFbI69Q8yafYs65wE5dHyy18KSD4egtYT3MQJ27GgZWvQPznl7DNS1klm27ZC0h2dlH12WlWfTryYwLtOzNSo3%2F4MSEP%2BsDGQ7QwR3s%2BaEKxR5SK86sCelDNuYdEd2FO6J9u2wF4%2FCxdkyXIJj2dz97YzNI6XonGBjsUMdiUvk%2BUkb944UOeIHpLgYhX8O9sYtukI4XaZD0rdUPGkoy9EjOpsjapB%2Fjqw5QymR%2BwAldnkitYTrEmA8A4aSk00MAE5swq5JLkbVyB0%2FBUjM58qYwW%2BAWLHMTMXAMVWN8nDCwuprWBjqyAS1DgjB6Jtyy8DsktwAcPHF5njYxA%2BXSJZEF5aeshHKf%2F%2BBMtla0yQ6HImS5FhwkhRR0qRnw3oUpXmXEXMRNq3w5ScBJURt3tSjMCCrhjcxi3sbY1ZlCaUmR7mNRY5QunsTV3Buj4U83QR1Y8D9hv3leiCgDZgP37WskaL%2F6CZ7B8aDG%2FbJZlNmaSltFmyaYxsIZcD3ftdhrDlXoCkJoxp5XiBiGlMBHpESYseqJ2%2BwQVIk%3D\u0026X-Amz-SignedHeaders=host\u0026X-Amz-Signature=3b49b192b50716b75ad7cf184cf9daa89a47607e0ad9a117d8743f4ceeed84d0","file_size":4445,"type":"application/zip","moderated":null}],"allow_singular_disclosure_at":null,"vote_count":110,"voters":["inventor0x01","l0da","0xcyborg","secgang","coder_mohammed","senku_","zy9ard3","fa-hacker","jakubk","akrania","and 100 more..."],"severity":{"rating":"low","author_type":"User"},"structured_scope":{"databaseId":130959,"asset_type":"URL","asset_identifier":"app.pullrequest.com","max_severity":"critical"},"abilities":{"assignable_team_members":[],"assignable_team_member_groups":[]},"is_exploit_agent_supported?":false,"is_linear_agent_ui_supported?":false,"summaries":[{"category":"team","can_view?":true,"can_create?":false},{"category":"researcher","can_view?":true,"can_create?":false}]}