I'm trying to protect my code from XSS. I used a tool to identify risks and it alerted the following code part as a possible injection case.
var urlParams = new URLSearchParams(window.location.search);
var param = urlParams.get('param');
var newUrl = "/" + param + "/goto";
document.write("<a href="+newUrl+">Link</a>");
I played a little bit around with some payloads but I was not able to break out and inject any code which is executed*. I wonder if this was a false positive or did I just missed a payload which executes code?
Also, in the course of this I have changed my code a little to
var param = window.location.search.split('param=')[1];
I noticed that in the latter case the parameter is url-encoded, whereas this is not the case in the first example.
Does this happen with the split() method? I want to understand the differences.
Example with ?param="; alert(1);
First case: console.log(param) prints "; alert(1);
Second case: console.log(param) prints %22;%20alert(1);
*Update: I was able to find two payloads that work:
\\"<svg/onload=alert(1)>
</script><script>alert(1);</script>
But why doesn't they work for window.location.search.split('param=')[1]? It is save to just use this approach instead of the first one or are there possible payloads to bypass, too?
newURL
which includes a user defined and unchecked value. This assignment by itself is not a problem, relevant is instead hownewURL
will be used after this assignment. But you don't show this part and thus the question cannot be answered.