February 2026 - Code Review

Unsanitized input through URL parameter to XSS

Vulnerable piece of code

<script>
      (function applyMessageParam() {
        const elem = document.getElementById("message");
        if (!elem) return;

        const params = new URLSearchParams(window.location.search);
        const msg = params.get("message");
        if (msg === null) return;

        elem.innerHTML = `<textarea
        class="w-full resize-none rounded-2xl border px-4 py-3 ring-black/5 text-slate-800 border-white/70 bg-white/70 shadow-sm outline-none ring-1 placeholder:text-slate-400 focus:border-rose-300 focus:ring-2 focus:ring-rose-200">
        ${msg}
        </textarea>`;

        elem.dispatchEvent(
          new Event("input", { bubbles: true })
        );
      })();
    </script>

Problem

The code takes unsanitized input from any user (authenticated or not) from the URL. An attacker can manipulate this URL very easily by adding an XSS payload to the message parameter.

Payload

When an attacker appends ?message=</textarea><img src=x onerror=alert(document.domain)><textarea> to the URL, he'll see a popup with the domain. Should he send that URL to a victim, the same would happen on the victim's computer.

Dangers

Just a popup is not dangerous, but this implies that more complex attacks such as token theft, redirects, ... are also possible. These attacks pose real dangers to whoever opens the seemingly harmless link because the root of the link is trusted.

Mitigations

  • Avoid using innerHTML with user input entirely - use safer alternatives like textContent or .value

  • If sanitization is necessary, use a proper library like DOMPurify

  • Simple string replacement is insufficient - nested payloads like <scr<script>ipt> can bypass basic filters

  • Never trust client-side sanitization alone - validate and sanitize on the server side

Secure implementation

Last updated