What is the subtraction operator -
used for in JavaScript, other than math?
This is a strange question, but it’s not the real question you’re asking here.
I’m having a hard time to understand how the alert is being raised.
This is the actual concern.
If you don’t understand how a process like this works, it helps to go through it step by step.
Look at the first line:
let jeff = (new URL(location).searchParams.get("jeff") || "No parameters.");
The URL
constructor stringifies its first argument and parses it as a URL.
location
is the object that holds information about the current page’s URL.
It’s stringified as the full URL.
The searchParams
property is a URLSearchParams
object, which holds all the query parameters of the URL, such as ?jeff=%22-alert(1)-%22
, in a structured, decoded way.
.get("jeff")
attempts to get the value of the jeff
parameter.
Note that URLs are subject to encoding.
%22
is the percent encoding of the quote character "
; %2B
is the percent encoding of the plus character +
; +
is the URL encoding of a single space
; and so on.
The || "No parameters."
defaults to the string "No parameters."
if the jeff
parameter is empty or not present.
If your location is https://example.com/?jeff=%22-alert(1)-%22
The result, which is assigned to the variable jeff
, is '"-alert(1)-"'
.
Second line:
eval(`ma = "Ma name ${jeff}"`);
`ma = "Ma name ${jeff}"`
is a template literal which interpolates the variable jeff
into the rest of the string; the resulting string is 'ma = "Ma name "-alert(1)-""'
.
eval
executes strings as code.
So, effectively, this line says: ma = "Ma name "-alert(1)-""
(or somewhat cleaner: ma = "Ma name " - alert(1) - "";
).
This subtracts alert(1)
from "Ma name "
, and then subtracts ""
from that intermediate result.
In order to evaluate this, alert(1)
is executed.
That’s how the alert
window appears.
Both the intermediate and the final result are NaN
, because they involve the return value from the alert
, namely undefined
.
NaN
is then assigned to the variable ma
.
Third line:
document.write(ma)
This just writes the resulting NaN
(as the string "NaN"
) into the open document stream (or, if closed, opens a new one, then writes into it).
Run this snippet to examine the intermediate results.
Note that the eval
and the reference to the real location
have been removed in the snippet; this is just to give you a general idea of how intermediate results might be examined.
const locationHref = "https://example.com/?jeff=%22-alert(1)-%22",
urlObject = new URL(locationHref),
searchParams = urlObject.searchParams,
jeffParameter = searchParams.get("jeff"),
jeff = jeffParameter || "No parameters.",
jeffIfNotFound = null || "No parameters.",
interpolatedString = `ma = "Ma name ${jeff}"`;
console.log({
locationHref,
urlObject,
searchParams, // Look at this in your browser console; the Stack Snippet doesn’t show a very useful representation.
jeffParameter,
jeff,
jeffIfNotFound,
interpolatedString
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
Back to your first question:
What is the subtraction operator -
used for in JavaScript, other than math?
There is nothing special about -
in this code.
Try any of the operators in this query string: ?jeff=%22**alert(1)/alert(1)*alert(1)>>>~alert(1)^alert(1)===alert(1)||!alert(1)<%22
, and many more; this’ll alert six times with the meaningless result 1
.
The Subtraction Operator is only used for math.
Any other application is either a hack or meaningless.
Actually, I tried other operators like plus (+
)
But you didn’t URL-encode it correctly.
new URLSearchParams("jeff=a+b").get("jeff"); // Result: "a b".
new URLSearchParams("jeff=a%2Bb").get("jeff"); // Result: "a+b".
new URLSearchParams("jeff=a%2Bb%25c%26%26d").get("jeff"); // Result: "a+b%c&&d".
The +
works just the same way.
The important thing is that functions will execute in order to be evaluated.
If they’re somewhere in the middle of operators, then they’re the operands which will be evaluated; it doesn’t matter which operators are used (unless they’re short-circuiting, in which case evaluation may be skipped).