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 JavaScript single-quoted string breakout. Search input appears in var searchTerms = 'INPUT'; angle brackets are HTML-encoded, but a single quote remains executable JavaScript syntax. The payload closes and reopens the string around an arithmetic expression, producing ''-alert(1)-''.

Lab objective/setup

Open the Academy exercise at the reserved lab URL and work only in that disposable environment. The required proof is specific: The inline script evaluates the expression, fires the alert, and solves the lab.

What I observed

Search input appears in var searchTerms = 'INPUT'; angle brackets are HTML-encoded, but a single quote remains executable JavaScript syntax. The payload closes and reopens the string around an arithmetic expression, producing ''-alert(1)-''.

Academy objective identifies reflected input inside a JavaScript string where angle brackets are encoded and requires breaking out to call alert.
Academy objective identifies reflected input inside a JavaScript string where angle brackets are encoded and requires breaking out to call alert.
Results heading displays a script-tag probe as text, confirming angle brackets do not create markup in this context.
Results heading displays a script-tag probe as text, confirming angle brackets do not create markup in this context.
Results heading displays an inert quote, image, and event-handler probe while the page remains unexecuted, narrowing the context to the JavaScript string.
Results heading displays an inert quote, image, and event-handler probe while the page remains unexecuted, narrowing the context to the JavaScript string.

Why it is vulnerable

The application applies protection for the wrong parser or omits a control at the decisive boundary. In this case, search input appears in var searchTerms = 'INPUT'; angle brackets are HTML-encoded, but a single quote remains executable JavaScript syntax. 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
`'-alert(1)-'`

The payload closes and reopens the string around an arithmetic expression, producing ''-alert(1)-''.

Normal search for `nguyen hoang` provides a clean baseline value for inspecting the generated script.
Normal search for `nguyen hoang` provides a clean baseline value for inspecting the generated script.
Page source places `nguyen hoang` inside `var searchTerms` before passing it to the search-tracking function.
Page source places `nguyen hoang` inside `var searchTerms` before passing it to the search-tracking function.
Browser alert dialog showing `1` after the quote-and-subtraction payload closes the string and evaluates `alert(1)`.
Browser alert dialog showing `1` after the quote-and-subtraction payload closes the string and evaluates `alert(1)`.

Verification

The inline script evaluates the expression, fires the alert, and solves the 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