URLSearchParams, DOM-based XSS & building links
Input from the address bar
Lesson 4 of 20 · 11 min · Module 1: Untrusted input
Anyone can send you a link. If a page copies part of its own address into the page unsafely, an attacker only needs someone to open a crafted link, for example from an email or a chat message.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Recognise the address as untrusted input
- Read query parameters with URLSearchParams
- Build addresses safely with URL and searchParams
The idea
Read query parameters with new URLSearchParams(location.search), which decodes them for you, and show the value with textContent. When you build addresses that contain people’s text, create them with new URL() and set values with url.searchParams.set(), so characters such as &, # and spaces cannot change the meaning of the address.
const url = new URL('https://forum.example/search');
url.searchParams.set('q', 'cats & dogs #1');
console.log(url.href);
// https://forum.example/search?q=cats+%26+dogs+%231
01DOM-based XSS
When the page itself moves data from the address into the page, no server is involved at all: the attack lives in the link. Data in location.search, location.hash and document.referrer is controlled by whoever made the link.
02Decoding is done for you
URLSearchParams turns %3C back into < and + into a space. That is what you want for searching, and exactly why the result must be treated as untrusted text.
console.log(new URLSearchParams('?q=%3Cb%3Ehi%3C%2Fb%3E').get('q'));<b>hi</b>03Build addresses with URL
Gluing text into an address lets & start a new parameter and # cut the rest off. url.searchParams.set() encodes every character that needs it, and new URL() checks that the result is a valid address.
Your turn
render(): show Results for “…” (or All articles without a search term) in #heading as text, list the matching articles as text, and point #forum-link to https://forum.example/search with the search term as its only q parameter. The term is read from ?q=, without spaces around it, and matching ignores capital letters. Use the pretend address bar to try your page.What the checks look for
- Without a search term, every article is listed
- The search term comes from the address
- A crafted address cannot add HTML
- The forum link keeps the search term intact
- Spaces around the term and capital letters do not matter
- The pretend address bar works too
Take this with you
Read the address with URLSearchParams, show it as text, and build new addresses with URL.
Go a little further
Highlight the search term inside each result with a <mark> element, built with DOM methods instead of HTML strings.