{"id":3888,"date":"2026-09-01T16:34:43","date_gmt":"2026-09-01T16:34:43","guid":{"rendered":"https:\/\/hackagora.com\/?p=3888"},"modified":"2026-09-15T11:19:37","modified_gmt":"2026-09-15T11:19:37","slug":"xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices","status":"publish","type":"post","link":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/","title":{"rendered":"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices"},"content":{"rendered":"\n<figure class=\"wp-block-image alignright size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/09\/xss-en.svg\" alt=\"XSS (Cross-Site Scripting) Vulnerabilities: Types of Attacks, Exploitations and Security Best Practices\" class=\"wp-image-3889\" style=\"width:346px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">XSS (Cross-Site Scripting) vulnerabilities are among the longest-standing vulnerabilities in web applications. Depending on the context, an XSS vulnerability can lead to session hijacking, credential theft, account takeover, the exposure of sensitive data, or even the compromise of administration interfaces.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this article, we outline the principles and mechanics of XSS vulnerabilities. We also detail the different types of XSS attacks, injection contexts, DOM-specific mechanisms, exploitation scenarios, and a research methodology that can be used during a penetration test. Finally, we present prevention mechanisms and a defence-in-depth approach to prevent XSS vulnerabilities.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comprehensive Guide to XSS (Cross-Site Scripting) Vulnerabilities<\/h2>\n\n\n<div class=\"wp-block-aioseo-table-of-contents\"><ul><li><a class=\"aioseo-toc-item\" href=\"#what-is-an-xss-cross-site-scripting-vulnerability\">What is an XSS (Cross-Site Scripting) Vulnerability?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#how-does-an-xss-work\">How Does an XSS Work?<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#verifiable-data-interpretation-and-output-context\">Verifiable data, interpretation and output context<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#role-of-the-browser-and-the-origin\">Role of the browser and the origin<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#understanding-xss-injection-contexts\">Understanding XSS Injection Contexts<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#injection-into-html-content\">Injection into HTML content<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#injection-into-an-html-attribute\">Injection into an HTML attribute<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#dangerous-attributes-and-separation-between-data-and-code\">Dangerous attributes and separation between data and code<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#injection-into-a-javascript-string\">Injection into a JavaScript string<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#single-and-double-quotes-and-template-literals\">Single and double quotes, and template literals<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#json-data-embedded-in-a-page\">JSON data embedded in a page<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#url-injection\">URL injection<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#injection-in-a-css-context\">Injection in a CSS context<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#svg-mathml-and-rich-html-content\">SVG, MathML and rich HTML content<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#injections-across-several-successive-contexts\">Injections across several successive contexts<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#what-are-the-different-types-of-xss-attacks\">What are the Different Types of XSS Attacks?<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#reflected-xss-attacks\">Reflected XSS attacks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#stored-xss-attacks\">Stored XSS attacks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#dom-based-xss-attacks\">DOM-Based XSS attacks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#blind-xss-attacks\">Blind XSS attacks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#self-xss\">Self-XSS<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#dom-based-xss-understanding-sources-and-sinks\">DOM-Based XSS: Understanding Sources and Sinks<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#verifiable-sources\">Verifiable sources<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#dangerous-html-sinks\">Dangerous HTML sinks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#sinks-that-execute-or-generate-code\">Sinks that execute or generate code<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#trace-the-flow-between-the-source-and-the-sink\">Trace the flow between the source and the sink<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#postmessage-and-cross-origin-trust\">postMessage and cross-origin trust<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#multiple-decodings-and-successive-representations\">Multiple decodings and successive representations<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#dom-clobbering-and-exploitation-chains\">DOM clobbering and exploitation chains<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#mutation-xss-and-the-complexity-of-html-parsing\">Mutation XSS and the complexity of HTML parsing<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#why-html-sanitisation-is-complex\">Why HTML sanitisation is complex<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#mxss-when-the-dom-changes-after-sanitisation\">mXSS: when the DOM changes after sanitisation<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#how-do-attackers-exploit-xss-vulnerabilities\">How Do Attackers Exploit XSS Vulnerabilities?<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#acting-within-the-victims-authenticated-session\">Act within the victim\u2019s authenticated session<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#compromising-an-administration-interface\">Compromise an administration interface<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#theft-of-client-side-data\">Theft of client-side data<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#phishing-with-a-legitimate-source\">Phishing with a legitimate source<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#keylogging-and-monitoring-of-interactions\">Keylogging and monitoring of interactions<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#xss-and-csrf-protection\">XSS and CSRF protection<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#xss-and-jwt-tokens\">XSS and JWT tokens<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#chaining-xss-with-other-vulnerabilities\">Chaining XSS with other vulnerabilities<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#methodology-for-detecting-xss-vulnerabilities-during-a-penetration-test\">Methodology for Detecting XSS Vulnerabilities During a Penetration Test<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#mapping-controllable-inputs\">Mapping controllable inputs<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#use-unique-markers\">Use unique markers<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#compare-the-http-response-and-the-final-dom\">Compare the HTTP response and the final DOM<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#identify-the-context-precisely\">Identify the context precisely<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#observe-the-changes\">Observe the changes<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#build-minimal-evidence-appropriate-to-the-context\">Build minimal evidence appropriate to the context<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#how-to-prevent-xss-vulnerabilities\">How To Prevent XSS Vulnerabilities?<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#encode-at-the-time-of-output-and-according-to-the-context\">Encode at the time of output and according to the context<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#prioritise-safe-sinks\">Prioritise safe sinks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#sanitise-when-html-actually-needs-to-be-accepted\">Sanitise when HTML actually needs to be accepted<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#validate-inputs-when-the-format-is-known\">Validate inputs when the format is known<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#avoid-payload-blocklists\">Avoid payload blocklists<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#retain-your-frameworks-automatic-safeguards\">Retain frameworks&#039; automatic safeguards<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#content-security-policy-as-a-defence-in-depth-strategy\">Content Security Policy as a defence-in-depth strategy<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#trusted-types-to-reduce-dom-xss\">Trusted Types to reduce DOM XSS<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#httponly-and-minimising-the-impact\">HttpOnly and minimising the impact<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#samesite-and-actual-scope-of-protection\">SameSite and actual scope of protection<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#isolate-sensitive-interfaces-and-sources\">Isolate sensitive interfaces and sources<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#maintain-rendering-and-sanitisation-libraries\">Maintain rendering and sanitisation libraries<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#conclusion\">Conclusion<\/a><\/li><\/ul><\/div>\n\n\n<h2 id=\"what-is-an-xss-cross-site-scripting-vulnerability\" class=\"wp-block-heading\">What is an XSS (Cross-Site Scripting) Vulnerability?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">An XSS is a client-side injection vulnerability in which data controllable by an attacker is interpreted by the browser as active content, when it should have remained mere data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unlike an <a href=\"https:\/\/hackagora.com\/en\/sql-injection-sqli-types-exploitation-and-security-best-practices\/\" target=\"_blank\" rel=\"noopener\">SQL injection<\/a>, which generally aims to alter the query sent to a database engine, XSS primarily targets the browser. The browser is, however, a particularly sensitive environment: it hosts the application interface, the displayed data, session mechanisms and part of the logic used to interact with the backend.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When an injected script runs on the vulnerable application\u2019s origin, it is subject to the same browser security rules as the legitimate JavaScript from that origin. Depending on the architecture, it can therefore read the DOM, access available JavaScript data, interact with certain client-side storage mechanisms and send requests to resources accessible from that session.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A classic example is as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script&gt;alert(1)&lt;\/script&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This payload is useful for visually confirming whether JavaScript can be executed, but it does not reflect the actual impact. A thorough assessment then seeks to understand what the compromised browser can do in the victim\u2019s specific context.<\/p>\n\n\n\n<h2 id=\"how-does-an-xss-work\" class=\"wp-block-heading\">How Does an XSS Work?<\/h2>\n\n\n\n<h3 id=\"verifiable-data-interpretation-and-output-context\" class=\"wp-block-heading\">Verifiable data, interpretation and output context<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An XSS vulnerability typically arises when three conditions are met: an attacker controls some data, that data reaches a rendering point or a vulnerable sink, and the processing applied is not suited to the context in which it is interpreted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s take, for example, a simplified search function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;p&gt;Results for : &lt;?php echo $_GET&#91;'q']; ?&gt;&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">With the query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/search?q=computer<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, the browser receives:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;p&gt;Results for: computer&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the value of <code>q<\/code> contains markup and no output encoding is applied, the browser may render new elements instead of displaying a string of characters. The problem is therefore not that the value was \u2018incorrect\u2019 when it entered the application. The problem arises when it is used in a context where certain characters alter the expected syntax.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This principle is fundamental: data is not inherently secure simply because it comes from a database, an internal API or an already authenticated user. Security must be assessed at the point of use.<\/p>\n\n\n\n<h3 id=\"role-of-the-browser-and-the-origin\" class=\"wp-block-heading\">Role of the browser and the origin<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In particular, the browser enforces the Same-Origin Policy to prevent a page from arbitrarily accessing data from another site. An XSS attack circumvents this trust model: the malicious code is not executed from an external site, but directly within the vulnerable origin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This does not mean that it gains unlimited access to the workstation. Browser sandboxing, permissions, CSP (Content Security Policy) and other security mechanisms continue to apply. However, from the perspective of the affected application, the injected script is in a very advantageous position. It can often call the same APIs as the legitimate interface and act with the privileges of the user who triggered the payload.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is also why CSRF protections often prove insufficient when an XSS vulnerability is present. They are designed to prevent a third-party site from triggering actions, not to deal with JavaScript executed within the trusted origin itself.<\/p>\n\n\n\n<h2 id=\"understanding-xss-injection-contexts\" class=\"wp-block-heading\">Understanding XSS Injection Contexts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Identifying the injection context is the most important step before constructing a payload. The browser does not interpret data placed within the HTML body, in an attribute, in a JavaScript string, in a URL or in a CSS fragment in the same way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Characters with syntactic significance and the necessary protection mechanisms therefore differ depending on their position.<\/p>\n\n\n\n<h3 id=\"injection-into-html-content\" class=\"wp-block-heading\">Injection into HTML content<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The simplest example is that of data inserted between two tags:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"result\"&gt;\n    USER_INPUT\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A vulnerable implementation may be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"result\"&gt;\n    &lt;?php echo $_GET&#91;'search']; ?&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the following entry is left as it is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;img src=x onerror=alert(1)&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The browser creates a genuine HTML element and interprets its event handler. It is therefore not necessary to inject a <code>&lt;script&gt; <\/code>tag.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When the requirement is simply to display text, the value must be encoded for the HTML context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In PHP, an implementation could, for example, be based on:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo htmlspecialchars(\n    $_GET&#91;'search'],\n    ENT_QUOTES | ENT_SUBSTITUTE,\n    'UTF-8'\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The string is then rendered as text, without altering the document\u2019s structure. This operation must be carried out at the time of rendering; it is generally preferable to retain the original data in storage rather than saving a version that has already been escaped for a specific context.<\/p>\n\n\n\n<h3 id=\"injection-into-an-html-attribute\" class=\"wp-block-heading\">Injection into an HTML attribute<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let us now consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;input type=\"text\" value=\"USER_INPUT\"&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The data is enclosed in double quotes. If the quotes are not correctly encoded, a controlled value may close the attribute and introduce new ones.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An entry such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\" autofocus onfocus=\"alert(1)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">can transform a vulnerable structure into:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;input type=\"text\" value=\"\" autofocus onfocus=\"alert(1)\"&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The key point here is the absence of delimiters. A payload intended for the HTML body is therefore not necessarily suitable for an attribute.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is also preferable to always enclose dynamic values in quotes. Attributes without delimiters give the parser more scope for interpretation and unnecessarily complicate security measures.<\/p>\n\n\n\n<h3 id=\"dangerous-attributes-and-separation-between-data-and-code\" class=\"wp-block-heading\">Dangerous attributes and separation between data and code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Not all attributes pose the same risk. Text data placed in <code>title<\/code> is not the same as data injected into <code>onclick<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;button onclick=\"showProfile(\u201cUSER_INPUT\u201d)\"&gt;View profile&lt;\/button&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, the application deliberately places data in the middle of a JavaScript context. Even a complex encoding system becomes vulnerable because multiple syntaxes are intertwined.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A safer design involves separating behaviour and data:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;button id=\"profileButton\"&gt;View profile&lt;\/button&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and then to link the event from a static script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>document\n  .getElementById('profileButton')\n  .addEventListener('click', showProfile);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The general principle is simple: where an architectural approach makes it possible to avoid inserting an unreliable value directly into the code, this solution is generally preferable to attempting to filter it out.<\/p>\n\n\n\n<h3 id=\"injection-into-a-javascript-string\" class=\"wp-block-heading\">Injection into a JavaScript string<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A piece of data can be entered directly into a JavaScript block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script&gt;\nconst username = 'USER_INPUT';\n&lt;\/script&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The relevant parser is no longer just the HTML parser. The browser must also interpret JavaScript syntax. Protection designed exclusively for the HTML body is therefore not sufficient.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You should avoid, as far as possible, constructing JavaScript code by concatenating it with untrusted data. When the server needs to send values to the client, these must be serialised using a mechanism designed to produce a valid data representation and embedded within a structure that prevents them from being taken out of their intended context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In PHP, one approach, for example, is to use <code>json_encode()<\/code> with options suited to the HTML context rather than manually constructing a string:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script&gt;\nconst username = &lt;?php echo json_encode(\n    $username,\n    JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT\n); ?&gt;;\n&lt;\/script&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In modern architecture, it is often still preferable to load data via a JSON API or place it in a dedicated data store, and then keep the JavaScript code static.<\/p>\n\n\n\n<h3 id=\"single-and-double-quotes-and-template-literals\" class=\"wp-block-heading\">Single and double quotes, and template literals<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The following constructions use different structures:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const value1 = 'USER_INPUT';\nconst value2 = \"USER_INPUT\";\nconst value3 = `USER_INPUT`;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Template literals (strings) may, in particular, contain <code>${...}<\/code> expressions. A filter designed solely to neutralise the apostrophe therefore does not protect a value that is reused with double quotes or backticks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">During an audit, the choice of delimiter forms part of the context to be identified. One should never infer the security of a field based on the behaviour observed in another representation of the same data.<\/p>\n\n\n\n<h3 id=\"json-data-embedded-in-a-page\" class=\"wp-block-heading\">JSON data embedded in a page<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Many applications set an initial state within a <code>&lt;script&gt;<\/code> element:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script&gt;\nwindow.initialData = {\n  \"username\": \"USER_INPUT\"\n};\n&lt;\/script&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The fact that the structure resembles JSON is not enough to make it secure. A genuine <code>application\/json<\/code> response must be distinguished from a fragment of serialised data placed within an HTML document and a <code>script<\/code> element.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the latter case, the rules of the enclosing document remain important. In particular, incorrect serialisation may result in sequences appearing that alter the HTML structure even before the JavaScript engine interprets the value.<\/p>\n\n\n\n<h3 id=\"url-injection\" class=\"wp-block-heading\">URL injection<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An application can create a link from a controllable value:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;a href=\"USER_INPUT\"&gt;Continue&lt;\/a&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Two separate issues need to be addressed. Encoding prevents the data from breaking the attribute\u2019s syntax; validation checks that the URL itself matches what the application accepts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the feature is only intended to generate HTTPS links to a list of approved domains, the policy must be explicitly checked. A string may be perfectly encoded from an HTML perspective whilst still being a functionally prohibited destination.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This distinction between encoding and validation is essential for dynamic links, redirects, callbacks and certain JavaScript APIs that manipulate URLs.<\/p>\n\n\n\n<h3 id=\"injection-in-a-css-context\" class=\"wp-block-heading\">Injection in a CSS context<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CSS injections are less commonly exploited as direct XSS in modern browsers than certain older techniques. They remain, however, important for understanding contextual reasoning.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;style&gt;\n.profile {\n  background-image: url('USER_INPUT');\n}\n&lt;\/style&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The data is interpreted here using CSS syntax, which is itself embedded within an HTML document. Strict validation of the expected value is generally preferable to accepting an arbitrary CSS fragment. If the user is only required to select a colour, the application could, for example, restrict the value to an expected colour format rather than accepting a complete property.<\/p>\n\n\n\n<h3 id=\"svg-mathml-and-rich-html-content\" class=\"wp-block-heading\">SVG, MathML and rich HTML content<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An application that allows rich HTML must also take into account namespaces such as SVG or MathML and the associated parsing considerations. The difficulty lies not only in a list of dangerous tags, but in the interactions between elements, attributes and DOM transformations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is one of the reasons why a robust HTML sanitiser should not be replaced by a few regular expressions. Specialised libraries rely on a structured understanding of the document and on precise policies regarding permitted elements and attributes.<\/p>\n\n\n\n<h3 id=\"injections-across-several-successive-contexts\" class=\"wp-block-heading\">Injections across several successive contexts<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Data may be safe in an initial response but become dangerous when reused.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose the server returns:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div id=\"data\"&gt;\n  &amp;lt;img src=x onerror=alert(1)&amp;gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The content is harmless at this stage: it is displayed as plain text. However, a script could read it and re-inject it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const value = document\n  .getElementById('data')\n  .textContent;\n\npreview.innerHTML = value;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>textContent<\/code> returns the logical characters, and then <code>innerHTML<\/code> instructs the browser to interpret them as HTML. The problem therefore arises at the second sink.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This scenario illustrates a general principle: data does not become \u2018definitively secure\u2019 simply because it has been encoded once. Protection must be tailored to each sensitive use case.<\/p>\n\n\n\n<h2 id=\"what-are-the-different-types-of-xss-attacks\" class=\"wp-block-heading\">What are the Different Types of XSS Attacks?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">XSS attacks are often categorised into three main types: reflected XSS, stored XSS and DOM-based XSS. Whilst this classification is useful, it does not describe exactly the same aspect in every case. Reflected and stored XSS primarily indicate how the data reaches the victim, whilst DOM-based XSS describe the location of the vulnerable processing on the client-side.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Blind XSS and Self-XSS are best understood as specific scenarios rather than as strictly equivalent categories.<\/p>\n\n\n\n<h3 id=\"reflected-xss-attacks\" class=\"wp-block-heading\">Reflected XSS attacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A reflected XSS occurs when data from the current request is immediately re-injected into the response or the DOM in a dangerous manner.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A search function might, for example, contain:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo $_GET&#91;'search'];<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The payload is not necessarily stored. The attacker usually has to trick the victim into loading a specially crafted request, for example via a link or a redirect.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The fact that user interaction is required does not automatically mean that the severity is low. If the page is viewed by an authenticated user and exposes sensitive actions, the execution of the JavaScript may grant significant access to their session.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/09\/reflected-xss-en.svg\" alt=\"Reflected XSS attacks\" class=\"wp-image-3769\"\/><\/figure>\n\n\n\n<h3 id=\"stored-xss-attacks\" class=\"wp-block-heading\">Stored XSS attacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A stored XSS occurs when user-supplied data is stored and then rendered at a later stage without appropriate protection. It may be stored in a database, a file, a logging system or any other persistent mechanism.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Profile fields, comments, support tickets, collaborative tools, messaging systems and editorial content are common entry points. The danger lies in the fact that the payload becomes part of the application\u2019s content and can be executed automatically every time the page is viewed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A stored XSS is particularly critical when the data is displayed to privileged operators or to a large number of users. The same payload can then affect multiple victims without requiring a specific link for each one.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/09\/stored-xss-en.svg\" alt=\"Stored XSS attacks\" class=\"wp-image-3765\"\/><\/figure>\n\n\n\n<h3 id=\"dom-based-xss-attacks\" class=\"wp-block-heading\">DOM-Based XSS attacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A DOM-based XSS occurs when the vulnerability lies in the code executed on the browser side. The server may never receive or reflect the full payload.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>document\n  .getElementById('output')\n  .innerHTML = location.hash;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The part of a URL that follows the <code>#<\/code> symbol is not normally sent to the server. However, the page\u2019s JavaScript can read it and then insert it into the DOM. If the sink interprets the value as HTML, an injection can therefore occur entirely on the client-side.<\/p>\n\n\n\n<h3 id=\"blind-xss-attacks\" class=\"wp-block-heading\">Blind XSS attacks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A Blind XSS generally refers to an injection that is executed at a later stage in a context that the attacker cannot directly observe. It is frequently a Stored XSS triggered within an internal interface.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, a public form may record a company name, a ticket subject or a message. The user never sees this data, but it may be displayed in a CRM or back-office system used by the support team.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">During a penetration test, a controlled callback mechanism can be used to confirm that an injected value has been processed within an interface that is not accessible to the auditor. This type of vulnerability is particularly significant because the victim may have elevated privileges.<\/p>\n\n\n\n<h3 id=\"self-xss\" class=\"wp-block-heading\">Self-XSS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The term \u2018Self-XSS\u2019 refers to scenarios in which a user must execute the code themselves, for example by pasting it into the browser console following social engineering.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This scenario should not be confused with a traditional XSS vulnerability that automatically triggers code execution on another victim\u2019s system. The risk lies primarily in social engineering.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, it may become relevant when another weakness transforms this manual action into an exploitable chain that can be automated. The distinction must therefore be explained rather than simply classified as an XSS of the same nature as the previous ones.<\/p>\n\n\n\n<h2 id=\"dom-based-xss-understanding-sources-and-sinks\" class=\"wp-block-heading\">DOM-Based XSS: Understanding Sources and Sinks<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Modern applications execute much of their logic within the browser. To analyse a DOM XSS, one must trace the path taken by data between a potentially controlled source and a sink capable of interpreting it in a dangerous manner.<\/p>\n\n\n\n<h3 id=\"verifiable-sources\" class=\"wp-block-heading\">Verifiable sources<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A source is a location from which JavaScript retrieves a value. URLs constitute a significant category of sources via <code>location.search<\/code>, <code>location.hash<\/code>, <code>location.href<\/code> or <code>document.URL<\/code>. <code>document.referrer<\/code>, <code>window.name<\/code> and messages received via <code>postMessage<\/code> may also be of interest, depending on the application\u2019s trust model.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Client-side storage is not automatically a hostile source, but a value stored in <code>localStorage<\/code>, <code>sessionStorage<\/code> or <code>IndexedDB<\/code> becomes a concern if an attacker has a way of manipulating it. The same applies to data retrieved via an API: the question is not just \u2018where does it come from?\u2019, but \u2018who can control its content before it reaches the browser?\u2019.<\/p>\n\n\n\n<h3 id=\"dangerous-html-sinks\" class=\"wp-block-heading\">Dangerous HTML sinks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A sink is an operation in which data is used. APIs such as <code>innerHTML<\/code>, <code>outerHTML<\/code>, <code>insertAdjacentHTML()<\/code> or <code>document.write()<\/code> instruct the browser to interpret a string as HTML.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>element.innerHTML = userInput;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">is much riskier than:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>element.textContent = userInput;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">when the functional requirement is simply to display text. The difference does not lie in the data itself, but in the behaviour required of the browser.<\/p>\n\n\n\n<h3 id=\"sinks-that-execute-or-generate-code\" class=\"wp-block-heading\">Sinks that execute or generate code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Functions that evaluate a string as JavaScript are even more sensitive. <code>eval()<\/code> and <code>new Function()<\/code> are obvious examples. Certain forms of <code>setTimeout()<\/code> or <code>setInterval()<\/code> may also evaluate a string when they are not passed a function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The aim of remediation should generally be to eliminate the dynamic evaluation of untrusted data. Attempting to filter out all possible JavaScript syntax is a much more fragile approach.<\/p>\n\n\n\n<h3 id=\"trace-the-flow-between-the-source-and-the-sink\" class=\"wp-block-heading\">Trace the flow between the source and the sink<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let us consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const fragment = location.hash.substring(1);\nconst decoded = decodeURIComponent(fragment);\ndocument.getElementById('result').innerHTML = decoded;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>location.hash<\/code> is the source. <code>substring()<\/code> modifies the string, <code>decodeURIComponent()<\/code> transforms it again, and <code>innerHTML<\/code> is the final sink.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A proper analysis tracks the value right up to the point where it is used. In a real-world application, several functions, components and libraries may intervene between the source and the sink. It is precisely this distance that makes certain DOM XSS attacks difficult to identify using a simple HTTP scanner.<\/p>\n\n\n\n<h3 id=\"postmessage-and-cross-origin-trust\" class=\"wp-block-heading\">postMessage and cross-origin trust<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">postMessage is widely used in applications that include iframes, embedded components or SSO flows. An example of unsafe handling might look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>window.addEventListener('message', event =&gt; {\n  result.innerHTML = event.data;\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Two aspects need to be analysed: who can send the message, and how event.data is used.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A more robust implementation checks the origin when the trust model requires it and uses a text sink if the content does not need to be interpreted as HTML:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>window.addEventListener('message', event =&gt; {\n  if (event.origin !== 'https:\/\/trusted.example') {\n    return;\n  }\n\n  result.textContent = event.data;\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Checking event.origin and choosing a secure sink address two different risks. One does not replace the other.<\/p>\n\n\n\n<h3 id=\"multiple-decodings-and-successive-representations\" class=\"wp-block-heading\">Multiple decodings and successive representations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A value may be encoded, decoded and then re-encoded several times. In this case, a security mechanism situated upstream may analyse a representation that differs from the one that actually reaches the sink.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Double encoding is not automatically a bypass. It simply serves as a reminder that an audit must examine the exact representation of the data at each stage. The value that matters is the one ultimately consumed by the parser or the sensitive sink.<\/p>\n\n\n\n<h3 id=\"dom-clobbering-and-exploitation-chains\" class=\"wp-block-heading\">DOM clobbering and exploitation chains<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">DOM Clobbering exploits certain browser behaviours in which elements with id or name attributes can influence properties accessible via window or document.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This mechanism is not an XSS attack in its own right, but it can form part of a chain of attacks. For example, a script might assume that a global property contains a safe configuration value, whilst an injected HTML element alters what the code retrieves.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The inclusion of DOM Clobbering in this article serves above all as a reminder that JavaScript execution can result from an interaction between several primitives, and not solely from the direct insertion of <code>&lt;script&gt;<\/code>.<\/p>\n\n\n\n<h2 id=\"mutation-xss-and-the-complexity-of-html-parsing\" class=\"wp-block-heading\">Mutation XSS and the complexity of HTML parsing<\/h2>\n\n\n\n<h3 id=\"why-html-sanitisation-is-complex\" class=\"wp-block-heading\">Why HTML sanitisation is complex<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When an application wishes to allow rich HTML, full encoding is no longer compatible with the functionality: it would also convert legitimate tags into text. It is therefore necessary to allow certain structures and eliminate others.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The problem is that HTML is not a string that can be interpreted in a straightforward manner. The browser parses the document, corrects certain structures, applies different rules depending on the namespaces, and may produce a DOM that differs from the initial textual representation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This complexity makes hand-coded sanitisers particularly risky. A regular expression that removes <code>&lt;script&gt;<\/code> does not understand either the structure of the document or the many ways in which active behaviour can be achieved.<\/p>\n\n\n\n<h3 id=\"mxss-when-the-dom-changes-after-sanitisation\" class=\"wp-block-heading\">mXSS: when the DOM changes after sanitisation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Mutation XSS (mXSS) exploits differences between the representation analysed by a sanitisation mechanism and that obtained following a further phase of parsing, serialisation or DOM mutation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key point is not to store a specific payload. It is important to understand that content may be considered safe in one state but can be interpreted differently following a transformation by the browser or a library.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This justifies the use of specialised and actively maintained libraries, as well as paying particular attention to the code executed after sanitisation. A sanitised value that is then concatenated with new, untrusted data can, of course, become dangerous again.<\/p>\n\n\n\n<h2 id=\"how-do-attackers-exploit-xss-vulnerabilities\" class=\"wp-block-heading\">How Do Attackers Exploit XSS Vulnerabilities?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">An <code>alert()<\/code> dialogue box confirms the presence of an XSS vulnerability. The actual impact must be assessed based on the compromised browser, the victim\u2019s session and the features to which they have access.<\/p>\n\n\n\n<h3 id=\"acting-within-the-victims-authenticated-session\" class=\"wp-block-heading\">Act within the victim\u2019s authenticated session<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">One of the most significant attack vectors involves directly exploiting the victim\u2019s session. Historically, demonstrations have focused on stealing cookies via <code>document.cookie<\/code>. The <code>HttpOnly<\/code> attribute prevents JavaScript from directly reading the relevant cookie, but it does not prevent XSS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A script running within the application can often send a request to an endpoint of the same origin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fetch('\/api\/account\/details', {\n  credentials: 'include'\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Where the session relies on cookies associated with that request, the browser can include them without the script needing to know their values.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An attacker may therefore sometimes view data or trigger actions from the authenticated browser without stealing the session token.<\/p>\n\n\n\n<h3 id=\"compromising-an-administration-interface\" class=\"wp-block-heading\">Compromise an administration interface<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The severity increases significantly when an injection can be triggered by an administrator. A classic example involves injecting data into a ticket, a message or a customer record that will subsequently be displayed in a back-office system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The JavaScript then runs within the privileged user\u2019s context. Depending on the features available in the interface, it may potentially access additional data, create an account, modify permissions or call administrative endpoints.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The impact should not be extrapolated without evidence. During a penetration test, it is preferable to demonstrate a controlled action on a test object or account rather than carrying out destructive operations.<\/p>\n\n\n\n<h3 id=\"theft-of-client-side-data\" class=\"wp-block-heading\">Theft of client-side data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An XSS attack can read data present in the DOM and, depending on the storage mechanisms, certain values stored in <code>localStorage<\/code>, <code>sessionStorage<\/code> or <code>IndexedDB<\/code>. It can also access JavaScript objects exposed on the page.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This capability becomes particularly sensitive when an application stores an access token in a location accessible to the origin\u2019s JavaScript. Unlike an <code>HttpOnly<\/code> cookie, this token can then be read directly by the injected script.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, the risk must be assessed in terms of scopes, validity period, rotation, revocation and server-side restrictions. The mere fact that a token is a JWT is not in itself the main problem.<\/p>\n\n\n\n<h3 id=\"phishing-with-a-legitimate-source\" class=\"wp-block-heading\">Phishing with a legitimate source<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An injected script can alter the interface displayed to the user: add a form, hide a message, replace a content area or display a re-authentication prompt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This scenario is particularly convincing because the user remains on the legitimate domain. The usual signs of phishing, such as an unfamiliar domain name, are partially masked. XSS therefore turns the compromised application into a social engineering tool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">During an audit, non-destructive visual evidence may be sufficient to demonstrate this risk, without the need to collect actual credentials.<\/p>\n\n\n\n<h3 id=\"keylogging-and-monitoring-of-interactions\" class=\"wp-block-heading\">Keylogging and monitoring of interactions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">JavaScript can register listeners for certain page events and monitor interactions with the user interface. Technically, this can be used to capture data entered into fields accessible within the same context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The scope depends on the content actually processed by the page. In a sensitive back-office system, this may involve authentication details, business data or privileged commands. The assessment must be based on the actual functionality present rather than on a generic assumption.<\/p>\n\n\n\n<h3 id=\"xss-and-csrf-protection\" class=\"wp-block-heading\">XSS and CSRF protection<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An XSS attack often renders CSRF protections largely ineffective because the malicious code is already running within the trusted origin. It is important to be precise, however: the browser does not automatically add an arbitrary CSRF token or a custom authentication header to every request.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The injected script can, however, replicate the legitimate behaviour of the application: reading a token present in the DOM when it is accessible, calling an endpoint that provides it, or triggering the same JavaScript function as the normal interface.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">XSS therefore does not cryptographically \u2018break\u2019 the CSRF mechanism; rather, it circumvents its key security assumption, namely that code executed within the application origin is trustworthy.<\/p>\n\n\n\n<h3 id=\"xss-and-jwt-tokens\" class=\"wp-block-heading\">XSS and JWT tokens<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In a SPA (Single Page Application), a JWT token can be used as a bearer token to call an API. If this token is stored in <code>localStorage<\/code> or another area accessible to JavaScript, an XSS attack could potentially extract it and then reuse it outside the browser, depending on the server-side controls.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If, on the other hand, authentication relies on an <code>HttpOnly<\/code> cookie, direct theft of the secret can be prevented, but the script can still act within the session as long as it is running in the browser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The assessment must therefore distinguish between the theft of the authentication secret and the misuse of the victim\u2019s session. These two scenarios do not have the same consequences in terms of persistence and detection.<\/p>\n\n\n\n<h3 id=\"chaining-xss-with-other-vulnerabilities\" class=\"wp-block-heading\">Chaining XSS with other vulnerabilities<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An XSS vulnerability can become a step in a wider attack chain. For example, it may enable an attacker to access an internal feature reserved for an administrator, retrieve data required for another attack, or trigger an action that exposes a new attack surface.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The reasoning must remain practical: it is not enough simply to list every conceivable vulnerability. A relevant attack chain is one where the prerequisites are actually present in the application being tested.<\/p>\n\n\n\n<h2 id=\"methodology-for-detecting-xss-vulnerabilities-during-a-penetration-test\" class=\"wp-block-heading\">Methodology for Detecting XSS Vulnerabilities During a Penetration Test<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">XSS search becomes far more effective when carried out as an analysis of data, contexts and sinks, rather than by randomly sending a long list of payloads.<\/p>\n\n\n\n<h3 id=\"mapping-controllable-inputs\" class=\"wp-block-heading\">Mapping controllable inputs<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The auditor begins by identifying the data that an attacker could manipulate: GET and POST parameters, form fields, profiles, comments, tickets, messages, file names, redirection parameters, URL fragments, data sent to APIs, HTTP headers or values from third-party integrations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is also important to consider data that is not immediately displayed. A \u2018Company\u2019 field entered on a public portal may be reused in a CRM, an HTML invoice, an email or a back-office system. Each instance of this data represents a different security context.<\/p>\n\n\n\n<h3 id=\"use-unique-markers\" class=\"wp-block-heading\">Use unique markers<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before sending an active payload, a recognisable marker is often more useful:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>XSS-HACKAGORA-84721<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The aim is to identify the value in the responses and in the DOM, to determine whether it is stored, whether it appears in several places, and what transformations it undergoes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For persistent or blind tests, it is useful to use a different identifier for each field:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>XSS-NAME-84721\nXSS-COMPANY-84722\nXSS-SUBJECT-84723\nXSS-MESSAGE-84724<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means that a callback or a later observation can be linked precisely to the injection point.<\/p>\n\n\n\n<h3 id=\"compare-the-http-response-and-the-final-dom\" class=\"wp-block-heading\">Compare the HTTP response and the final DOM<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In a traditional application, the HTML in the response and the final DOM may be similar. In a SPA, they can be very different: the server sometimes returns a simple container, after which JavaScript builds the entire interface using APIs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The auditor must therefore examine both the raw response and the DOM after execution. Data missing from the initial HTML may subsequently appear; a harmless value in the response may also be re-read and then injected into a dangerous sink.<\/p>\n\n\n\n<h3 id=\"identify-the-context-precisely\" class=\"wp-block-heading\">Identify the context precisely<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The marker may appear in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;p&gt;XSS-HACKAGORA-84721&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">or:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;input value=\"XSS-HACKAGORA-84721\"&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">or:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const name = 'XSS-HACKAGORA-84721';<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These three scenarios require different analyses. The construction of a payload should only begin once the context has been understood.<\/p>\n\n\n\n<h3 id=\"observe-the-changes\" class=\"wp-block-heading\">Observe the changes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The auditor then tests the behaviour of characters that have a specific meaning in the identified context, such as &lt;, &gt;, \u00ab, \u2018, `, `, &amp; or \/`.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The aim is not immediately to bypass a filter, but to determine what the application does. Does the character &lt; become &amp;lt;? Are quotes encoded? Is a value decoded twice? Does a sanitiser remove the element or only certain attributes?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This analysis reveals the protection actually in place and often makes it possible to distinguish between correct encoding and a weak blocklist.<\/p>\n\n\n\n<h3 id=\"build-minimal-evidence-appropriate-to-the-context\" class=\"wp-block-heading\">Build minimal evidence appropriate to the context<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once the structure is understood, the proof of concept should be as simple as possible. In an HTML context, an element containing an event handler may be sufficient. In an attribute, one must first determine whether it is possible to escape the delimiter. In JavaScript, the exact syntax of the string must be analysed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A minimal proof makes remediation easier: it clearly shows which syntactic boundary has been crossed without obscuring the problem behind a complex payload.<\/p>\n\n\n\n<h2 id=\"how-to-prevent-xss-vulnerabilities\" class=\"wp-block-heading\">How To Prevent XSS Vulnerabilities?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There is not a single security measure that applies to all situations. The most robust strategy is to maintain a strict separation between data and code, and then to choose the appropriate security measures based on the rendering context.<\/p>\n\n\n\n<h3 id=\"encode-at-the-time-of-output-and-according-to-the-context\" class=\"wp-block-heading\">Encode at the time of output and according to the context<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When text needs to be displayed, contextual encoding is one of the main safeguards. A value intended for the HTML body is not treated in the same way as an attribute value, a URL or a JavaScript string.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Encoding must be carried out as close as possible to the sink. Encoding data as soon as it enters the application is unreliable: it ties the value to a specific context, may cause double encoding and does not protect against future uses in other syntaxes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Modern template engines often provide automatic escaping. It is preferable to rely on these mechanisms rather than manually recreating the transformations.<\/p>\n\n\n\n<h3 id=\"prioritise-safe-sinks\" class=\"wp-block-heading\">Prioritise safe sinks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Choosing the right API can eliminate much of the risk. When a string simply needs to be displayed, <code>textContent<\/code> is preferable to <code>innerHTML<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>output.textContent = userInput;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Beyond this example, the aim is to use APIs that manipulate structured values rather than fragments of code or markup. <code>createElement()<\/code>, safe property assignment and the explicit construction of DOM nodes are often preferable to concatenating HTML strings.<\/p>\n\n\n\n<h3 id=\"sanitise-when-html-actually-needs-to-be-accepted\" class=\"wp-block-heading\">Sanitise when HTML actually needs to be accepted<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Certain features need to retain HTML: CMS, forums, rich text editors or Markdown content converted to HTML. In such cases, simple encoding would break the functionality.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A specialised, maintained sanitisation library, such as <a href=\"https:\/\/github.com\/cure53\/dompurify\" target=\"_blank\" rel=\"noopener\">DOMPurify<\/a> for compatible uses, is preferable to a home-made filter. The configuration must be tailored to the elements and attributes that are actually required.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The security of the pipeline does not end with the call to the sanitiser. The result must not subsequently be modified with untrusted content or injected into a context that the library was not designed to protect.<\/p>\n\n\n\n<h3 id=\"validate-inputs-when-the-format-is-known\" class=\"wp-block-heading\">Validate inputs when the format is known<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Validation reduces the attack surface when the expected data has a clearly defined format. A numeric identifier can be restricted to digits; a date, a colour or an enumeration value can be subject to a strict allowlist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This measure complements output filtering but does not replace it. A free-text field cannot be made secure simply by removing a few sequences deemed suspicious.<\/p>\n\n\n\n<h3 id=\"avoid-payload-blocklists\" class=\"wp-block-heading\">Avoid payload blocklists<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An approach such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>input.replace('&lt;script&gt;', '')<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">is fundamentally inadequate. Browsers have numerous mechanisms for enabling active behaviour without using this exact string.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The correct strategy is not to recognise every conceivable attack. It is to prevent untrusted data from being interpreted as code in the context in which it is used.<\/p>\n\n\n\n<h3 id=\"retain-your-frameworks-automatic-safeguards\" class=\"wp-block-heading\">Retain frameworks&#8217; automatic safeguards<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The escape mechanisms in frameworks and template engines must remain enabled by default. APIs that return raw HTML or mark a value as safe must be few and far between, clearly identified and treated as security boundaries.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When a component receives sanitised HTML, the source of the data and the sanitisation process must be explicitly stated in the code. This practice also facilitates audits and reduces the risk of unintentional bypasses.<\/p>\n\n\n\n<h3 id=\"content-security-policy-as-a-defence-in-depth-strategy\" class=\"wp-block-heading\">Content Security Policy as a defence-in-depth strategy<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CSP allows you to restrict script sources and execution conditions. A modern policy can rely on nonces or hashes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Content-Security-Policy:\n  default-src 'self';\n  script-src 'nonce-RANDOM_VALUE';<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">More advanced policies may use <code>strict-dynamic<\/code> when appropriate for the architecture. The aim is to minimise the execution of scripts that have not been explicitly authorised.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, CSP should not be regarded as a fix for XSS. A permissive policy, an exploitable authorised source or a change in configuration may allow the exploit to be reinstated. The vulnerability must be addressed at the data flow and sink levels.<\/p>\n\n\n\n<h3 id=\"trusted-types-to-reduce-dom-xss\" class=\"wp-block-heading\">Trusted Types to reduce DOM XSS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Trusted Types provides architectural protection against the accidental use of arbitrary strings in certain sensitive DOM sinks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In particular, a CSP policy may require the use of Trusted Types on the relevant sinks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Content-Security-Policy: require-trusted-types-for 'script';<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On compatible browsers, the code must then provide Trusted Types objects rather than ordinary strings to certain APIs. The application can centralise the creation of HTML content within explicitly audited policies, for example by passing the data through a sanitiser before producing <code>TrustedHTML<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Trusted Types does not magically make a transformation function correct. A policy that declares dangerous content to be safe remains vulnerable. Its benefit lies in reducing the number of places capable of directly feeding sensitive sinks and making these boundaries more visible in the code.<\/p>\n\n\n\n<h3 id=\"httponly-and-minimising-the-impact\" class=\"wp-block-heading\">HttpOnly and minimising the impact<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>HttpOnly<\/code> attribute prevents JavaScript from directly reading the value of an affected cookie via <code>document.cookie<\/code>. It therefore limits certain session hijacking scenarios and should be used for authentication cookies where functionality permits.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, it does not prevent XSS. The injected script can still operate within the authenticated browser and send requests to which the cookie automatically applies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>HttpOnly<\/code> should therefore be regarded as a measure to mitigate the impact, not as a primary defence against injection.<\/p>\n\n\n\n<h3 id=\"samesite-and-actual-scope-of-protection\" class=\"wp-block-heading\">SameSite and actual scope of protection<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>SameSite<\/code> primarily controls the circumstances in which a cookie is sent in requests initiated from other sites. It therefore plays an important role in mitigating several CSRF scenarios.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An XSS attack is executed directly on the legitimate origin; the value of <kbd>SameSite<\/kbd> is therefore much more limited in such cases. The attribute remains useful as part of an overall session security strategy, but should not be presented as a direct defence against XSS attacks.<\/p>\n\n\n\n<h3 id=\"isolate-sensitive-interfaces-and-sources\" class=\"wp-block-heading\">Isolate sensitive interfaces and sources<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Architecture can also help mitigate the impact. It is not always advisable for a particularly sensitive administration interface to share the same origin as an area used to display user-controlled rich content.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Separating origins can limit the interactions permitted by the Same-Origin Policy and reduce the scope of a compromise. Whilst this measure does not replace the need to fix injection vulnerabilities, it provides a useful defence-in-depth strategy in certain risk models.<\/p>\n\n\n\n<h3 id=\"maintain-rendering-and-sanitisation-libraries\" class=\"wp-block-heading\">Maintain rendering and sanitisation libraries<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Frameworks, Markdown parsers, WYSIWYG editors, sanitisers and components that manipulate HTML form part of the security surface. They must be inventoried and kept up to date.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An application may use a library correctly yet still be vulnerable if the version contains a known exploit or if the value is subsequently modified in a context not covered by the library\u2019s security model.<\/p>\n\n\n\n<h2 id=\"conclusion\" class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">XSS vulnerabilities remain significant because they exploit a central element of the relationship of trust between the user and an application: the user\u2019s browser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Understanding them must not be limited to the injection of a <code>&lt;script&gt;<\/code> tag or the theft of the <code>document.cookie<\/code>. A modern XSS attack is, above all, a problem of data flow and interpretation context. A controllable value enters the system, may pass through several components, and then reaches a point where the browser can interpret it as active content.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This approach explains why encoding must be context-dependent, why safe sinks are preferable to APIs that interpret HTML, why sanitisation is only necessary when rich content actually needs to be preserved, and why frameworks\u2019 automatic protections must not be deliberately disabled without additional checks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From a penetration testing perspective, the same logic applies in reverse. An effective methodology begins by identifying controllable data and its outputs, then analyses the transformations and sinks before constructing a suitable proof. This method is particularly important for DOM XSS, persistent injections into internal interfaces, and complex JavaScript applications.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, the severity must always be considered within its functional context: what triggers the payload, what data is accessible, what actions can be performed, and which session model is used. It is this combination of understanding the browser, analysing data flows and assessing privileges that enables both the accurate detection of XSS attacks and their long-term prevention.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>XSS (Cross-Site Scripting) vulnerabilities are among the longest-standing vulnerabilities in web applications. Depending on the context, an XSS vulnerability can lead to session hijacking, credential theft, account takeover, the exposure of sensitive data, or even the compromise of administration interfaces. In this article, we outline the principles and mechanics of XSS vulnerabilities. We also detail [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3889,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,24],"tags":[],"class_list":["post-3888","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-applications","category-guides"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":8}},"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Eli T.\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"HackAgora \u2013 Expose. Understand. Defend.\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"XSS (Cross-Site Scripting): Exploitations and Security Tips\" \/>\n\t\t<meta property=\"og:description\" content=\"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"313\" \/>\n\t\t<meta property=\"og:image:height\" content=\"122\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-09-01T16:34:43+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-09-15T11:19:37+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"XSS (Cross-Site Scripting): Exploitations and Security Tips\" \/>\n\t\t<meta name=\"twitter:description\" content=\"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#blogposting\",\"name\":\"XSS (Cross-Site Scripting): Exploitations and Security Tips\",\"headline\":\"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices\",\"author\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/author\\\/traorea_hg\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/hackagora.com\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/xss-en.svg\",\"width\":885,\"height\":659,\"caption\":\"xss cross-site scripting\"},\"datePublished\":\"2026-09-01T16:34:43+00:00\",\"dateModified\":\"2026-09-15T11:19:37+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#webpage\"},\"articleSection\":\"Applications, Guides, Facultatif\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hackagora.com\\\/en\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/category\\\/applications\\\/#listItem\",\"name\":\"Applications\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/category\\\/applications\\\/#listItem\",\"position\":2,\"name\":\"Applications\",\"item\":\"https:\\\/\\\/hackagora.com\\\/en\\\/category\\\/applications\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#listItem\",\"name\":\"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#listItem\",\"position\":3,\"name\":\"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/category\\\/applications\\\/#listItem\",\"name\":\"Applications\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#organization\",\"name\":\"HackAgora\",\"description\":\"Expose. Understand. Defend.\",\"url\":\"https:\\\/\\\/hackagora.com\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/hackagora.com\\\/wp-content\\\/uploads\\\/2026\\\/06\\\/logo_hackagora_agora_color.svg\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#organizationLogo\",\"width\":313,\"height\":122},\"image\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#organizationLogo\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/author\\\/traorea_hg\\\/#author\",\"url\":\"https:\\\/\\\/hackagora.com\\\/en\\\/author\\\/traorea_hg\\\/\",\"name\":\"Eli T.\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/748941d304278b11e857c7ae5582eefefe0689f1b0642e56a2eda7b98bae722b?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Eli T.\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#webpage\",\"url\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/\",\"name\":\"XSS (Cross-Site Scripting): Exploitations and Security Tips\",\"description\":\"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/author\\\/traorea_hg\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/author\\\/traorea_hg\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/hackagora.com\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/xss-en.svg\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#mainImage\",\"width\":885,\"height\":659,\"caption\":\"xss cross-site scripting\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\\\/#mainImage\"},\"datePublished\":\"2026-09-01T16:34:43+00:00\",\"dateModified\":\"2026-09-15T11:19:37+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/hackagora.com\\\/en\\\/\",\"name\":\"HackAgora\",\"description\":\"Expose. Understand. Defend.\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/hackagora.com\\\/en\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"XSS (Cross-Site Scripting): Exploitations and Security Tips","description":"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices","canonical_url":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#blogposting","name":"XSS (Cross-Site Scripting): Exploitations and Security Tips","headline":"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices","author":{"@id":"https:\/\/hackagora.com\/en\/author\/traorea_hg\/#author"},"publisher":{"@id":"https:\/\/hackagora.com\/en\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/09\/xss-en.svg","width":885,"height":659,"caption":"xss cross-site scripting"},"datePublished":"2026-09-01T16:34:43+00:00","dateModified":"2026-09-15T11:19:37+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#webpage"},"isPartOf":{"@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#webpage"},"articleSection":"Applications, Guides, Facultatif"},{"@type":"BreadcrumbList","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/#listItem","position":1,"name":"Home","item":"https:\/\/hackagora.com\/en\/","nextItem":{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/category\/applications\/#listItem","name":"Applications"}},{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/category\/applications\/#listItem","position":2,"name":"Applications","item":"https:\/\/hackagora.com\/en\/category\/applications\/","nextItem":{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#listItem","name":"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices"},"previousItem":{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#listItem","position":3,"name":"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices","previousItem":{"@type":"ListItem","@id":"https:\/\/hackagora.com\/en\/category\/applications\/#listItem","name":"Applications"}}]},{"@type":"Organization","@id":"https:\/\/hackagora.com\/en\/#organization","name":"HackAgora","description":"Expose. Understand. Defend.","url":"https:\/\/hackagora.com\/en\/","logo":{"@type":"ImageObject","url":"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#organizationLogo","width":313,"height":122},"image":{"@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#organizationLogo"}},{"@type":"Person","@id":"https:\/\/hackagora.com\/en\/author\/traorea_hg\/#author","url":"https:\/\/hackagora.com\/en\/author\/traorea_hg\/","name":"Eli T.","image":{"@type":"ImageObject","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/748941d304278b11e857c7ae5582eefefe0689f1b0642e56a2eda7b98bae722b?s=96&d=mm&r=g","width":96,"height":96,"caption":"Eli T."}},{"@type":"WebPage","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#webpage","url":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/","name":"XSS (Cross-Site Scripting): Exploitations and Security Tips","description":"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/hackagora.com\/en\/#website"},"breadcrumb":{"@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#breadcrumblist"},"author":{"@id":"https:\/\/hackagora.com\/en\/author\/traorea_hg\/#author"},"creator":{"@id":"https:\/\/hackagora.com\/en\/author\/traorea_hg\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/09\/xss-en.svg","@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#mainImage","width":885,"height":659,"caption":"xss cross-site scripting"},"primaryImageOfPage":{"@id":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/#mainImage"},"datePublished":"2026-09-01T16:34:43+00:00","dateModified":"2026-09-15T11:19:37+00:00"},{"@type":"WebSite","@id":"https:\/\/hackagora.com\/en\/#website","url":"https:\/\/hackagora.com\/en\/","name":"HackAgora","description":"Expose. Understand. Defend.","inLanguage":"en-US","publisher":{"@id":"https:\/\/hackagora.com\/en\/#organization"}}]},"og:locale":"en_US","og:site_name":"HackAgora \u2013 Expose. Understand. Defend.","og:type":"article","og:title":"XSS (Cross-Site Scripting): Exploitations and Security Tips","og:description":"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices","og:url":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/","og:image":"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg","og:image:secure_url":"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg","og:image:width":313,"og:image:height":122,"article:published_time":"2026-09-01T16:34:43+00:00","article:modified_time":"2026-09-15T11:19:37+00:00","twitter:card":"summary_large_image","twitter:title":"XSS (Cross-Site Scripting): Exploitations and Security Tips","twitter:description":"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices","twitter:image":"https:\/\/hackagora.com\/wp-content\/uploads\/2026\/06\/logo_hackagora_agora_color.svg"},"aioseo_meta_data":{"post_id":"3888","title":"XSS (Cross-Site Scripting): Exploitations and Security Tips","description":"What is an XSS vulnerability? This article explains how XSS works, the types of attacks, exploitation techniques and security best practices","keywords":null,"keyphrases":{"focus":{"keyphrase":"xss","score":0,"analysis":[]},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_image_url":null,"twitter_title":null,"twitter_description":null,"schema_type":"default","schema_type_options":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"BlogPosting","isEnabled":true},"graphs":[]},"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"created":"2026-09-10 14:55:08","updated":"2026-09-15 11:51:00","focus_keyword":"xss","additional_keywords":null,"truseo_locale":"en_GB"},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/hackagora.com\/en\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/hackagora.com\/en\/category\/applications\/\" title=\"Applications\">Applications<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tXSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/hackagora.com\/en\/"},{"label":"Applications","link":"https:\/\/hackagora.com\/en\/category\/applications\/"},{"label":"XSS (Cross-Site Scripting): Types of Attacks, Exploitations and Security Best Practices","link":"https:\/\/hackagora.com\/en\/xss-cross-site-scripting-vulnerabilities-types-of-attacks-exploitations-and-security-best-practices\/"}],"_links":{"self":[{"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/posts\/3888","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/comments?post=3888"}],"version-history":[{"count":23,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/posts\/3888\/revisions"}],"predecessor-version":[{"id":3969,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/posts\/3888\/revisions\/3969"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/media\/3889"}],"wp:attachment":[{"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/media?parent=3888"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/categories?post=3888"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackagora.com\/en\/wp-json\/wp\/v2\/tags?post=3888"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}