Skip to content

Commit

Permalink
Don't issue errors for <a/> with target=_blank and non-external URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
gfx committed May 22, 2017
1 parent a8d4c9b commit 7c45509
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
8 changes: 5 additions & 3 deletions docs/rules/jsx-no-target-blank.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Prevent usage of unsafe `target='_blank'` (react/jsx-no-target-blank)

When creating a JSX element that has an a tag, it is often desired to have
When creating a JSX element that has an `a` tag, it is often desired to have
the link open in a new tab using the `target='_blank'` attribute. Using this
attribute unaccompanied by `rel='noreferrer noopener'`, however, is a severe
security vulnerability ([see here for more details](https://mathiasbynens.github.io/rel-noopener))
Expand All @@ -11,14 +11,16 @@ This rules requires that you accompany all `target='_blank'` attributes with `re
The following patterns are considered errors:

```jsx
var Hello = <a target='_blank'></a>
var Hello = <a target='_blank' href="http://example.com/"></a>
```

The following patterns are not considered errors:

```jsx
var Hello = <p target='_blank'></p>
var Hello = <a target='_blank' rel='noopener noreferrer'></a>
var Hello = <a target='_blank' rel='noopener noreferrer' href="http://example.com"></a>
var Hello = <a target='_blank' href="relative/path/in/the/host"></a>
var Hello = <a target='_blank' href="/absolute/path/in/the/host"></a>
var Hello = <a></a>
```

Expand Down
17 changes: 15 additions & 2 deletions lib/rules/jsx-no-target-blank.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,21 @@ module.exports = {
var relFound = false;
var attrs = node.parent.attributes;
for (var idx in attrs) {
if (attrs[idx].name && attrs[idx].name.name === 'rel') {
var tags = attrs[idx].value.type === 'Literal' && attrs[idx].value.value.toLowerCase().split(' ');
if (!Object.prototype.hasOwnProperty.call(attrs, idx)) {
continue;
}
var attr = attrs[idx];
if (!attr.name) {
continue;
}
if (attr.name.name === 'href') {
if (attr.value.type === 'Literal' && !/^\w+:/.test(attr.value.value)) {
// it's safe because it is not an external link (i.e. doesn't start with a protocol)
return;
}
}
if (attr.name.name === 'rel') {
var tags = attr.value.type === 'Literal' && attr.value.value.toLowerCase().split(' ');
if (!tags || (tags.indexOf('noopener') >= 0 && tags.indexOf('noreferrer') >= 0)) {
relFound = true;
break;
Expand Down
12 changes: 7 additions & 5 deletions tests/lib/rules/jsx-no-target-blank.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,30 @@ ruleTester.run('jsx-no-target-blank', rule, {
{code: '<p target="_blank"></p>'},
{code: '<a href="foobar" target="_BLANK" rel="NOOPENER noreferrer"></a>'},
{code: '<a target="_blank" rel={relValue}></a>'},
{code: '<a target={targetValue} rel="noopener noreferrer"></a>'}
{code: '<a target={targetValue} rel="noopener noreferrer"></a>'},
{code: '<a target={targetValue} href="relative/path"></a>'},
{code: '<a target={targetValue} href="/absolute/path"></a>'}
],
invalid: [{
code: '<a target="_blank"></a>',
code: '<a target="_blank" href="http://example.com"></a>',
errors: [{
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
' see https://mathiasbynens.github.io/rel-noopener'
}]
}, {
code: '<a target="_blank" rel=""></a>',
code: '<a target="_blank" rel="" href="http://example.com"></a>',
errors: [{
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
' see https://mathiasbynens.github.io/rel-noopener'
}]
}, {
code: '<a target="_blank" rel="noopenernoreferrer"></a>',
code: '<a target="_blank" rel="noopenernoreferrer" href="http://example.com"></a>',
errors: [{
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
' see https://mathiasbynens.github.io/rel-noopener'
}]
}, {
code: '<a target="_BLANK"></a>',
code: '<a target="_BLANK" href="http://example.com"></a>',
errors: [{
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
' see https://mathiasbynens.github.io/rel-noopener'
Expand Down

0 comments on commit 7c45509

Please sign in to comment.