Skip to content

Commit 7c45509

Browse files
committed
Don't issue errors for <a/> with target=_blank and non-external URLs
1 parent a8d4c9b commit 7c45509

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

docs/rules/jsx-no-target-blank.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Prevent usage of unsafe `target='_blank'` (react/jsx-no-target-blank)
22

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

1313
```jsx
14-
var Hello = <a target='_blank'></a>
14+
var Hello = <a target='_blank' href="http://example.com/"></a>
1515
```
1616

1717
The following patterns are not considered errors:
1818

1919
```jsx
2020
var Hello = <p target='_blank'></p>
21-
var Hello = <a target='_blank' rel='noopener noreferrer'></a>
21+
var Hello = <a target='_blank' rel='noopener noreferrer' href="http://example.com"></a>
22+
var Hello = <a target='_blank' href="relative/path/in/the/host"></a>
23+
var Hello = <a target='_blank' href="/absolute/path/in/the/host"></a>
2224
var Hello = <a></a>
2325
```
2426

lib/rules/jsx-no-target-blank.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,21 @@ module.exports = {
3333
var relFound = false;
3434
var attrs = node.parent.attributes;
3535
for (var idx in attrs) {
36-
if (attrs[idx].name && attrs[idx].name.name === 'rel') {
37-
var tags = attrs[idx].value.type === 'Literal' && attrs[idx].value.value.toLowerCase().split(' ');
36+
if (!Object.prototype.hasOwnProperty.call(attrs, idx)) {
37+
continue;
38+
}
39+
var attr = attrs[idx];
40+
if (!attr.name) {
41+
continue;
42+
}
43+
if (attr.name.name === 'href') {
44+
if (attr.value.type === 'Literal' && !/^\w+:/.test(attr.value.value)) {
45+
// it's safe because it is not an external link (i.e. doesn't start with a protocol)
46+
return;
47+
}
48+
}
49+
if (attr.name.name === 'rel') {
50+
var tags = attr.value.type === 'Literal' && attr.value.value.toLowerCase().split(' ');
3851
if (!tags || (tags.indexOf('noopener') >= 0 && tags.indexOf('noreferrer') >= 0)) {
3952
relFound = true;
4053
break;

tests/lib/rules/jsx-no-target-blank.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,30 @@ ruleTester.run('jsx-no-target-blank', rule, {
3535
{code: '<p target="_blank"></p>'},
3636
{code: '<a href="foobar" target="_BLANK" rel="NOOPENER noreferrer"></a>'},
3737
{code: '<a target="_blank" rel={relValue}></a>'},
38-
{code: '<a target={targetValue} rel="noopener noreferrer"></a>'}
38+
{code: '<a target={targetValue} rel="noopener noreferrer"></a>'},
39+
{code: '<a target={targetValue} href="relative/path"></a>'},
40+
{code: '<a target={targetValue} href="/absolute/path"></a>'}
3941
],
4042
invalid: [{
41-
code: '<a target="_blank"></a>',
43+
code: '<a target="_blank" href="http://example.com"></a>',
4244
errors: [{
4345
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
4446
' see https://mathiasbynens.github.io/rel-noopener'
4547
}]
4648
}, {
47-
code: '<a target="_blank" rel=""></a>',
49+
code: '<a target="_blank" rel="" href="http://example.com"></a>',
4850
errors: [{
4951
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
5052
' see https://mathiasbynens.github.io/rel-noopener'
5153
}]
5254
}, {
53-
code: '<a target="_blank" rel="noopenernoreferrer"></a>',
55+
code: '<a target="_blank" rel="noopenernoreferrer" href="http://example.com"></a>',
5456
errors: [{
5557
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
5658
' see https://mathiasbynens.github.io/rel-noopener'
5759
}]
5860
}, {
59-
code: '<a target="_BLANK"></a>',
61+
code: '<a target="_BLANK" href="http://example.com"></a>',
6062
errors: [{
6163
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
6264
' see https://mathiasbynens.github.io/rel-noopener'

0 commit comments

Comments
 (0)