Top 10 Reasons for XSS (Cross-Site Scripting)

Author: Kateryna Ivanenko, Invicti Brand Manager

Cross-site scripting (XSS) is a class of injection flaws that lets attackers run malicious JavaScript in a target’s browser. It occurs when untrusted data is included in web pages without proper handling, allowing to hijack user sessions, deface content, or pivot to further attacks.

The fundamental weakness behind XSS is improper neutralization of untrusted input during web page generation or DOM manipulation (CWE-79). XSS variants are different expressions of the same core issue, but there are a lot of nuances to it.

Three Types of XSS and Why They Happen

Stored (persistent) XSS

Attacker-controlled input is saved by the application (e.g., in a database, CMS, or comment) and later rendered into pages for other users. The root cause is typically mixing untrusted data into HTML responses without output encoding or sanitization.

Reflected (non-persistent) XSS

Untrusted data (e.g., from a form) is immediately reflected in the response. It often arises when server-side templates incorporate request parameters without context-aware encoding.

DOM-based XSS

Client-side JavaScript reads attacker-controlled data (like location.search or document.referrer) and writes it into dangerous sinks such as innerHTML, document.write, or eval() without any safe practices. The defect exists entirely in the browser that makes it hard to detect.

Core reasons developers still introduce XSS

1) Mixing Data and Code Without Context-Aware Output Encoding

XSS thrives when applications interpolate untrusted data directly into HTML, attributes, JavaScript, CSS, or URLs without using the correct encoding for that context. A single “escape everything” approach is insufficient; escaping rules differ across contexts. Failing to apply the right encoder is the one of the biggest reason XSS persists.

2) Unsafe Client-Side Sinks and APIs

Modern front-ends frequently manipulate the DOM at runtime. Using sinks like innerHTML, outerHTML, insertAdjacentHTML, document.write, or setting on* event handler attributes with unsanitized strings injects HTML/JS directly into the document. Security training materials consistently flag these as high-risk when fed with attacker-controlled data.

3) Trusting URL/DOM Sources Without Validation

Client-side code often consumes values from attacker-influenced sources (URL parameters, fragment identifiers, document.referrer). Passing these sources straight into HTML or script contexts without validation or safe APIs enables DOM XSS.

4) Insufficient or Misapplied Input Validation

While output encoding is primary, lack of robust allow-list validation for data that must become HTML increases risk. Developers may attempt blacklist filters that fail against obfuscation and new payload techniques, letting dangerous tokens slip into page contexts.

5) Rendering User-Generated HTML Without a Proven Sanitizer

Features like comments, CMS content, or user profiles may intentionally allow markup. Rolling custom sanitizers or using outdated ones is a common path to XSS. If HTML must be accepted, it needs a mature, actively maintained sanitizer and strict policies around allowed tags/attributes/URL schemes.

6) Template Injection and Insecure Templating Practices

Server-side or client-side templates that work with user input without secure practices can lead to code execution or XSS within the rendered page.

7) Relying solely on CSP

Content Security Policy (CSP) is an additional layer, not a substitute for context-aware encoding. Weak CSP yields a false sense of security, and even strict CSPs have limitations.

8) Third-Party Scripts and Supply-Chain Risks

Widgets, analytics, ads, and other third-party scripts execute with the page’s origin privileges. If they process attacker-controlled data insecurely — or if the supply chain is compromised — they can introduce XSS regardless of the site’s own code quality.

9) Legacy Code and Frameworks

Older codebases and libraries often predate modern defaults (like auto-escaping templates). Without refactoring, legacy patterns like concatenating HTML strings or inline event attributes persist, continually re-introducing XSS.

10) Lack of Security Testing

Even with practices above, the only way to check for sure whether the website is vulnerable to XSS is to conduct security testing. Furthermore, many tools provide remediation advice and useful resources in tickets, that helps developers to adopt secure coding practices over time.

Various tools can be used for this purpose.

  • DAST: safe imitation of hacker’s actions that uncovers vulnerabilities in a running web application.
  • SAST: static analysis that finds security issues in code “like in text”.

The best way to scan a website is to use both approaches, since DAST uncovers more real vulnerabilities due to testing in runtime, and SAST can scan a whole code base and can be integrated in early stages of CI/CD (DAST can be implemented at later stages).

If you want to test Invicti (DAST) based on Acunetix and Netsparker with vulnerability confirmation feature, and Mend.io (SAST, SCA, Container Security) for free, please leave your contact information in the form below:

Request for free Invicti/Mend.io Trial

Leave your contact details and we will get in touch with you



    Підписатися на новини