@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator

Explicitly add rel="noreferrer" to all external links

Summary: See D19117. Instead of automatically figuring this out inside `phutil_tag()`, explicitly add rel="noreferrer" at the application level to all external links.

Test Plan:
- Grepped for `_blank`, `isValidRemoteURIForLink`, checked all callsites for user-controlled data.
- Created a link menu item, verified noreferrer in markup.
- Created a link custom field, verified no referrer in markup.
- Verified noreferrer for `{nav href=...}`.

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Differential Revision: https://secure.phabricator.com/D19118

+44 -20
+1
src/applications/auth/view/PhabricatorAuthAccountView.php
··· 77 77 array( 78 78 'href' => $account_uri, 79 79 'target' => '_blank', 80 + 'rel' => 'noreferrer', 80 81 ), 81 82 $account_uri); 82 83 }
+1
src/applications/calendar/import/PhabricatorCalendarICSURIImportEngine.php
··· 45 45 array( 46 46 'href' => $uri, 47 47 'target' => '_blank', 48 + 'rel' => 'noreferrer', 48 49 ), 49 50 $uri); 50 51 }
+1 -7
src/applications/files/markup/PhabricatorImageRemarkupRule.php
··· 20 20 $defaults = array( 21 21 'uri' => null, 22 22 'alt' => null, 23 - 'href' => null, 24 23 'width' => null, 25 24 'height' => null, 26 25 ); ··· 45 44 46 45 $args += $defaults; 47 46 48 - if ($args['href'] && !PhabricatorEnv::isValidURIForLink($args['href'])) { 49 - $args['href'] = null; 50 - } 51 - 52 47 if ($args['uri']) { 53 48 $src_uri = id(new PhutilURI('/file/imageproxy/')) 54 49 ->setQueryParam('uri', (string)$args['uri']); ··· 57 52 array( 58 53 'src' => $src_uri, 59 54 'alt' => $args['alt'], 60 - 'href' => $args['href'], 61 55 'width' => $args['width'], 62 56 'height' => $args['height'], 63 - )); 57 + )); 64 58 return $this->getEngine()->storeText($img); 65 59 } else { 66 60 return $matches[0];
+1
src/applications/harbormaster/artifact/HarbormasterURIArtifact.php
··· 81 81 array( 82 82 'href' => $uri, 83 83 'target' => '_blank', 84 + 'rel' => 'noreferrer', 84 85 ), 85 86 $name); 86 87 }
+2
src/applications/nuance/item/NuanceGitHubEventItemType.php
··· 309 309 'a', 310 310 array( 311 311 'href' => $event_uri, 312 + 'target' => '_blank', 313 + 'rel' => 'noreferrer', 312 314 ), 313 315 $event_uri); 314 316 }
+1
src/applications/phurl/remarkup/PhabricatorPhurlLinkRemarkupRule.php
··· 64 64 array( 65 65 'href' => $uri, 66 66 'target' => '_blank', 67 + 'rel' => 'noreferrer', 67 68 ), 68 69 $name); 69 70 }
+2 -1
src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php
··· 99 99 ->setHref($href) 100 100 ->setName($name) 101 101 ->setIcon($icon_class) 102 - ->setTooltip($tooltip); 102 + ->setTooltip($tooltip) 103 + ->setRel('noreferrer'); 103 104 104 105 return array( 105 106 $item,
+5 -1
src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldLink.php
··· 31 31 32 32 return phutil_tag( 33 33 'a', 34 - array('href' => $value, 'target' => '_blank'), 34 + array( 35 + 'href' => $value, 36 + 'target' => '_blank', 37 + 'rel' => 'noreferrer', 38 + ), 35 39 $value); 36 40 } 37 41
+3
src/view/layout/PhabricatorActionView.php
··· 255 255 } else { 256 256 if ($this->getOpenInNewWindow()) { 257 257 $target = '_blank'; 258 + $rel = 'noreferrer'; 258 259 } else { 259 260 $target = null; 261 + $rel = null; 260 262 } 261 263 262 264 if ($this->submenu) { ··· 277 279 'href' => $this->getHref(), 278 280 'class' => 'phabricator-action-view-item', 279 281 'target' => $target, 282 + 'rel' => $rel, 280 283 'sigil' => $sigils, 281 284 'meta' => $this->metadata, 282 285 ),
+12 -1
src/view/phui/PHUIListItemView.php
··· 34 34 private $actionIcon; 35 35 private $actionIconHref; 36 36 private $count; 37 + private $rel; 37 38 38 39 public function setOpenInNewWindow($open_in_new_window) { 39 40 $this->openInNewWindow = $open_in_new_window; ··· 44 45 return $this->openInNewWindow; 45 46 } 46 47 47 - public function setHideInApplicationMenu($hide) { 48 + public function setRel($rel) { 49 + $this->rel = $rel; 50 + return $this; 51 + } 52 + 53 + public function getRel() { 54 + return $this->rel; 55 + } 56 + 57 + public function setHideInApplicationMenu($hide) { 48 58 $this->hideInApplicationMenu = $hide; 49 59 return $this; 50 60 } ··· 363 373 'meta' => $meta, 364 374 'sigil' => $sigil, 365 375 'target' => $this->getOpenInNewWindow() ? '_blank' : null, 376 + 'rel' => $this->rel, 366 377 ), 367 378 array( 368 379 $aural,
+15 -10
src/view/phui/PHUITagView.php
··· 154 154 $classes[] = 'phui-tag-'.$this->border; 155 155 } 156 156 157 + $attributes = array( 158 + 'href' => $this->href, 159 + 'class' => $classes, 160 + ); 161 + 162 + if ($this->external) { 163 + $attributes += array( 164 + 'target' => '_blank', 165 + 'rel' => 'noreferrer', 166 + ); 167 + } 168 + 157 169 if ($this->phid) { 158 170 Javelin::initBehavior('phui-hovercards'); 159 171 160 - $attributes = array( 161 - 'href' => $this->href, 172 + $attributes += array( 162 173 'sigil' => 'hovercard', 163 - 'meta' => array( 174 + 'meta' => array( 164 175 'hoverPHID' => $this->phid, 165 176 ), 166 - 'target' => $this->external ? '_blank' : null, 167 - ); 168 - } else { 169 - $attributes = array( 170 - 'href' => $this->href, 171 - 'target' => $this->external ? '_blank' : null, 172 177 ); 173 178 } 174 179 175 - return $attributes + array('class' => $classes); 180 + return $attributes; 176 181 } 177 182 178 183 protected function getTagContent() {