Authorization disclaimer. This walkthrough is limited to the intentionally vulnerable PortSwigger Web Security Academy lab linked below. Test only systems you own or are explicitly authorized to assess.

Overview

This lab isolates Custom-element focus event bypass. The search response is HTML context behind a filter that rejects standard tags but accepts unknown custom elements and global attributes. tabindex makes the custom element focusable and fragment #x focuses it when the exploit-server redirect reaches the page.

Lab objective/setup

Open the Academy exercise at the reserved lab URL and work only in that disposable environment. The required proof is specific: Automatic focus runs onfocus, displays the cookie, and solves the victim-delivery lab.

What I observed

The search response is HTML context behind a filter that rejects standard tags but accepts unknown custom elements and global attributes. tabindex makes the custom element focusable and fragment #x focuses it when the exploit-server redirect reaches the page.

Academy objective states that all standard HTML tags are blocked but custom elements remain available, with automatic access to `document.cookie` required.
Academy objective states that all standard HTML tags are blocked but custom elements remain available, with automatic access to `document.cookie` required.
Burp Intruder tag enumeration shows the custom name `xss` returning status 200 while standard tags are rejected.
Burp Intruder tag enumeration shows the custom name `xss` returning status 200 while standard tags are rejected.

Why it is vulnerable

The application applies protection for the wrong parser or omits a control at the decisive boundary. In this case, the search response is HTML context behind a filter that rejects standard tags but accepts unknown custom elements and global attributes. Browser parsing therefore preserves the attacker-controlled behavior instead of reducing the value to inert text or a safe URL.

Walkthrough in the authorized PortSwigger lab

First reproduce the recorded page or request and inspect the exact reflected, stored, or DOM-generated context described above. Then supply the following lab payload as data, not as active markup in this article:

1
`<xss id=x onfocus=alert(document.cookie) tabindex=1></xss>`

tabindex makes the custom element focusable and fragment #x focuses it when the exploit-server redirect reaches the page.

Developer Tools shows the reflected custom `xss` element with id `x`, `tabindex=1`, and an `onfocus` handler containing the inert alert expression.
Developer Tools shows the reflected custom `xss` element with id `x`, `tabindex=1`, and an `onfocus` handler containing the inert alert expression.
Solved Academy banner confirms navigation to fragment `#x` focused the custom element and triggered its handler.
Solved Academy banner confirms navigation to fragment `#x` focused the custom element and triggered its handler.

Verification

Automatic focus runs onfocus, displays the cookie, and solves the victim-delivery lab. This distinguishes execution from a payload merely appearing in source or being stored without reaching the required event or sink.

Impact and defensive lesson

In a real application, equivalent XSS could act with the victim’s same-origin privileges, expose readable data, or perform authenticated actions. Fix the data flow at its context: use text-only DOM APIs, JavaScript- or attribute-aware encoding, strict URL-scheme allowlists, and maintained sanitization where HTML is unavoidable. HttpOnly cookies and a restrictive CSP reduce consequences but do not repair the injection flaw.

References