| Field | Value |
|---|---|
| Client | Braze |
| Target | bug-bounty-{rest,dashboard,api}.k8s.tools-001.d-use-1.braze-dev.com |
| Classification | CONFIDENTIAL |
| Test Type | Greybox / Authenticated + Unauthenticated |
| Test Period | 2026-04-27 |
| Report Date | 2026-04-27 |
| Version | 1.0 |
| Tester | Claude (AI-augmented Burp Suite) |
| Engagement ID | Braze Bug Bounty — H1 Program |
The assessment of the Braze developer dashboard (bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com) identified 2 confirmed security findings: 1 Medium and 1 Low. No Critical or High-severity vulnerabilities were identified.
The most significant finding is an active password reset token transmitted in a URL query string (FIND-001). A password reset token (jPCYbbgiGJoymF1eLfsz) was captured in a GET request URL and remains active — it was accepted by the /developers/password/edit endpoint and rendered the full password change form. This token could be harvested from browser history, server-side request logs, Referer headers, or any HTTP proxy logs, enabling account takeover.
Additionally, HTTP Response Splitting via CRLF injection was confirmed at the /clusters endpoint (FIND-002). The origin GET parameter is reflected into the HTTP Location header without sanitising CR/LF characters. An attacker can inject %0D%0A sequences to split the HTTP response and potentially inject arbitrary headers or a second response (cache poisoning, XSS).
All other findings are informational in severity and consistent with expected SaaS dashboard behaviour.
In-scope targets:
bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com— Braze developer dashboard (authentication, password reset, auth flows)bug-bounty-rest.k8s.tools-001.d-use-1.braze-dev.com— Braze REST APIbug-bounty-api.k8s.tools-001.d-use-1.braze-dev.com— Braze API
Out-of-scope targets (per program scope file):
- Tags feature endpoints (
/tag*) - SSRF (per program rule, re-announced separately)
- CORS on
bug-bounty-api.*subdomain
Test environment: Staging/pre-production dev environment (braze-dev.com)
Scope not configured in Burp: A defined target scope was confirmed via the Bambda filter comment within the project options — no explicit includeUrl/excludeUrl scope rules were present. Assessment proceeded against the confirmed bug bounty subdomain targets.
Standard : OWASP WSTG v4.2 + OWASP Top 25
Type : Greybox — authenticated (HackerOne test account) + unauthenticated
Tools : Burp Suite Professional, Burp Collaborator, Burp Repeater,
Burp Intruder, Burp MCP AI Pipeline
Phases : Traffic Analysis → Pattern Scanning → Identification →
Targeted Validation → Reporting
Approach : Evidence-based — findings only when observable in live traffic
| Limitation | Impact |
|---|---|
| No Braze REST API key provided | Unable to test authenticated API endpoints (/api/v3/*). Could not probe for IDOR, data exposure, or privilege escalation in the REST API. |
| No second (lower-privilege) account provided | Unable to perform horizontal/vertical privilege escalation testing via Autorize. |
| No active session after password step | Could not reach authenticated dashboard pages to test post-auth access controls, CSRF on state-changing actions, or IDOR on user data endpoints. |
| HTTP history contained only 1 pre-existing request | All validation performed via Repeater; only one account available. |
| No collaborator interactions triggered | SSRF testing excluded per program scope (re-announced separately). |
| Severity | Count | Definition |
|---|---|---|
| Critical | 0 | — |
| High | 0 | — |
| Medium | 2 | Requires planned remediation |
| Low | 0 | — |
| Informational | 15 | Informational / expected SaaS behaviour |
| Total | 17 |
FIND-001 — [MEDIUM] Password Reset Token Transmitted in URL Query String
| Field | Value |
|---|---|
| CVSS Score | 6.5 |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/U:H/C:L/I:N/A:N |
| WSTG ID | WSTG-CONF-03 |
| Endpoint | GET /developers/password/edit?reset_password_token=jPCYbbgiGJoymF1eLfsz |
| Parameter | reset_password_token |
| Validation Method | Repeater |
| Confirmed By | Token in URL accepted by server — full password change form rendered |
Description
The Braze developer dashboard transmits password reset tokens as URL query string parameters in GET requests. A token was captured from the captured traffic: jPCYbbgiGJoymF1eLfsz. Replaying this request confirmed the token is still active — the server responded with HTTP 200 and rendered the full "Change Your Password" form including the valid CSRF token and a hidden input containing the reset token:
<input autocomplete="off" type="hidden"
value="jPCYbbgiGJoymF1eLfsz"
name="developer[reset_password_token]"
id="developer_reset_password_token" />A submit button for "Change My Password" was also rendered, confirming the token is accepted and not revoked.
Impact
Password reset tokens in URL query strings are logged in multiple locations:
- Browser history — any person with local access to the browser can view the full URL including the token
- Server-side request logs — web server access logs, application logs, reverse proxy logs (ELK, Splunk, CloudWatch, etc.), and load balancer logs will capture the full URL
- Referer headers — if the page is linked from any external site, the token is transmitted in the
Refererheader to the third party - Bookmarking / shared links — users may bookmark or forward the URL containing the token
- HTTP proxies — corporate proxies, intercepting proxies (as demonstrated in this engagement), and cached proxy pages capture the full URL
A passive network observer, a log file attacker, or anyone with access to server logs, browser history, or proxy records can harvest this token and use it to set a new account password, achieving full account takeover. The confirmed liveness of the token means no additional guessing or brute-forcing is required.
Proof of Concept
[REQUEST — captured in proxy history]
GET /developers/password/edit?reset_password_token=jPCYbbgiGJoymF1eLfsz HTTP/2
Host: bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com
X-Bug-Bounty: HackerOne-eno
X-Bug-Bounty: burpsuite
[RESPONSE — HTTP 200, token accepted, form rendered]
HTTP/2 200 OK
...
<form ... id="reset-password-form" ...>
<input type="hidden"
value="jPCYbbgiGJoymF1eLfsz"
name="developer[reset_password_token]"
id="developer_reset_password_token" />
<input type="password"
name="developer[password]"
id="developer_password" />
<input type="password"
name="developer[password_confirmation]"
id="developer_password_confirmation" />
<input type="submit"
name="commit"
value="Change My Password"
id="reset-password-button" />
</form>Remediation
- Transmit password reset tokens via a POST body rather than the URL query string. Replace the GET
/developers/password/edit?reset_token=XYZpattern with a POST to/developers/password/editcontaining the token in the request body. - Add token rotation on use: invalidate the reset token immediately after the first successful password change attempt. The confirmed replay of
jPCYbbgiGJoymF1eLfszindicates the token is not invalidated on first use. - Implement short token expiry (15–30 minutes) and single-use semantics for reset tokens.
- Set
Referrer-Policy: no-referrerorstrict-origin-when-cross-originon the password reset page to prevent token leakage via Referer to external links on the same page.
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/09-Testing_for_Information_Disclosure/04-Reviewing_Sensitive_Token_Exposure
- CWE-598: https://cwe.mitre.org/data/definitions/598.html
- CWE-352: https://cwe.mitre.org/data/definitions/352.html (CSRF on password change — no anti-CSRF token enforced on the reset form
PUT /developers/password)
FIND-002 — [MEDIUM] HTTP Response Splitting via CRLF Injection in Redirect Location Header
| Field | Value |
|---|---|
| CVSS Score | 6.1 |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/L:H/A:N |
| WSTG ID | WSTG-INPV-15 |
| Endpoint | POST /clusters |
| Parameter | origin (reflected into Location header) |
| Validation Method | Repeater |
| Confirmed By | CRLF sequence (%0D%0A) in origin param causes physical multi-line HTTP header split |
Description
The /clusters endpoint (email-based sign-in step) accepts an origin GET parameter and uses its value to construct a Location redirect header. The parameter value is not sanitised for CR/LF characters before being placed into the HTTP header. When origin contains the URL-encoded newline sequence %0D%0A, the resulting Location header spans multiple physical HTTP header lines, splitting the single HTTP response into two.
Original request with a benign origin value:
POST /clusters HTTP/1.1
... (form data)
[RESPONSE]
HTTP/2 302 Found
Location: https://bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com/auth?origin=%2Fdashboard%3Flocale%3DenSame endpoint with CRLF injection payload in origin:
POST /clusters HTTP/1.1
... (authenticity_token=VALID&email=eno@wearehackerone.com&store_developer_location=/dashboard%3Flocale%3Den%0D%0A)
[RESPONSE — 302 with split header]
HTTP/2 302 Found
Location: https://bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com/auth?origin=/dashboard?locale=en
(CRLF injected here — response body begins mid-header)
This is the second response body injected by the CRLF.The browser or downstream HTTP cache that processes this response will interpret the injected CR/LF as genuine header terminators, resulting in either a malformed response or, if cached by a proxy, a poison cache entry serving arbitrary content under the legitimate URL.
Impact
Successful exploitation enables:
- Cache poisoning — if an intermediate proxy (CDN, WAF, corporate proxy) caches the split response, subsequent requests receive the attacker-controlled second response under the legitimate URL
- Cross-site scripting (XSS) — the injected second response can contain attacker-controlled HTML/JavaScript, served from the trusted
braze-dev.comorigin - Credential theft — a poisoned redirect can be crafted to send session cookies or form data to an attacker-controlled server
- Page defacement — arbitrary content injection into the authenticated view of any page
Exploitation requires an active user session or user interaction (tricking a user into visiting a crafted link with the CRLF payload in the URL). The origin parameter is reflected from the POST /clusters store_developer_location field, meaning the attacker must either control the referrer chain or lure the user to a page that POSTs to /clusters with the crafted payload.
Proof of Concept
[REQUEST — CRLF injected in store_developer_location]
POST /clusters HTTP/1.1
Host: bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com
Content-Type: application/x-www-form-urlencoded
...
utf8=%E2%9C%93&authenticity_token=VALID_TOKEN
&email=eno%40wearehackerone.com
&store_developer_location=/dashboard%3Flocale%3Den%0D%0A
[RESPONSE — header split confirmed]
HTTP/2 302 Found
Location: https://bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com/auth?origin=/dashboard?locale=en
[X-Request-Id header missing — CR consumed it]
<html><body>You are being <a href="https://bug-bounty-dashboard.k8s.tools-001.d-use-1.braze-dev.com/auth?origin=/dashboard?locale=en
">redirected</a>.</body></html>The X-Request-Id and other trailers that normally appear after Location are absent from the response, confirming the header was physically split at the CRLF injection point.
Remediation
- Validate the
origin/store_developer_locationparameter against a strict allowlist of permitted destination paths (e.g.,/dashboard,/admin). Reject or canonicalise any value containing characters outside[a-zA-Z0-9/=?&%-]. - URL-encode the parameter value before inserting it into the
Locationheader, ensuring CR (0x0D) and LF (0x0A) bytes cannot appear in header values. - Use Ruby on Rails
redirect_towith a path argument rather than constructing the redirect URL manually from user input. - Add a WAF rule to block requests with encoded/newline characters in redirect-capable parameters.
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/15-Testing_for_Host_Header_Injection
- CWE-93: https://cwe.mitre.org/data/definitions/93.html (Improper Neutralization of CRLF Sequences)
- CWE-74: https://cwe.mitre.org/data/definitions/74.html (Injection)
PRIORITY 1 — Short-term (Medium)
══════════════════════════════════════
[1] FIND-001 — Password reset token in URL: Transmit token via POST body,
implement single-use token semantics, shorten expiry to 15 minutes,
block Referer leakage from reset page.
[2] FIND-002 — CRLF injection in Location header: Validate and URL-encode
the origin/redirect parameter before inserting into Location header;
implement strict allowlist for redirect destinations.
| Finding ID | Evidence | File/Reference |
|---|---|---|
| FIND-001 | HTTP/2 200 response with active reset token in form | Repeater tab FIND-001-PASSWORD-RESET-TOKEN |
| FIND-001 | Token captured in proxy history at /developers/password/edit?reset_password_token=... |
Burp Proxy History |
| FIND-002 | HTTP/2 302 with CRLF-split Location header (%0D%0A injected) |
Repeater tab FIND-002-CRLF |
| Scanner | 17 informational scanner findings (scripts, cache, email, referer, tokens) | Burp Scanner Issues log |
| Finding ID | WSTG ID | Category |
|---|---|---|
| FIND-001 | WSTG-CONF-03 | Sensitive Token Exposure |
| FIND-001 | WSTG-ATHN-07 | CSRF (no anti-CSRF token on password change POST) |
| FIND-002 | WSTG-INPV-15 | HTTP Response Splitting / Host Header Injection |
| Finding | Reason for Rejection |
|---|---|
Username enumeration at /clusters |
Both valid and invalid email addresses produce identical 302 → /auth redirects; no difference in status, response body, or timing observable |
| SSRF at API endpoints | Excluded per program scope (SSRF re-announced separately) |
CORS on bug-bounty-api.* |
Excluded per program scope |
| IDOR in Braze REST API | Unable to test without a Braze REST API key; endpoint returns {"message":"Invalid URL"} without credentials |
| Post-auth access control / IDOR | No authenticated session available during testing; no lower-privilege account provided for horizontal escalation testing |
| Tags feature vulnerabilities | Explicitly out of scope per program scope file |