UNPKG

4.96 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = function (d, b) {
4 extendStatics = Object.setPrototypeOf ||
5 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7 return extendStatics(d, b);
8 }
9 return function (d, b) {
10 extendStatics(d, b);
11 function __() { this.constructor = d; }
12 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13 };
14})();
15Object.defineProperty(exports, "__esModule", { value: true });
16var ts = require("typescript");
17var Lint = require("tslint");
18var tsutils = require("tsutils");
19var Utils_1 = require("./utils/Utils");
20var JsxAttribute_1 = require("./utils/JsxAttribute");
21var OPTION_FORCE_REL_REDUNDANCY = 'force-rel-redundancy';
22var Rule = (function (_super) {
23 __extends(Rule, _super);
24 function Rule() {
25 return _super !== null && _super.apply(this, arguments) || this;
26 }
27 Rule.prototype.apply = function (sourceFile) {
28 if (sourceFile.languageVariant === ts.LanguageVariant.JSX) {
29 return this.applyWithFunction(sourceFile, walk, this.parseOptions(this.getOptions()));
30 }
31 else {
32 return [];
33 }
34 };
35 Rule.prototype.parseOptions = function (options) {
36 var parsed = {
37 forceRelRedundancy: false
38 };
39 if (options.ruleArguments !== undefined && options.ruleArguments.length > 0) {
40 parsed.forceRelRedundancy = options.ruleArguments.indexOf(OPTION_FORCE_REL_REDUNDANCY) > -1;
41 }
42 return parsed;
43 };
44 Rule.metadata = {
45 ruleName: 'react-anchor-blank-noopener',
46 type: 'functionality',
47 description: 'Anchor tags with target="_blank" should also include rel="noreferrer"',
48 options: {
49 type: 'array',
50 items: {
51 type: 'string',
52 enum: [OPTION_FORCE_REL_REDUNDANCY]
53 },
54 minLength: 0,
55 maxLength: 1
56 },
57 optionsDescription: "One argument may be optionally provided: \n\n' +\n '* `" + OPTION_FORCE_REL_REDUNDANCY + "` ignores the default `rel=\"noreferrer\"`\n behaviour which implies `rel=\"noreferrer noopener\"`. Instead, force redundancy\n for `rel` attribute.",
58 typescriptOnly: true,
59 issueClass: 'SDL',
60 issueType: 'Error',
61 severity: 'Critical',
62 level: 'Mandatory',
63 group: 'Security',
64 commonWeaknessEnumeration: '242,676'
65 };
66 return Rule;
67}(Lint.Rules.AbstractRule));
68exports.Rule = Rule;
69function walk(ctx) {
70 var failureString = ctx.options.forceRelRedundancy
71 ? 'Anchor tags with target="_blank" should also include rel="noopener noreferrer"'
72 : 'Anchor tags with target="_blank" should also include rel="noreferrer"';
73 function validateOpeningElement(openingElement) {
74 if (openingElement.tagName.getText() === 'a') {
75 var allAttributes = JsxAttribute_1.getJsxAttributesFromJsxElement(openingElement);
76 var target = allAttributes['target'];
77 var rel = allAttributes['rel'];
78 if (target !== undefined &&
79 JsxAttribute_1.getStringLiteral(target) === '_blank' &&
80 !isRelAttributeValue(rel, ctx.options.forceRelRedundancy)) {
81 ctx.addFailureAt(openingElement.getStart(), openingElement.getWidth(), failureString);
82 }
83 }
84 }
85 function cb(node) {
86 if (tsutils.isJsxElement(node)) {
87 validateOpeningElement(node.openingElement);
88 }
89 else if (tsutils.isJsxSelfClosingElement(node)) {
90 validateOpeningElement(node);
91 }
92 return ts.forEachChild(node, cb);
93 }
94 return ts.forEachChild(ctx.sourceFile, cb);
95}
96function isRelAttributeValue(attribute, forceRedundancy) {
97 if (JsxAttribute_1.isEmpty(attribute)) {
98 return false;
99 }
100 if (attribute.initializer !== undefined && attribute.initializer.kind === ts.SyntaxKind.JsxExpression) {
101 var expression = attribute.initializer;
102 if (expression.expression !== undefined && expression.expression.kind !== ts.SyntaxKind.StringLiteral) {
103 return true;
104 }
105 }
106 var stringValue = JsxAttribute_1.getStringLiteral(attribute);
107 if (stringValue === undefined || stringValue.length === 0) {
108 return false;
109 }
110 var relValues = stringValue.split(/\s+/);
111 return forceRedundancy
112 ? Utils_1.Utils.contains(relValues, 'noreferrer') && Utils_1.Utils.contains(relValues, 'noopener')
113 : Utils_1.Utils.contains(relValues, 'noreferrer');
114}
115//# sourceMappingURL=reactAnchorBlankNoopenerRule.js.map
\No newline at end of file