Glossary

XSS

XSS arises at output when data is mistaken for code. Contextual escaping is the primary defence; CSP, sanitisation, and safe DOM APIs add further layers.

Short definition

Data must remain data even when a browser reads it.

Cross-site scripting allows an attacker to place code on a page that runs under the same origin as the vulnerable application. It can read data available to the page, send requests on behalf of the user, modify administration content, or persuade the user to take another action. The impact depends on what the application exposes in the browser and how it protects the session.

The most common cause is not “bad JavaScript,” but inserting a value into the wrong context without the correct encoding. Contextual escaping depends on whether the target is HTML, an attribute, a URL, or JavaScript. Automatic escaping covers ordinary HTML output; raw HTML and manual innerHTML use must be deliberate and controlled.

Where protection is needed

Every output that may contain data beyond the fixed template

Untrusted data does not come only from forms. It may originate in an integration, administration interface, or previously stored record.

  • a product name, review, order note, or customer-support message
  • data imported from a marketplace, ERP, CSV file, or external API
  • an administration interface where staff see content entered by another user
  • frontend JavaScript that builds the DOM from API data or URL parameters

Practical example

A product name from an external catalogue

An importer loads a product name from a marketplace and stores it in the database. The administration interface renders the name as plain text. Even if it was supplied by a previously trusted partner, the application treats it as data: between import and display, there may have been an incorrect mapping, a compromised account, or another source of content.

The example is safe for text content inside an HTML element. It is not a universal solution for an attribute, URL, JavaScript, or an HTML editor. If the business needs a formatted description, the content is sanitised before storage or display by a proven allowlist sanitiser; the result is then distinguished from plain text.

<?php

// Bezpečné pro text uvnitř HTML elementu, například <h1>…</h1>.
$safeProductName = htmlspecialchars(
    $productName,
    ENT_QUOTES | ENT_SUBSTITUTE,
    'UTF-8',
);
?>
<h1><?= $safeProductName ?></h1>

How the vulnerability arises

From untrusted input to interpretation as code

A safe flow distinguishes where data comes from and the exact context in which it will later appear.

  1. Data enters the system A user, administrator, import, or API supplies text, a URL, or structured content that the application must not yet consider safe.
  2. Data is stored or passed on Stored content is not automatically safe. Stored XSS can affect everyone who later opens it in the administration interface or website.
  3. The application chooses the output context The value may be displayed as text, an attribute, a URL, JavaScript data, or permitted rich HTML; each context has different rules.
  4. The output is handled correctly The template uses automatic contextual escaping, a safe DOM API, or sanitisation of permitted HTML. This is not a matter of blindly replacing a few characters.
  5. The browser interprets the page A correctly encoded value remains text. CSP can limit the impact of a residual mistake, but must not be the only barrier to code execution.

Key concepts

The correct protection depends on where the value appears.

There is no single universal form of “escaping.” A safe solution starts by identifying the output context.

Reflected, stored, and DOM XSS

Reflected XSS returns input directly in the response, while stored XSS saves it first and may affect multiple users. DOM XSS arises in client-side JavaScript through unsafe handling of data and the DOM.

Contextual escaping

HTML text, attributes, URLs, and JavaScript have different syntax. Output is encoded for the place of use; general escaping at storage time leads to display errors and a false sense of security.

Sanitising rich HTML

When a description genuinely needs limited HTML, a sanitiser removes disallowed elements, attributes, and URL schemes according to an allowlist. A regular expression or manual blocklist is not a reliable security model.

Safe DOM APIs

JavaScript uses textContent or a similarly safe API for text. innerHTML, insertAdjacentHTML, dynamic URLs, and event handlers are boundaries at which data must be validated or sanitised for the context.

CSP and HttpOnly

CSP restricts the execution or loading of content, while HttpOnly prevents JavaScript from reading a cookie. Neither prevents every action by injected script within the user session.

Benefits and limitations

A strict output model protects users, but requires a clear purpose for the content.

Benefits

  • automatic template escaping covers much ordinary HTML output
  • separating text from rich HTML simplifies review and content auditing
  • a sanitiser allowlist permits limited formatting without allowing arbitrary code
  • CSP and HttpOnly add another layer when the application makes a mistake

Risks and mistakes

  • using raw HTML or innerHTML for data merely because it “does not format correctly”
  • applying HTML escaping in a JavaScript or URL context where different rules apply
  • trusting data from an internal administration interface or external integration without the same output model
  • relying on CSP, HttpOnly, or a CSRF token instead of fixing the source of XSS

When it is required

Whenever a page displays variable content.

XSS protection is fundamental to a web application, whether data comes from a public user, business partner, or internal staff. Online stores in particular pass long descriptions, product names, notes, marketing content, and API responses between multiple systems. Every boundary can change who controls the content.

The simplest safe model displays data as text and supports rich HTML only where it is genuinely needed. A content editor needs a separate sanitisation policy, tests of both allowed and forbidden constructs, and an up-to-date library. A clear restriction is safer than vague freedom to format anything.

What to consider

Escape at output and review exceptions to the automatic path.

Review should quickly reveal places where data becomes HTML, JavaScript, a URL, or dynamic DOM content.

  • keep automatic template escaping enabled and allow raw output only for a clear reason
  • choose encoding for the HTML, attribute, URL, JavaScript, or CSS context
  • use textContent instead of innerHTML and similar HTML sinks for DOM text
  • sanitise permitted rich HTML with a proven allowlist tool and test its rules
  • deploy CSP as defence in depth and monitor violations without adding broad exceptions

Common questions

Making practical decisions about XSS

Is validating data before storage enough?

No. Validation checks whether data meets business rules, but the same value may later appear in HTML, a URL, or JavaScript. XSS protection must match the specific output context.

Is HTML escaping the same for an attribute and JavaScript?

No. Every context has different syntax and dangerous points. The safest approach is not to place data in JavaScript code or dynamic HTML when structured data and safe APIs can be used instead.

Can I use raw HTML for a description editor?

Only if the content has first been safely sanitised with a proven allowlist and the team understands the contract for that content. Unescaped output from an ordinary text field is not safe.

Does CSP replace XSS protection?

No. CSP reduces the impact of some attack paths, but both the specification and practice treat it as defence in depth. Safe construction of HTML and JavaScript remains the foundation.

Does an HttpOnly cookie protect against the impact of XSS?

It prevents script from reading the marked cookie directly, but injected code can often still make requests in the user session or read data available to the page.

How I work with PHP in practice

Safe output belongs in every backend and e-commerce flow.

In applications, I address external data, templates, administration interfaces, and the security boundary between the browser, API, and database.

Request a call

I will call you on the next working day between 9:00 and 17:00.

You can also call me directly.

+420 605 181 728

Leave your phone number and send a callback request.

By sending, you agree to processing your data in order to handle your request.