diff --git a/CHANGELOG.md b/CHANGELOG.md
index 561a9e2a6a..218f0d5197 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,7 +14,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
* [`display-name`]/component detection: avoid a crash on anonymous components ([#2840][] @ljharb)
* [`prop-types`]: function in class that returns a component causes false warning in typescript ([#2843][] @SyMind)
* [`jsx-no-target-blank`]: avoid a crash with a non-string literal ([#2851][] @ljharb)
+* [`jsx-no-script-url`]: avoid crash with boolean `href` ([#2871][] @ljharb)
+[#2871]: https://github.com/yannickcr/eslint-plugin-react/issues/2871
[#2851]: https://github.com/yannickcr/eslint-plugin-react/issues/2851
[#2843]: https://github.com/yannickcr/eslint-plugin-react/pull/2843
[#2840]: https://github.com/yannickcr/eslint-plugin-react/issues/2840
diff --git a/lib/rules/jsx-no-script-url.js b/lib/rules/jsx-no-script-url.js
index 6e42f93df4..97c0cc53ce 100644
--- a/lib/rules/jsx-no-script-url.js
+++ b/lib/rules/jsx-no-script-url.js
@@ -16,7 +16,7 @@ const docsUrl = require('../util/docsUrl');
const isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i;
function hasJavaScriptProtocol(attr) {
- return attr.value.type === 'Literal'
+ return attr.value && attr.value.type === 'Literal'
&& isJavaScriptProtocol.test(attr.value.value);
}
diff --git a/tests/lib/rules/jsx-no-script-url.js b/tests/lib/rules/jsx-no-script-url.js
index ea820e9d2d..471f19d39f 100644
--- a/tests/lib/rules/jsx-no-script-url.js
+++ b/tests/lib/rules/jsx-no-script-url.js
@@ -37,7 +37,8 @@ ruleTester.run('jsx-no-script-url', rule, {
{code: ''},
{code: ''},
{code: ''},
- {code: ''}
+ {code: ''},
+ {code: ''}
],
invalid: [{
code: '',