Skip to content

Commit 93d3230

Browse files
authored
Merge pull request #81 from javiereguiluz/safer_external_links
Mark external links as unsafe
2 parents 82a2fa3 + 3d0040d commit 93d3230

File tree

5 files changed

+37
-16
lines changed

5 files changed

+37
-16
lines changed

src/Renderers/SpanNodeRenderer.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public function link(?string $url, string $title, array $attributes = []): strin
5252
$this->urlChecker->checkUrl($url);
5353
}
5454

55+
if (!$this->isSafeUrl($url)) {
56+
$attributes['rel'] = 'external noopener noreferrer';
57+
$attributes['target'] = '_blank';
58+
}
59+
5560
return $this->templateRenderer->render(
5661
'link.html.twig',
5762
[
@@ -80,4 +85,20 @@ private function isExternalUrl($url): bool
8085
{
8186
return u($url)->containsAny('://');
8287
}
88+
89+
/*
90+
* If the URL is considered safe, it's opened in the same browser tab;
91+
* otherwise it's opened in a new tab and with some strict security options.
92+
*/
93+
private function isSafeUrl(string $url): bool
94+
{
95+
// The following are considered Symfony URLs:
96+
// * https://symfony.com/[...]
97+
// * https://[...].symfony.com/ (e.g. insight.symfony.com, etc.)
98+
// * https://symfony.wip/[...] (used for internal/local development)
99+
$isSymfonyUrl = preg_match('{^http(s)?://(.*\.)?symfony.(com|wip)}', $url);
100+
$isRelativeUrl = !str_starts_with($url, 'http://') && !str_starts_with($url, 'https://');
101+
102+
return $isSymfonyUrl || $isRelativeUrl;
103+
}
83104
}

tests/fixtures/expected/blocks/references/php-class.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<head>
44
<meta charset="utf-8" />
55

6-
6+
77
</head>
88

99
<body>
10-
<p><a href="https://secure.php.net/manual/en/class.arrayaccess.php" class="reference external" title="ArrayAccess">ArrayAccess</a></p>
10+
<p><a href="https://secure.php.net/manual/en/class.arrayaccess.php" class="reference external" title="ArrayAccess" rel="external noopener noreferrer" target="_blank">ArrayAccess</a></p>
1111

1212
</body>
13-
</html>
13+
</html>

tests/fixtures/expected/blocks/references/php-function.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<head>
44
<meta charset="utf-8" />
55

6-
6+
77
</head>
88

99
<body>
10-
<p><a href="https://secure.php.net/manual/en/function.trigger-error.php" class="reference external" title="trigger_error">trigger_error</a></p>
10+
<p><a href="https://secure.php.net/manual/en/function.trigger-error.php" class="reference external" title="trigger_error" rel="external noopener noreferrer" target="_blank">trigger_error</a></p>
1111

1212
</body>
13-
</html>
13+
</html>

tests/fixtures/expected/blocks/references/php-method.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<head>
44
<meta charset="utf-8" />
55

6-
6+
77
</head>
88

99
<body>
10-
<p><a href="https://secure.php.net/manual/en/locale.getdefault.php" class="reference external" title="Locale">Locale::getDefault()</a></p>
10+
<p><a href="https://secure.php.net/manual/en/locale.getdefault.php" class="reference external" title="Locale" rel="external noopener noreferrer" target="_blank">Locale::getDefault()</a></p>
1111

1212
</body>
13-
</html>
13+
</html>

tests/fixtures/expected/main/datetime.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8" />
55

6-
6+
77
</head>
88

99
<body>
@@ -12,7 +12,7 @@ <h1 id="datetimetype-field"><a class="headerlink" href="#datetimetype-field" tit
1212
<p>This field type allows the user to modify data that represents a specific
1313
date and time (e.g. <code translate="no" class="notranslate">1984-06-05 12:15:30</code>).</p>
1414
<table>
15-
15+
1616
<tbody>
1717
<tr>
1818
<td>Underlying Data Type</td>
@@ -67,8 +67,8 @@ <h3 id="the-date-format-option"><a class="headerlink" href="#the-date-format-opt
6767
</p><p>This is a little tip about something! We an also talk about specific
6868
methods: <a href="https://api.symfony.com/4.0/Symfony/Component/BrowserKit/Client.html#method_doRequest" class="reference external" title="Symfony\Component\BrowserKit\Client::doRequest()">doRequest()</a>.
6969
Or a namespace: <a href="https://api.symfony.com/4.0/Symfony/Component/Validator/Constraints.html" class="reference external" title="Symfony\Component\Validator\Constraints">Constraints</a>.
70-
Or a PHP function: <a href="https://secure.php.net/manual/en/function.parse-ini-file.php" class="reference external" title="parse_ini_file">parse_ini_file</a>.
71-
Or a PHP method! <a href="https://secure.php.net/manual/en/locale.getdefault.php" class="reference external" title="Locale">Locale::getDefault()</a>.</p>
70+
Or a PHP function: <a href="https://secure.php.net/manual/en/function.parse-ini-file.php" class="reference external" title="parse_ini_file" rel="external noopener noreferrer" target="_blank">parse_ini_file</a>.
71+
Or a PHP method! <a href="https://secure.php.net/manual/en/locale.getdefault.php" class="reference external" title="Locale" rel="external noopener noreferrer" target="_blank">Locale::getDefault()</a>.</p>
7272
</div>
7373
</div>
7474
<div class="section">
@@ -129,7 +129,7 @@ <h3 id="format"><a class="headerlink" href="#format" title="Permalink to this he
129129
<p><strong>type</strong>: <code translate="no" class="notranslate">string</code><strong>default</strong>: <code translate="no" class="notranslate">Symfony<wbr>\Component<wbr>\Form<wbr>\Extension<wbr>\Core<wbr>\Type<wbr>\DateTimeType::HTML5_FORMAT</code></p>
130130
<p>If the <code translate="no" class="notranslate">widget</code> option is set to <code translate="no" class="notranslate">single_text</code>, this option specifies
131131
the format of the input, i.e. how Symfony will interpret the given input
132-
as a datetime string. See <a href="http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax" class="reference external">Date/Time Format Syntax</a>.</p>
132+
as a datetime string. See <a href="http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax" class="reference external" rel="external noopener noreferrer" target="_blank">Date/Time Format Syntax</a>.</p>
133133
<div class="admonition-wrapper"><div class="admonition admonition-sidebar"><p class="sidebar-title">Everyone loves sidebars</p><p>But do they really? They also get in the way!</p>
134134
</div></div>
135135
<div class="admonition admonition-caution ">
@@ -294,7 +294,7 @@ <h2 id="field-variables"><a class="headerlink" href="#field-variables" title="Pe
294294
<th>Usage</th>
295295
</tr>
296296
</thead>
297-
297+
298298
<tbody>
299299
<tr>
300300
<td>widget</td>
@@ -313,7 +313,7 @@ <h2 id="field-variables"><a class="headerlink" href="#field-variables" title="Pe
313313
<div class="section">
314314
<h2 id="url-checker-errors"><a class="headerlink" href="#url-checker-errors" title="Permalink to this headline">Url checker errors</a></h2>
315315
<p>This is a <a href="https://symfony.com/404" class="reference external">404 error</a>.
316-
And here is an invalid url <a href="http://invalid-url" class="reference external">invalid-url</a>.</p>
316+
And here is an invalid url <a href="http://invalid-url" class="reference external" rel="external noopener noreferrer" target="_blank">invalid-url</a>.</p>
317317
</div>
318318

319319
</body>

0 commit comments

Comments
 (0)