From the Angular security guide, there's this:
To block XSS attacks, you must prevent malicious code from entering
the DOM (Document Object Model). For example, if attackers can trick
you into inserting a tag in the DOM, they can run arbitrary
code on your website. The attack isn't limited to tags—many
elements and properties in the DOM allow code execution, for example,
<img onerror="...">
and <a href="javascript:...">
. If
attacker-controlled data enters the DOM, expect security
vulnerabilities.
I've sometimes used <a href="javascript:" (click)="someFunction()">link</a>
to target the element with CSS selectors (a:link
) without the link referencing a URI, anchor, or running any code.
Is this a dangerous practice? They don't really give an example of how this could be exploited.
And if this is bad practice, then here's my dilemma: If I have a series of links in a nav, some of them ARE HREFs, and some of them bind to JS, but I want them all to look the same and use the same CSS selectors. Is there an easy way to accomplish that?
Try adding an empty href
for links that has (click)
<a (click)="action()" href>Previous</a>
If it doesn't work, you can try
<a href (click)="doSomething(); $event.preventDefault()">Link</a>
<a href (click)="!!doSomething()">Link</a>
<a href (click)="doSomething(); false">Link</a>
What you are doing is fine.
This:
<a href="javascript:" (click)="someFunction()">link</a>
...is not an immediate security risk because you are not templateizing anything in your href
.
This:
<a href="javascript:{{someVariable}}" (click)="someFunction()">link</a>
...is a security risk, because the someVariable
value can be something malicious that was entered by a user and will now get executed on click.
That being said, why do you need to use href="javascript:"
at all? Just use an Angular (click)
event and call preventDefault()
on the event object to stop it from doing that behavior you described.
<a (click)="doSomething($event)"><a/>
doSomething(event: any) {
event.preventDefault();
}
Update
Scott Marcus makes some good points. You really shouldn't use an a
element here at all because it requires some workarounds (such as the preventDefault()
. The best tool in the toolbox here is a span
.
Use it like so:
<span (click)="doSomething()"></span>