diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts
index dbde8f1b2d..046d6252f3 100644
--- a/src/compiler/compile/nodes/Element.ts
+++ b/src/compiler/compile/nodes/Element.ts
@@ -394,6 +394,26 @@ export default class Element extends Node {
const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
const id_attribute = attribute_map.get('id');
const name_attribute = attribute_map.get('name');
+ const target_attribute = attribute_map.get('target');
+
+ if (target_attribute && target_attribute.get_static_value() === '_blank' && href_attribute) {
+ const href_static_value = href_attribute.get_static_value() ? href_attribute.get_static_value().toLowerCase() : null;
+
+ if (href_static_value === null || href_static_value.startsWith('http') || href_static_value.startsWith('//')) {
+ const rel = attribute_map.get('rel');
+ const rel_values = rel ? rel.get_static_value().split(' ') : [];
+ const expected_values = ['noopener', 'noreferrer'];
+
+ expected_values.forEach(expected_value => {
+ if (!rel || rel && rel_values.indexOf(expected_value) < 0) {
+ component.warn(this, {
+ code: `security-anchor-rel-${expected_value}`,
+ message: `Security: Anchor with "target=_blank" should have rel attribute containing the value "${expected_value}"`
+ });
+ }
+ });
+ }
+ }
if (href_attribute) {
const href_value = href_attribute.get_static_value();
diff --git a/test/validator/samples/security-anchor-rel-noopener/input.svelte b/test/validator/samples/security-anchor-rel-noopener/input.svelte
new file mode 100644
index 0000000000..be146f6676
--- /dev/null
+++ b/test/validator/samples/security-anchor-rel-noopener/input.svelte
@@ -0,0 +1,34 @@
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+Same host (valid)
+
+Same host (valid)
+Same host (valid)
+
+svelte website (valid)
+svelte website (valid)
+
+svelte website (valid)
+svelte website (valid)
+
+svelte website (valid)
+svelte website (valid)
\ No newline at end of file
diff --git a/test/validator/samples/security-anchor-rel-noopener/warnings.json b/test/validator/samples/security-anchor-rel-noopener/warnings.json
new file mode 100644
index 0000000000..6d4c77e7d3
--- /dev/null
+++ b/test/validator/samples/security-anchor-rel-noopener/warnings.json
@@ -0,0 +1,182 @@
+[
+ {
+ "code": "security-anchor-rel-noopener",
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "start": {
+ "line": 2,
+ "column": 0,
+ "character": 54
+ },
+ "end": {
+ "line": 2,
+ "column": 73,
+ "character": 127
+ },
+ "pos": 54
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "start": {
+ "line": 4,
+ "column": 0,
+ "character": 182
+ },
+ "end": {
+ "line": 4,
+ "column": 80,
+ "character": 262
+ },
+ "pos": 182
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "start": {
+ "line": 5,
+ "column": 0,
+ "character": 263
+ },
+ "end": {
+ "line": 5,
+ "column": 90,
+ "character": 353
+ },
+ "pos": 263
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 483,
+ "column": 75,
+ "line": 7
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 408,
+ "start": {
+ "character": 408,
+ "column": 0,
+ "line": 7
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 620,
+ "column": 82,
+ "line": 9
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 538,
+ "start": {
+ "character": 538,
+ "column": 0,
+ "line": 9
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 713,
+ "column": 92,
+ "line": 10
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 621,
+ "start": {
+ "character": 621,
+ "column": 0,
+ "line": 10
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 835,
+ "column": 67,
+ "line": 12
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 768,
+ "start": {
+ "character": 768,
+ "column": 0,
+ "line": 12
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 964,
+ "column": 74,
+ "line": 14
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 890,
+ "start": {
+ "character": 890,
+ "column": 0,
+ "line": 14
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 1049,
+ "column": 84,
+ "line": 15
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 965,
+ "start": {
+ "character": 965,
+ "column": 0,
+ "line": 15
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 1176,
+ "column": 72,
+ "line": 17
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 1104,
+ "start": {
+ "character": 1104,
+ "column": 0,
+ "line": 17
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 1310,
+ "column": 79,
+ "line": 19
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 1231,
+ "start": {
+ "character": 1231,
+ "column": 0,
+ "line": 19
+ }
+ },
+ {
+ "code": "security-anchor-rel-noopener",
+ "end": {
+ "character": 1400,
+ "column": 89,
+ "line": 20
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noopener\"",
+ "pos": 1311,
+ "start": {
+ "character": 1311,
+ "column": 0,
+ "line": 20
+ }
+ }
+]
\ No newline at end of file
diff --git a/test/validator/samples/security-anchor-rel-noreferrer/input.svelte b/test/validator/samples/security-anchor-rel-noreferrer/input.svelte
new file mode 100644
index 0000000000..82248d28ef
--- /dev/null
+++ b/test/validator/samples/security-anchor-rel-noreferrer/input.svelte
@@ -0,0 +1,34 @@
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+svelte website (invalid)
+
+svelte website (invalid)
+svelte website (invalid)
+
+Same host (valid)
+
+Same host (valid)
+Same host (valid)
+
+svelte website (valid)
+svelte website (valid)
+
+svelte website (valid)
+svelte website (valid)
+
+svelte website (valid)
+svelte website (valid)
\ No newline at end of file
diff --git a/test/validator/samples/security-anchor-rel-noreferrer/warnings.json b/test/validator/samples/security-anchor-rel-noreferrer/warnings.json
new file mode 100644
index 0000000000..5581b3e449
--- /dev/null
+++ b/test/validator/samples/security-anchor-rel-noreferrer/warnings.json
@@ -0,0 +1,182 @@
+[
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "start": {
+ "line": 2,
+ "column": 0,
+ "character": 52
+ },
+ "end": {
+ "line": 2,
+ "column": 73,
+ "character": 125
+ },
+ "pos": 52
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "start": {
+ "line": 4,
+ "column": 0,
+ "character": 178
+ },
+ "end": {
+ "line": 4,
+ "column": 80,
+ "character": 258
+ },
+ "pos": 178
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "start": {
+ "line": 5,
+ "column": 0,
+ "character": 259
+ },
+ "end": {
+ "line": 5,
+ "column": 88,
+ "character": 347
+ },
+ "pos": 259
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 475,
+ "column": 75,
+ "line": 7
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 400,
+ "start": {
+ "character": 400,
+ "column": 0,
+ "line": 7
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 610,
+ "column": 82,
+ "line": 9
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 528,
+ "start": {
+ "character": 528,
+ "column": 0,
+ "line": 9
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 701,
+ "column": 90,
+ "line": 10
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 611,
+ "start": {
+ "character": 611,
+ "column": 0,
+ "line": 10
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 821,
+ "column": 67,
+ "line": 12
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 754,
+ "start": {
+ "character": 754,
+ "column": 0,
+ "line": 12
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 948,
+ "column": 74,
+ "line": 14
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 874,
+ "start": {
+ "character": 874,
+ "column": 0,
+ "line": 14
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 1031,
+ "column": 82,
+ "line": 15
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 949,
+ "start": {
+ "character": 949,
+ "column": 0,
+ "line": 15
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 1156,
+ "column": 72,
+ "line": 17
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 1084,
+ "start": {
+ "character": 1084,
+ "column": 0,
+ "line": 17
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 1288,
+ "column": 79,
+ "line": 19
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 1209,
+ "start": {
+ "character": 1209,
+ "column": 0,
+ "line": 19
+ }
+ },
+ {
+ "code": "security-anchor-rel-noreferrer",
+ "end": {
+ "character": 1376,
+ "column": 87,
+ "line": 20
+ },
+ "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"",
+ "pos": 1289,
+ "start": {
+ "character": 1289,
+ "column": 0,
+ "line": 20
+ }
+ }
+]
\ No newline at end of file