DOM XSS via search query parameter rendered with [innerHTML] after bypassSecurityTrustHtml
The URL query parameter `q` is wrapped with `DomSanitizer.bypassSecurityTrustHtml` and bound to `[innerHTML]`, allowing arbitrary HTML/script execution from a crafted link.
In search-result.component.html line 11, the template renders:
<span id="searchValue" [innerHTML]="searchValue"></span>
The searchValue field is populated in search-result.component.ts (filterTable(), lines 132–155) directly from the q query parameter:
let queryParam: string = this.route.snapshot.queryParams.q
if (queryParam) {
queryParam = queryParam.trim()
...
this.searchValue = this.sanitizer.bypassSecurityTrustHtml(queryParam)
}
Because the value is explicitly marked SafeHtml via bypassSecurityTrustHtml, Angular's default HTML sanitization is disabled and [innerHTML] injects the raw attacker-controlled string into the DOM. This is the classic Juice Shop localXssChallenge sink — any HTML/JS payload supplied in ?q= is executed in the victim's browser.
Visit https://<host>/#/search?q=<iframe%20src="javascript:alert(xss)"> (or similar payload). The iframe element is written verbatim into the #searchValue span and the script executes in the victim's session context.
Reflected/DOM XSS: an attacker can craft a link that, when followed by an authenticated user, executes arbitrary JavaScript with the user's privileges (steal JWT/localStorage tokens, perform actions as the user, deface the page). No authentication required to trigger; only victim navigation.
The template at line 11 binds [innerHTML]="searchValue" where searchValue is wrapped by DomSanitizer.bypassSecurityTrustHtml(queryParam) using the raw q query parameter. Bypassing Angular's sanitizer and injecting attacker-controlled HTML into innerHTML is a textbook DOM XSS sink, exploitable by any victim clicking a crafted #/search?q=<payload> link. Per scope rules, Juice Shop's training nature is irrelevant — this is a real reflected/DOM XSS bug.
The q query parameter is passed through DomSanitizer.bypassSecurityTrustHtml and bound to [innerHTML] on the #searchValue span in search-result.component.html line 11, so any crafted URL like /#/search?q=<iframe src="javascript:..."> executes attacker JS in the victim's origin — reachable remotely (AV:N), with no preconditions (AC:L), without authentication (PR:N), but requiring the victim to follow the link (UI:R). Scope is Changed because the XSS executes script in the browser security context of the visiting user, crossing from the web-app component into the user's browser/session authority (token theft from localStorage, actions as the victim). C and I are Low because the attacker gains access to whatever the victim's session exposes (JWT, page DOM, ability to perform user actions) rather than full system data/integrity; availability impact within the app is negligible (A:N).
- CWE-79
- OWASP A03:2021 Injection
- https://angular.io/api/platform-browser/DomSanitizer#bypassSecurityTrustHtml