diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index dbde8f1b2df8..aa84b1e7e0ad 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.match(/^(https?:)?\/\//i)) { + const rel = attribute_map.get('rel'); + const rel_values = rel ? rel.get_static_value().split(' ') : []; + const expected_values = ['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-noreferrer/input.svelte b/test/validator/samples/security-anchor-rel-noreferrer/input.svelte new file mode 100644 index 000000000000..de52d5a59604 --- /dev/null +++ b/test/validator/samples/security-anchor-rel-noreferrer/input.svelte @@ -0,0 +1,31 @@ +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) +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) +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 000000000000..24c10fb7639c --- /dev/null +++ b/test/validator/samples/security-anchor-rel-noreferrer/warnings.json @@ -0,0 +1,272 @@ +[ + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 73, + "column": 73, + "line": 1 + }, + "pos": 0, + "start": { + "character": 0, + "column": 0, + "line": 1 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 154, + "column": 80, + "line": 2 + }, + "pos": 74, + "start": { + "character": 74, + "column": 0, + "line": 2 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 243, + "column": 88, + "line": 3 + }, + "pos": 155, + "start": { + "character": 155, + "column": 0, + "line": 3 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 319, + "column": 75, + "line": 4 + }, + "pos": 244, + "start": { + "character": 244, + "column": 0, + "line": 4 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 402, + "column": 82, + "line": 5 + }, + "pos": 320, + "start": { + "character": 320, + "column": 0, + "line": 5 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 493, + "column": 90, + "line": 6 + }, + "pos": 403, + "start": { + "character": 403, + "column": 0, + "line": 6 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 561, + "column": 67, + "line": 7 + }, + "pos": 494, + "start": { + "character": 494, + "column": 0, + "line": 7 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 636, + "column": 74, + "line": 8 + }, + "pos": 562, + "start": { + "character": 562, + "column": 0, + "line": 8 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 719, + "column": 82, + "line": 9 + }, + "pos": 637, + "start": { + "character": 637, + "column": 0, + "line": 9 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 792, + "column": 72, + "line": 10 + }, + "pos": 720, + "start": { + "character": 720, + "column": 0, + "line": 10 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 872, + "column": 79, + "line": 11 + }, + "pos": 793, + "start": { + "character": 793, + "column": 0, + "line": 11 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 960, + "column": 87, + "line": 12 + }, + "pos": 873, + "start": { + "character": 873, + "column": 0, + "line": 12 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 1033, + "column": 72, + "line": 13 + }, + "pos": 961, + "start": { + "character": 961, + "column": 0, + "line": 13 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 1113, + "column": 79, + "line": 14 + }, + "pos": 1034, + "start": { + "character": 1034, + "column": 0, + "line": 14 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 1201, + "column": 87, + "line": 15 + }, + "pos": 1114, + "start": { + "character": 1114, + "column": 0, + "line": 15 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 1277, + "column": 75, + "line": 16 + }, + "pos": 1202, + "start": { + "character": 1202, + "column": 0, + "line": 16 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 1360, + "column": 82, + "line": 17 + }, + "pos": 1278, + "start": { + "character": 1278, + "column": 0, + "line": 17 + } + }, + { + "code": "security-anchor-rel-noreferrer", + "message": "Security: Anchor with \"target=_blank\" should have rel attribute containing the value \"noreferrer\"", + "end": { + "character": 1451, + "column": 90, + "line": 18 + }, + "pos": 1361, + "start": { + "character": 1361, + "column": 0, + "line": 18 + } + } +]