The link displayed in the bottom of the web browser window, when you hover over the link, can not be trusted.
Google has been doing it for ages. You can reproduce it on Firefox: Just search for something on Google, then hover over the link. The link will say it goes directly to the website. Then right click the link and dismiss the menu. Now hover over it again. The link has changed to a Google tracker URL. It’s shady and it’s not okay, and in my eyes, it is a UI bug / exploit that needs to be fixed in the browsers. Links shouldn’t change right under your nose.
This is a feature that all browsers had for ages: “Disable Javascript”.
The whole concept of running arbitrary code on client side is a feature, and it means that you can run any arbitrary code on client side. The browser has no way of knowing which snippet is good or bad.
You can argue that this specific case is obviously malicious, and should be treated explicitly, but you would have two major issues:
You cannot treat this without breaking something else (changing href attribute is a valid usage)
You will soon have to treat billions of other “malicious cases” (changing content based on user-agent, hiding content, …)
And anyway, people will find a way to break through, for example by making calls to an analysis website on load, or event replace the current page with the target link passed through an analysis website.
The only safe way to counter this is to disable javascript, or at least, ask the user for the right to run it (though this will only get in the way…).
But the browser could kill the whole pattern by changing the order of execution. Currently execution flow looks like
Detect click from operating system
Run javascript
If click is on a href, go to link
Just change the order of 2 and 3. The browser controls the javascript vm. There is no reason it needs to let it run between detecting the click and checking for href’s.
Legitimate patterns that need the onclick to run before going to a link can still work, they just need to follow the link in js instead of doing it through the href element, which will avoid the browser displaying the contents of the false original link at the bottom of the page.
Running the code after following the link means giving the priority to the element themselves rather than the code.
That would indeed fix the issue for “malicious” links, but it would kill a whole lot of other (legitimate) stuff.
Take as an example someone filling a form, and submitting it from a link. The onClick event can be used to check user input before submitting anything, and cancel the submission if, eg. one field is not filled, or incorrect.
By running the JS after following the link, you simply prevent the process. And I can barely imagine a (valid!) use-case with onClick that would work as intended if the code is run after the link is followed.
For forms, the url isn’t displayed by the browser so this change isn’t needed.
But, let’s pretend that it was so we can use your example. The “fix” for making on-click continue to be useful would be as simple as removing the url from the html attribute, and instead passing it to the javascript, then the javascript could load the url (or send the post request) after validating the input. The only difference here is the url isn’t part of the element, so the browser doesn’t display it.
Interestingly, there exists a ping attribute on the a element, which would facilitate click tracking without sneakily changing the link with JavaScript. Google uses it on their search results, but only if you’re using Chrome. On Firefox, it appears to use <a onmousedown> instead, which would be responsible for the swap. The ping attribute is supported on Firefox, but it’s not enabled by default. It is on Chrome, though. Hmm.
Google has been doing it for ages. You can reproduce it on Firefox: Just search for something on Google, then hover over the link. The link will say it goes directly to the website. Then right click the link and dismiss the menu. Now hover over it again. The link has changed to a Google tracker URL. It’s shady and it’s not okay, and in my eyes, it is a UI bug / exploit that needs to be fixed in the browsers. Links shouldn’t change right under your nose.
This is a feature that all browsers had for ages: “Disable Javascript”.
The whole concept of running arbitrary code on client side is a feature, and it means that you can run any arbitrary code on client side. The browser has no way of knowing which snippet is good or bad.
You can argue that this specific case is obviously malicious, and should be treated explicitly, but you would have two major issues:
href
attribute is a valid usage)And anyway, people will find a way to break through, for example by making calls to an analysis website on load, or event replace the current page with the target link passed through an analysis website.
The only safe way to counter this is to disable javascript, or at least, ask the user for the right to run it (though this will only get in the way…).
But the browser could kill the whole pattern by changing the order of execution. Currently execution flow looks like
Just change the order of 2 and 3. The browser controls the javascript vm. There is no reason it needs to let it run between detecting the click and checking for href’s.
Legitimate patterns that need the onclick to run before going to a link can still work, they just need to follow the link in js instead of doing it through the href element, which will avoid the browser displaying the contents of the false original link at the bottom of the page.
Running the code after following the link means giving the priority to the element themselves rather than the code. That would indeed fix the issue for “malicious” links, but it would kill a whole lot of other (legitimate) stuff.
Take as an example someone filling a form, and submitting it from a link. The
onClick
event can be used to check user input before submitting anything, and cancel the submission if, eg. one field is not filled, or incorrect.By running the JS after following the link, you simply prevent the process. And I can barely imagine a (valid!) use-case with
onClick
that would work as intended if the code is run after the link is followed.For forms, the url isn’t displayed by the browser so this change isn’t needed.
But, let’s pretend that it was so we can use your example. The “fix” for making on-click continue to be useful would be as simple as removing the url from the html attribute, and instead passing it to the javascript, then the javascript could load the url (or send the post request) after validating the input. The only difference here is the url isn’t part of the element, so the browser doesn’t display it.
You find this out the hard way when you want to simply copy a link from google, only to paste a load of tracking horseshit
First, I agree with what you said, that this is not OK.
But how would you fix this in a way that doesn’t break legitimate uses of onClick?
Interestingly, there exists a
ping
attribute on thea
element, which would facilitate click tracking without sneakily changing the link with JavaScript. Google uses it on their search results, but only if you’re using Chrome. On Firefox, it appears to use<a onmousedown>
instead, which would be responsible for the swap. Theping
attribute is supported on Firefox, but it’s not enabled by default. It is on Chrome, though. Hmm.