Reflected XSS via bypassSecurityTrustHtml on order tracking result
Order-tracking result interpolates the untrusted `orderId` value into an HTML string and pushes it through `bypassSecurityTrustHtml`, which the template then renders via `[innerHtml]`, enabling arbitrary script execution.
In frontend/src/app/track-result/track-result.component.ts line 48:
this.orderId = this.route.snapshot.queryParams.id
this.trackOrderService.find(this.orderId).subscribe((results) => {
this.results.orderNo = this.sanitizer.bypassSecurityTrustHtml(`<code>${results.data[0].orderId}</code>`)
...
})
The sink (bypassSecurityTrustHtml) is bound to the page in track-result.component.html line 9:
<h1><span translate>TITLE_SEARCH_RESULTS</span> - <span [innerHtml]="results.orderNo"></span></h1>
results.data[0].orderId originates from the response of GET /rest/track-order/<id>, where <id> is user-controlled via the ?id= query parameter (this.orderId = this.route.snapshot.queryParams.id). Angular’s bypassSecurityTrustHtml explicitly disables sanitization, so the interpolated value is rendered as raw HTML. No DOMPurify/sanitize-html is applied. An attacker can craft a URL whose id parameter (or whose stored order record’s orderId field) contains markup such as <img src=x onerror=alert(document.cookie)> and the payload will execute in the victim’s browser when they visit the resulting track-result page.
This matches the brief’s Angular [innerHTML] / bypassSecurityTrustHtml true-positive pattern: an bypassSecurityTrust* sink fed an untrusted, interpolated string with no sanitizer in between.
- Submit a feedback/order with an
orderIdcontaining HTML, or otherwise control theidquery parameter / response payload. For the simplest stored case: have any field returned asresults.data[0].orderIdcontain<img src=x onerror=alert(1)>. - Send the victim to:
https://<host>/#/track-result?id=<crafted-orderId>(or any URL that causes the back-end to return an order whoseorderIdcontains the payload). - The component executes
bypassSecurityTrustHtml('<code><img src=x onerror=alert(1)></code>')and the template renders it via[innerHtml], triggering script execution in the victim's session.
Cross-site scripting on an authenticated route. An attacker who can influence the orderId value returned by /rest/track-order/<id> (or convince a victim to follow a crafted track-result URL) gains arbitrary JavaScript execution in the victim’s browser, allowing session-token theft from localStorage/cookies, account takeover, CSRF-style actions on behalf of the user, or further client-side exploitation. No authentication required for the attacker to host/share the link; the victim need only follow it.
Line 48 calls this.sanitizer.bypassSecurityTrustHtml(\<code>${results.data[0].orderId}</code>\) and the template binds it via [innerHtml]. The orderId originates from this.route.snapshot.queryParams.id, which the Juice Shop track-order backend echoes back in results.data[0].orderId, so an attacker can craft a URL like /#/track-result?id=<img src=x onerror=alert(1)> to achieve reflected XSS. bypassSecurityTrustHtml explicitly disables Angular's sanitization, and no DOMPurify or equivalent is applied, making the exploit chain reachable from untrusted input.
The sink at line 48 (bypassSecurityTrustHtml(<code>${results.data[0].orderId}</code>)) is fed from this.route.snapshot.queryParams.id with no auth gate on reaching the route, so any attacker can craft a ?id= URL and share it (AV:N, PR:N, AC:L). Exploitation requires the victim to click the crafted link, so UI:R. Per CVSS 3.1 guidance, XSS that executes script in the victim's browser typically crosses the security authority from the vulnerable web app component into the user's browser/session, hence Scope:C, with C:L/I:L (attacker can steal session tokens from localStorage/cookies and perform actions as the user, but impact is bounded by what that user can do in the browser) and A:N (no availability impact).
- CWE-79: Improper Neutralization of Input During Web Page Generation
- OWASP A03:2021 Injection (XSS)
- https://angular.io/guide/security#bypass-security-apis