From 5e0d3a2b1c80e16926cc246486cf392478696087 Mon Sep 17 00:00:00 2001 From: Pablo Zmdl Date: Thu, 9 Oct 2025 17:29:23 +0200 Subject: [PATCH] Add rel='noopener' to all links opening in a new window Browsers younger than ~5 years don't need this, but older browsers might cause problems. Code style change as demanded by eslint Remove accidentally added `id` attribute Fix test as it was intended --- plugins/help/help.php | 2 +- program/actions/contacts/show.php | 1 + program/actions/mail/index.php | 1 + program/actions/settings/about.php | 8 +++++--- program/actions/settings/index.php | 2 +- program/include/rcmail_install.php | 2 +- program/include/rcmail_output.php | 4 ++-- program/js/app.js | 8 +++++++- program/js/editor.js | 2 +- program/lib/Roundcube/rcube_text2html.php | 2 +- skins/elastic/templates/includes/footer.html | 2 +- skins/elastic/templates/login.html | 2 +- tests/Actions/Contacts/ShowTest.php | 2 +- tests/Actions/Mail/IndexTest.php | 4 ++-- tests/Framework/Text2HtmlTest.php | 4 ++-- 15 files changed, 28 insertions(+), 18 deletions(-) diff --git a/plugins/help/help.php b/plugins/help/help.php index 8a4816007c..c3b3b67741 100644 --- a/plugins/help/help.php +++ b/plugins/help/help.php @@ -162,7 +162,7 @@ public function error_page($args) && $rcmail->request_status == rcube::REQUEST_ERROR_URL && ($url = $rcmail->config->get('help_csrf_info')) ) { - $args['text'] .= '

' . html::a(['href' => $url, 'target' => '_blank'], $this->gettext('csrfinfo')) . '

'; + $args['text'] .= '

' . html::a(['href' => $url, 'target' => '_blank', 'rel' => 'noopener'], $this->gettext('csrfinfo')) . '

'; } return $args; diff --git a/program/actions/contacts/show.php b/program/actions/contacts/show.php index 98a4790acb..c4a0633a75 100644 --- a/program/actions/contacts/show.php +++ b/program/actions/contacts/show.php @@ -194,6 +194,7 @@ public static function render_url_value($url) return html::a([ 'href' => $prefix . $url, 'target' => '_blank', + 'rel' => 'noopener', 'class' => 'url', ], rcube::Q($url) diff --git a/program/actions/mail/index.php b/program/actions/mail/index.php index 30ddffc43b..7d7c57116f 100644 --- a/program/actions/mail/index.php +++ b/program/actions/mail/index.php @@ -1324,6 +1324,7 @@ public static function washtml_link_callback($tag, $attribs, $content, $washtml) } } elseif (!empty($attrib['href']) && $attrib['href'][0] != '#') { $attrib['target'] = '_blank'; + $attrib['rel'] = 'noopener'; } // Better security by adding rel="noreferrer" (#1484686) diff --git a/program/actions/settings/about.php b/program/actions/settings/about.php index e1fcd34873..900edef54a 100644 --- a/program/actions/settings/about.php +++ b/program/actions/settings/about.php @@ -43,10 +43,10 @@ public function run($args = []) }, 'license' => static function () { return 'This program is free software; you can redistribute it and/or modify it under the terms ' - . 'of the GNU General Public License ' + . 'of the GNU General Public License ' . 'as published by the Free Software Foundation, either version 3 of the License, ' . 'or (at your option) any later version.
' - . 'Some exceptions ' + . 'Some exceptions ' . 'for skins & plugins apply.'; }, ]); @@ -117,6 +117,7 @@ public static function plugins_list($attrib) if ($uri) { $uri = html::a([ 'target' => '_blank', + 'rel' => 'noopener', 'href' => rcube::Q($uri), ], rcube::Q($rcmail->gettext('download')) @@ -128,6 +129,7 @@ public static function plugins_list($attrib) if (!empty($data['license_uri'])) { $license = html::a([ 'target' => '_blank', + 'rel' => 'noopener', 'href' => rcube::Q($data['license_uri']), ], rcube::Q($data['license']) @@ -155,7 +157,7 @@ public static function skin_info($attrib) html::span('skinitem', html::span('skinname', rcube::Q($meta['name'])) . (!empty($meta['version']) ? ' (' . $meta['version'] . ')' : '') . html::br() . (!empty($meta['author_link']) ? html::span('skinauthor', $rcmail->gettext(['name' => 'skinauthor', 'vars' => ['author' => $meta['author_link']]])) . html::br() : '') . (!empty($meta['license_link']) ? html::span('skinlicense', $rcmail->gettext('license') . ': ' . $meta['license_link']) . html::br() : '') - . (!empty($meta['uri']) ? html::span('skinhomepage', $rcmail->gettext('source') . ': ' . html::a(['href' => $meta['uri'], 'target' => '_blank', 'tabindex' => '-1'], rcube::Q($rcmail->gettext('download')))) : '')) + . (!empty($meta['uri']) ? html::span('skinhomepage', $rcmail->gettext('source') . ': ' . html::a(['href' => $meta['uri'], 'target' => '_blank', 'rel' => 'noopener', 'tabindex' => '-1'], rcube::Q($rcmail->gettext('download')))) : '')) ); return $content; diff --git a/program/actions/settings/index.php b/program/actions/settings/index.php index fcb0df97fb..e9a9fb19c5 100644 --- a/program/actions/settings/index.php +++ b/program/actions/settings/index.php @@ -1513,7 +1513,7 @@ public static function user_prefs($current = null) 'content' => html::div( ['style' => 'display:none', 'class' => 'boxwarning', 'id' => 'mailvelope-warning'], str_replace( - 'Mailvelope', 'Mailvelope', + 'Mailvelope', 'Mailvelope', rcube::Q($rcmail->gettext('mailvelopenotfound')) ) . html::script([], "if (!parent.mailvelope) \$('#mailvelope-warning').show()") diff --git a/program/include/rcmail_install.php b/program/include/rcmail_install.php index 9f8936d559..14c41852e9 100644 --- a/program/include/rcmail_install.php +++ b/program/include/rcmail_install.php @@ -811,7 +811,7 @@ private function _showhint($message, $url = '') $hint = rcube::Q($message); if ($url) { - $hint .= ($hint ? '; ' : '') . 'See ' . rcube::Q($url) . ''; + $hint .= ($hint ? '; ' : '') . 'See ' . rcube::Q($url) . ''; } if ($hint) { diff --git a/program/include/rcmail_output.php b/program/include/rcmail_output.php index 332c69793a..2a3cc82bd7 100644 --- a/program/include/rcmail_output.php +++ b/program/include/rcmail_output.php @@ -73,8 +73,8 @@ public function get_skin_info($name = null) $meta = INSTALL_PATH . "skins/{$skin}/meta.json"; if (is_readable($meta) && ($json = json_decode(file_get_contents($meta), true))) { $data = $json; - $data['author_link'] = !empty($json['url']) ? html::a(['href' => $json['url'], 'target' => '_blank'], rcube::Q($json['author'])) : rcube::Q($json['author']); - $data['license_link'] = !empty($json['license-url']) ? html::a(['href' => $json['license-url'], 'target' => '_blank', 'tabindex' => '-1'], rcube::Q($json['license'])) : rcube::Q($json['license']); + $data['author_link'] = !empty($json['url']) ? html::a(['href' => $json['url'], 'target' => '_blank', 'rel' => 'noopener'], rcube::Q($json['author'])) : rcube::Q($json['author']); + $data['license_link'] = !empty($json['license-url']) ? html::a(['href' => $json['license-url'], 'target' => '_blank', 'rel' => 'noopener', 'tabindex' => '-1'], rcube::Q($json['license'])) : rcube::Q($json['license']); } $composer = INSTALL_PATH . "/skins/{$skin}/composer.json"; diff --git a/program/js/app.js b/program/js/app.js index 018335249f..ace7f9f5eb 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -4425,7 +4425,13 @@ function rcube_webmail() { li.append($('