Okay so today I was solving an XSS lab, and at first it was honestly confusing But after struggling a bit, I finally figured it out. Let me walk you through it.
Step 1: Understanding the code
I checked the page source and found this script:
function tracking(search, hash) {
document.getElementById('tracker').href = search;
document.getElementById(hash).click();
}
var urlParams = new URLSearchParams(window.location.search);
var searchTerm = decodeURI(urlParams.get('search'));
var hashed = window.location.hash.slice(1);
if (searchTerm != 'null') {
tracking(searchTerm, hashed);
}There was also a hidden link in the HTML:
<a id="tracker" href="javascript:alert(1)" hidden></a>Step 2: What the code is doing
After reading it carefully, here's what's happening:
?search=...→ sets the href of the link#...→ selects an element by ID and clicks it
So basically:
- It takes my input and sets it as a link destination
- Then it clicks an element based on the hash
Step 3: First attempts (failed)
I tried:
?search=javascript:alert(1)Nothing happened.
Then I realized: The code also needs a hash, otherwise nothing gets clicked
So I tried:
?search=javascript:alert(1)#trackerStill nothing… that confused me.
Step 4: Testing if code works
To debug, I tried:
?search=TEST#trackerThen in console:
document.getElementById('tracker').href
It showed "TEST" → so the code is working.
Then I manually triggered:
document.getElementById('tracker').click()Still no alert.
So the issue wasn't the logic — it was the payload.
Step 5: Understanding the problem
After some research, I realized:
- Browsers sometimes block
javascript:URLs when set dynamically - That's why
javascript:alert(1)didn't execute
But normal URLs worked:
?search=https://google.com#trackerThis redirected successfully
So the functionality was correct — only the payload behavior was tricky.
Step 6: The important realization
I noticed something very important:
When I typed the payload in the input field, the # became:
%23So the URL looked like:
?search=javascript:alert(1)%23trackerAnd that breaks everything because:
%23is just text- It is NOT treated as a real hash
So:
window.location.hash becomes empty
No element gets clicked
No XSS
Step 7: The correct approach
When I typed the payload directly in the URL bar:
?search=javascript:alert(1)#trackerNow:
search=javascript:alert(1)hash=tracker
So:
- The link's href becomes
javascript:alert(1) - The script clicks the element with id
tracker - The JavaScript executes


XSS triggered
Step 8: Why the hash is critical
This line is the key:
document.getElementById(hash).click();If there is no hash:
hash = ""- No element found
- No click
- No execution
If there is a hash:
- It finds the element
- Click happens
- Payload executes
Step 9: What I learned

Final Payload
?search=javascript:alert(1)#trackerImportant: Type it directly in the URL bar
Big Takeaway
Whenever you see:
window.location.search→ controls inputwindow.location.hash→ controls behavior
Both are user-controlled inputs
Also:
The way you deliver the payload (URL vs input field) can completely change the result.
Alright, that's it for this today. See you in the next one