Skip to content

Commit

Permalink
[Fix] jsx-no-target-blank: allow no-referrer without noopener b…
Browse files Browse the repository at this point in the history
…y default

Fixes #2022.
  • Loading branch information
seancrater authored and ljharb committed Nov 12, 2018
1 parent 3385caa commit b9d2eb5
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -176,7 +176,7 @@ Enable the rules that you would like to use.
* [react/jsx-no-duplicate-props](docs/rules/jsx-no-duplicate-props.md): Enforce no duplicate props
* [react/jsx-no-literals](docs/rules/jsx-no-literals.md): Prevent using string literals in React component definition
* [react/jsx-no-script-url](docs/rules/jsx-no-script-url.md): Forbid `javascript:` URLs
* [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md): Forbid target="_blank" attribute without rel="noopener noreferrer"
* [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md): Forbid `target="_blank"` attribute without `rel="noreferrer"`
* [react/jsx-no-undef](docs/rules/jsx-no-undef.md): Disallow undeclared variables in JSX
* [react/jsx-no-useless-fragment](docs/rules/jsx-no-useless-fragment.md): Disallow unnecessary fragments (fixable)
* [react/jsx-one-expression-per-line](docs/rules/jsx-one-expression-per-line.md): Limit to one expression per line in JSX (fixable)
Expand Down
9 changes: 5 additions & 4 deletions docs/rules/jsx-no-target-blank.md
Expand Up @@ -2,14 +2,14 @@

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))
This rules requires that you accompany `target='_blank'` attributes with `rel='noreferrer noopener'`.
attribute unaccompanied by `rel='noreferrer'`, however, is a severe
security vulnerability ([see here for more details](https://html.spec.whatwg.org/multipage/links.html#link-type-noopener))
This rules requires that you accompany `target='_blank'` attributes with `rel='noreferrer'`.

## Rule Details

This rule aims to prevent user generated links from creating security vulnerabilities by requiring
`rel='noreferrer noopener'` for external links, and optionally any dynamically generated links.
`rel='noreferrer'` for external links, and optionally any dynamically generated links.

## Rule Options
```json
Expand Down Expand Up @@ -39,6 +39,7 @@ The following patterns are **not** considered errors:

```jsx
var Hello = <p target="_blank"></p>
var Hello = <a target="_blank" rel="noreferrer" href="http://example.com"></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>
Expand Down
8 changes: 4 additions & 4 deletions lib/rules/jsx-no-target-blank.js
Expand Up @@ -53,7 +53,7 @@ function hasSecureRel(element, allowReferrer) {
attr.value.expression.value
));
const tags = value && value.toLowerCase && value.toLowerCase().split(' ');
return tags && tags.indexOf('noopener') >= 0 && (allowReferrer || tags.indexOf('noreferrer') >= 0);
return tags && (allowReferrer ? tags.indexOf('noopener') >= 0 : tags.indexOf('noreferrer') >= 0);
}
return false;
});
Expand All @@ -62,7 +62,7 @@ function hasSecureRel(element, allowReferrer) {
module.exports = {
meta: {
docs: {
description: 'Forbid target="_blank" attribute without rel="noopener noreferrer"',
description: 'Forbid `target="_blank"` attribute without `rel="noreferrer"`',
category: 'Best Practices',
recommended: true,
url: docsUrl('jsx-no-target-blank')
Expand Down Expand Up @@ -102,8 +102,8 @@ module.exports = {
if (hasExternalLink(node.parent, linkAttribute) || (enforceDynamicLinks === 'always' && hasDynamicLink(node.parent, linkAttribute))) {
context.report({
node,
message: 'Using target="_blank" without rel="noopener noreferrer" ' +
'is a security risk: see https://mathiasbynens.github.io/rel-noopener'
message: 'Using target="_blank" without rel="noreferrer" ' +
'is a security risk: see https://html.spec.whatwg.org/multipage/links.html#link-type-noopener'
});
}
}
Expand Down
18 changes: 16 additions & 2 deletions tests/lib/rules/jsx-no-target-blank.js
Expand Up @@ -26,8 +26,8 @@ const parserOptions = {

const ruleTester = new RuleTester({parserOptions});
const defaultErrors = [{
message: 'Using target="_blank" without rel="noopener noreferrer" is a security risk:' +
' see https://mathiasbynens.github.io/rel-noopener'
message: 'Using target="_blank" without rel="noreferrer" is a security risk:' +
' see https://html.spec.whatwg.org/multipage/links.html#link-type-noopener'
}];

ruleTester.run('jsx-no-target-blank', rule, {
Expand All @@ -36,18 +36,29 @@ ruleTester.run('jsx-no-target-blank', rule, {
{code: '<a randomTag></a>'},
{code: '<a target />'},
{code: '<a href="foobar" target="_blank" rel="noopener noreferrer"></a>'},
{code: '<a href="foobar" target="_blank" rel="noreferrer"></a>'},
{code: '<a href="foobar" target="_blank" rel={"noopener noreferrer"}></a>'},
{code: '<a href="foobar" target="_blank" rel={"noreferrer"}></a>'},
{code: '<a href={"foobar"} target={"_blank"} rel={"noopener noreferrer"}></a>'},
{code: '<a href={"foobar"} target={"_blank"} rel={"noreferrer"}></a>'},
{code: '<a href={\'foobar\'} target={\'_blank\'} rel={\'noopener noreferrer\'}></a>'},
{code: '<a href={\'foobar\'} target={\'_blank\'} rel={\'noreferrer\'}></a>'},
{code: '<a href={`foobar`} target={`_blank`} rel={`noopener noreferrer`}></a>'},
{code: '<a href={`foobar`} target={`_blank`} rel={`noreferrer`}></a>'},
{code: '<a target="_blank" {...spreadProps} rel="noopener noreferrer"></a>'},
{code: '<a target="_blank" {...spreadProps} rel="noreferrer"></a>'},
{code: '<a {...spreadProps} target="_blank" rel="noopener noreferrer" href="http://example.com">s</a>'},
{code: '<a {...spreadProps} target="_blank" rel="noreferrer" href="http://example.com">s</a>'},
{code: '<a target="_blank" rel="noopener noreferrer" {...spreadProps}></a>'},
{code: '<a target="_blank" rel="noreferrer" {...spreadProps}></a>'},
{code: '<p target="_blank"></p>'},
{code: '<a href="foobar" target="_BLANK" rel="NOOPENER noreferrer"></a>'},
{code: '<a href="foobar" target="_BLANK" rel="NOREFERRER"></a>'},
{code: '<a target="_blank" rel={relValue}></a>'},
{code: '<a target={targetValue} rel="noopener noreferrer"></a>'},
{code: '<a target={targetValue} rel="noreferrer"></a>'},
{code: '<a target={targetValue} rel={"noopener noreferrer"}></a>'},
{code: '<a target={targetValue} rel={"noreferrer"}></a>'},
{code: '<a target={targetValue} href="relative/path"></a>'},
{code: '<a target={targetValue} href="/absolute/path"></a>'},
{code: '<a target={\'targetValue\'} href="/absolute/path"></a>'},
Expand Down Expand Up @@ -89,6 +100,9 @@ ruleTester.run('jsx-no-target-blank', rule, {
}, {
code: '<a target="_blank" rel="noopenernoreferrer" href="http://example.com"></a>',
errors: defaultErrors
}, {
code: '<a target="_blank" rel="no referrer" href="http://example.com"></a>',
errors: defaultErrors
}, {
code: '<a target="_BLANK" href="http://example.com"></a>',
errors: defaultErrors
Expand Down

0 comments on commit b9d2eb5

Please sign in to comment.