1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 | const docsUrl = require('../util/docsUrl');
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | 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;
|
17 |
|
18 | function hasJavaScriptProtocol(attr) {
|
19 | return attr.value.type === 'Literal'
|
20 | && isJavaScriptProtocol.test(attr.value.value);
|
21 | }
|
22 |
|
23 | function shouldVerifyElement(node, config) {
|
24 | const name = node.name && node.name.name;
|
25 | return name === 'a' || config.find((i) => i.name === name);
|
26 | }
|
27 |
|
28 | function shouldVerifyProp(node, config) {
|
29 | const name = node.name && node.name.name;
|
30 | const parentName = node.parent.name && node.parent.name.name;
|
31 |
|
32 | if (parentName === 'a' && name === 'href') {
|
33 | return true;
|
34 | }
|
35 |
|
36 | const el = config.find((i) => i.name === parentName);
|
37 | if (!el) {
|
38 | return false;
|
39 | }
|
40 |
|
41 | const props = el.props || [];
|
42 | return node.name && props.indexOf(name) !== -1;
|
43 | }
|
44 |
|
45 | module.exports = {
|
46 | meta: {
|
47 | docs: {
|
48 | description: 'Forbid `javascript:` URLs',
|
49 | category: 'Best Practices',
|
50 | recommended: false,
|
51 | url: docsUrl('jsx-no-script-url')
|
52 | },
|
53 | schema: [{
|
54 | type: 'array',
|
55 | uniqueItems: true,
|
56 | items: {
|
57 | type: 'object',
|
58 | properties: {
|
59 | name: {
|
60 | type: 'string'
|
61 | },
|
62 | props: {
|
63 | type: 'array',
|
64 | items: {
|
65 | type: 'string',
|
66 | uniqueItems: true
|
67 | }
|
68 | }
|
69 | },
|
70 | required: ['name', 'props'],
|
71 | additionalProperties: false
|
72 | }
|
73 | }]
|
74 | },
|
75 |
|
76 | create(context) {
|
77 | const config = context.options[0] || [];
|
78 | return {
|
79 | JSXAttribute(node) {
|
80 | const parent = node.parent;
|
81 | if (shouldVerifyElement(parent, config) && shouldVerifyProp(node, config) && hasJavaScriptProtocol(node)) {
|
82 | context.report({
|
83 | node,
|
84 | message: 'A future version of React will block javascript: URLs as a security precaution. '
|
85 | + 'Use event handlers instead if you can. If you need to generate unsafe HTML, try using dangerouslySetInnerHTML instead.'
|
86 | });
|
87 | }
|
88 | }
|
89 | };
|
90 | }
|
91 | };
|