diff --git a/.eslintrc.js b/.eslintrc.js index 93ff1d7b59..480b274fad 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -109,7 +109,7 @@ module.exports = defineConfig({ 'react/jsx-equals-spacing': 'error', 'react/jsx-no-bind': 'error', 'react/jsx-no-useless-fragment': 'error', - 'react/jsx-no-target-blank': 'off', + 'react/jsx-no-target-blank': ['error', { allowReferrer: true }], 'react/jsx-tag-spacing': 'error', 'react/jsx-uses-react': 'off', // not needed with new JSX transform 'react/jsx-wrap-multilines': 'error', diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 48685db17a..3dca3a9614 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -8,6 +8,7 @@ module Admin layout 'admin' before_action :set_cache_headers + before_action :set_referrer_policy_header after_action :verify_authorized @@ -17,6 +18,10 @@ module Admin response.cache_control.replace(private: true, no_store: true) end + def set_referrer_policy_header + response.headers['Referrer-Policy'] = 'same-origin' + end + def set_user @user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound) end diff --git a/app/javascript/mastodon/components/attachment_list.jsx b/app/javascript/mastodon/components/attachment_list.jsx index c5ac046751..f97e22f2d4 100644 --- a/app/javascript/mastodon/components/attachment_list.jsx +++ b/app/javascript/mastodon/components/attachment_list.jsx @@ -36,7 +36,7 @@ export default class AttachmentList extends ImmutablePureComponent { return ( <li key={attachment.get('id')}> - <a href={displayUrl} target='_blank' rel='noopener noreferrer'> + <a href={displayUrl} target='_blank' rel='noopener'> {compact && <Icon id='link' icon={LinkIcon} />} {compact && ' ' } {displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />} diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx index d731a8e2d1..df0be8bc12 100644 --- a/app/javascript/mastodon/components/dropdown_menu.jsx +++ b/app/javascript/mastodon/components/dropdown_menu.jsx @@ -124,7 +124,7 @@ class DropdownMenu extends PureComponent { return ( <li className={classNames('dropdown-menu__item', { 'dropdown-menu__item--dangerous': dangerous })} key={`${text}-${i}`}> - <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}> + <a href={href} target={target} data-method={method} rel='noopener' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}> {text} </a> </li> diff --git a/app/javascript/mastodon/components/error_boundary.jsx b/app/javascript/mastodon/components/error_boundary.jsx index 392a3ad61e..ca2f017f3b 100644 --- a/app/javascript/mastodon/components/error_boundary.jsx +++ b/app/javascript/mastodon/components/error_boundary.jsx @@ -98,7 +98,7 @@ export default class ErrorBoundary extends PureComponent { )} </p> - <p className='error-boundary__footer'>Mastodon v{version} 路 <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> 路 <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p> + <p className='error-boundary__footer'>Mastodon v{version} 路 <a href={source_url} rel='noopener' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> 路 <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p> </div> <Helmet> diff --git a/app/javascript/mastodon/components/follow_button.tsx b/app/javascript/mastodon/components/follow_button.tsx index faf9d8bdb8..c62e76d4b5 100644 --- a/app/javascript/mastodon/components/follow_button.tsx +++ b/app/javascript/mastodon/components/follow_button.tsx @@ -88,7 +88,7 @@ export const FollowButton: React.FC<{ <a href='/settings/profile' target='_blank' - rel='noreferrer noopener' + rel='noopener' className='button button-secondary' > {label} diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index 59963a0a9f..95b06abc54 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -106,7 +106,7 @@ class Item extends PureComponent { if (attachment.get('type') === 'unknown') { return ( <div className={classNames('media-gallery__item', { standalone, 'media-gallery__item--tall': height === 100, 'media-gallery__item--wide': width === 100 })} key={attachment.get('id')}> - <a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={description} lang={lang} target='_blank' rel='noopener noreferrer'> + <a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={description} lang={lang} target='_blank' rel='noopener'> <Blurhash hash={attachment.get('blurhash')} className='media-gallery__preview' @@ -138,7 +138,7 @@ class Item extends PureComponent { href={attachment.get('remote_url') || originalUrl} onClick={this.handleClick} target='_blank' - rel='noopener noreferrer' + rel='noopener' > <img src={previewUrl} diff --git a/app/javascript/mastodon/components/server_banner.jsx b/app/javascript/mastodon/components/server_banner.jsx index b6ea01997b..989ac7f006 100644 --- a/app/javascript/mastodon/components/server_banner.jsx +++ b/app/javascript/mastodon/components/server_banner.jsx @@ -42,7 +42,7 @@ class ServerBanner extends PureComponent { return ( <div className='server-banner'> <div className='server-banner__introduction'> - <FormattedMessage id='server_banner.is_one_of_many' defaultMessage='{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank'>Mastodon</a> }} /> + <FormattedMessage id='server_banner.is_one_of_many' defaultMessage='{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank' rel='noopener'>Mastodon</a> }} /> </div> <Link to='/about'> diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index cf6fe86c3d..9f57629807 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -293,7 +293,7 @@ class Status extends ImmutablePureComponent { if (e?.button === 0 && !(e?.ctrlKey || e?.metaKey)) { history.push(path); } else if (e?.button === 1 || (e?.button === 0 && (e?.ctrlKey || e?.metaKey))) { - window.open(path, '_blank', 'noreferrer noopener'); + window.open(path, '_blank', 'noopener'); } }; diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx index 24141b13cb..34e84506f0 100644 --- a/app/javascript/mastodon/features/about/index.jsx +++ b/app/javascript/mastodon/features/about/index.jsx @@ -123,7 +123,7 @@ class About extends PureComponent { <div className='about__header'> <ServerHeroImage blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' /> <h1>{isLoading ? <Skeleton width='10ch' /> : server.get('domain')}</h1> - <p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank'>Mastodon</a> }} /></p> + <p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank' rel='noopener'>Mastodon</a> }} /></p> </div> <div className='about__meta'> diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx index 6583c1f604..fc38adc131 100644 --- a/app/javascript/mastodon/features/account/components/header.jsx +++ b/app/javascript/mastodon/features/account/components/header.jsx @@ -421,7 +421,7 @@ class Header extends ImmutablePureComponent { <div className='account__header__bar'> <div className='account__header__tabs'> - <a className='avatar' href={account.get('avatar')} rel='noopener noreferrer' target='_blank' onClick={this.handleAvatarClick}> + <a className='avatar' href={account.get('avatar')} rel='noopener' target='_blank' onClick={this.handleAvatarClick}> <Avatar account={suspended || hidden ? undefined : account} size={90} /> </a> diff --git a/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js b/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js index 9d6ff5226a..022c9baaf7 100644 --- a/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js +++ b/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js @@ -90,8 +90,8 @@ describe('emoji', () => { }); it('keeps ordering as expected (issue fixed by PR 20677)', () => { - expect(emojify('<p>馃挄 <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener noreferrer" target="_blank">#<span>foo</span></a> test: foo.</p>')) - .toEqual('<p><picture><img draggable="false" class="emojione" alt="馃挄" title=":two_hearts:" src="/emoji/1f495.svg"></picture> <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener noreferrer" target="_blank">#<span>foo</span></a> test: foo.</p>'); + expect(emojify('<p>馃挄 <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener" target="_blank">#<span>foo</span></a> test: foo.</p>')) + .toEqual('<p><picture><img draggable="false" class="emojione" alt="馃挄" title=":two_hearts:" src="/emoji/1f495.svg"></picture> <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener" target="_blank">#<span>foo</span></a> test: foo.</p>'); }); }); }); diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.jsx b/app/javascript/mastodon/features/getting_started/components/announcements.jsx index 3c0b53b9e7..713ad9f069 100644 --- a/app/javascript/mastodon/features/getting_started/components/announcements.jsx +++ b/app/javascript/mastodon/features/getting_started/components/announcements.jsx @@ -85,7 +85,7 @@ class ContentWithRouter extends ImmutablePureComponent { } link.setAttribute('target', '_blank'); - link.setAttribute('rel', 'noopener noreferrer'); + link.setAttribute('rel', 'noopener'); } } diff --git a/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx b/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx index 3075aff31b..65ccd7c276 100644 --- a/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx +++ b/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx @@ -28,7 +28,7 @@ export const RelationshipsSeveranceEvent = ({ type, target, followingCount, foll <div className='notification-group__main'> <p>{intl.formatMessage(messages[type], { from: <strong>{domain}</strong>, target: <strong>{target}</strong>, followingCount, followersCount })}</p> - <a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a> + <a href='/severed_relationships' target='_blank' rel='noopener' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a> </div> </div> ); diff --git a/app/javascript/mastodon/features/notifications/components/report.jsx b/app/javascript/mastodon/features/notifications/components/report.jsx index 52d6bfee9d..ed043ae789 100644 --- a/app/javascript/mastodon/features/notifications/components/report.jsx +++ b/app/javascript/mastodon/features/notifications/components/report.jsx @@ -55,7 +55,7 @@ class Report extends ImmutablePureComponent { </div> <div className='notification__report__actions'> - <a href={`/admin/reports/${report.get('id')}`} className='button' target='_blank' rel='noopener noreferrer'>{intl.formatMessage(messages.openReport)}</a> + <a href={`/admin/reports/${report.get('id')}`} className='button' target='_blank' rel='noopener'>{intl.formatMessage(messages.openReport)}</a> </div> </div> </div> diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx index ca0d1bc850..88e65c668b 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx @@ -70,7 +70,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ if (button === 0 && !(ctrlKey || metaKey)) { history.push(path); } else if (button === 1 || (button === 0 && (ctrlKey || metaKey))) { - window.open(path, '_blank', 'noreferrer noopener'); + window.open(path, '_blank', 'noopener'); } } diff --git a/app/javascript/mastodon/features/standalone/status/index.tsx b/app/javascript/mastodon/features/standalone/status/index.tsx index d5cb7e7f40..3b68c5c176 100644 --- a/app/javascript/mastodon/features/standalone/status/index.tsx +++ b/app/javascript/mastodon/features/standalone/status/index.tsx @@ -61,7 +61,7 @@ const Embed: React.FC<{ id: string }> = ({ id }) => { className='embed__overlay' href={permalink} target='_blank' - rel='noreferrer noopener' + rel='noopener' aria-label='' /> </div> diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx index 136a5568a4..f8d5a26aff 100644 --- a/app/javascript/mastodon/features/status/components/card.jsx +++ b/app/javascript/mastodon/features/status/components/card.jsx @@ -208,7 +208,7 @@ export default class Card extends PureComponent { <div className='status-card__actions' onClick={this.handleEmbedClick} role='none'> <div> <button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button> - <a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a> + <a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener'><Icon id='external-link' icon={OpenInNewIcon} /></a> </div> </div> ) : spoilerButton} @@ -219,7 +219,7 @@ export default class Card extends PureComponent { return ( <div className={classNames('status-card', { expanded: largeImage })} ref={this.setRef} onClick={revealed ? null : this.handleReveal} role={revealed ? 'button' : null}> {embed} - <a href={card.get('url')} target='_blank' rel='noopener noreferrer'>{description}</a> + <a href={card.get('url')} target='_blank' rel='noopener'>{description}</a> </div> ); } else if (card.get('image')) { @@ -239,7 +239,7 @@ export default class Card extends PureComponent { return ( <> - <a href={card.get('url')} className={classNames('status-card', { expanded: largeImage, bottomless: showAuthor })} target='_blank' rel='noopener noreferrer' ref={this.setRef}> + <a href={card.get('url')} className={classNames('status-card', { expanded: largeImage, bottomless: showAuthor })} target='_blank' rel='noopener' ref={this.setRef}> {embed} {description} </a> diff --git a/app/javascript/mastodon/features/ui/components/actions_modal.jsx b/app/javascript/mastodon/features/ui/components/actions_modal.jsx index 4e0879580b..851f828b4e 100644 --- a/app/javascript/mastodon/features/ui/components/actions_modal.jsx +++ b/app/javascript/mastodon/features/ui/components/actions_modal.jsx @@ -24,7 +24,7 @@ export default class ActionsModal extends ImmutablePureComponent { return ( <li key={`${text}-${i}`}> - <a href={href} target='_blank' rel='noopener noreferrer' onClick={this.props.onClick} data-index={i} className={classNames({ active })}> + <a href={href} target='_blank' rel='noopener' onClick={this.props.onClick} data-index={i} className={classNames({ active })}> {icon && <IconButton title={text} icon={icon} iconComponent={iconComponent} role='presentation' tabIndex={-1} inverted />} <div> <div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div> diff --git a/app/javascript/mastodon/features/ui/components/link_footer.tsx b/app/javascript/mastodon/features/ui/components/link_footer.tsx index 06cb92fe4f..cbfb6a3114 100644 --- a/app/javascript/mastodon/features/ui/components/link_footer.tsx +++ b/app/javascript/mastodon/features/ui/components/link_footer.tsx @@ -26,7 +26,7 @@ export const LinkFooter: React.FC<{ {statusPageUrl && ( <> <DividingCircle /> - <a href={statusPageUrl} target='_blank' rel='noopener noreferrer'> + <a href={statusPageUrl} target='_blank' rel='noopener'> <FormattedMessage id='footer.status' defaultMessage='Status' /> </a> </> @@ -72,15 +72,11 @@ export const LinkFooter: React.FC<{ <p> <strong>Mastodon</strong>:{' '} - <a href='https://joinmastodon.org' target='_blank' rel='noreferrer'> + <a href='https://joinmastodon.org' target='_blank' rel='noopener'> <FormattedMessage id='footer.about' defaultMessage='About' /> </a> <DividingCircle /> - <a - href='https://joinmastodon.org/apps' - target='_blank' - rel='noreferrer' - > + <a href='https://joinmastodon.org/apps' target='_blank' rel='noopener'> <FormattedMessage id='footer.get_app' defaultMessage='Get the app' /> </a> <DividingCircle /> @@ -91,7 +87,7 @@ export const LinkFooter: React.FC<{ /> </Link> <DividingCircle /> - <a href={source_url} rel='noopener noreferrer' target='_blank'> + <a href={source_url} rel='noopener' target='_blank'> <FormattedMessage id='footer.source_code' defaultMessage='View source code' diff --git a/app/lib/text_formatter.rb b/app/lib/text_formatter.rb index 5e8e73a217..7fbb6fce12 100644 --- a/app/lib/text_formatter.rb +++ b/app/lib/text_formatter.rb @@ -7,7 +7,7 @@ class TextFormatter URL_PREFIX_REGEX = %r{\A(https?://(www\.)?|xmpp:)} - DEFAULT_REL = %w(nofollow noopener noreferrer).freeze + DEFAULT_REL = %w(nofollow noopener).freeze DEFAULT_OPTIONS = { multiline: true, diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index d20266aa2c..c1e47d5b32 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -44,7 +44,7 @@ = t("statuses.visibilities.#{status.visibility}") 路 - = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener' do = t('admin.statuses.view_publicly') - if status.proper.sensitive? diff --git a/app/views/admin/reports/actions/preview.html.haml b/app/views/admin/reports/actions/preview.html.haml index 79c444453f..5a90bf1b8f 100644 --- a/app/views/admin/reports/actions/preview.html.haml +++ b/app/views/admin/reports/actions/preview.html.haml @@ -63,7 +63,7 @@ = material_symbol 'link' = media_attachment.file_file_name .strike-card__statuses-list__item__meta - = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener' do %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - unless status.application.nil? 路 diff --git a/app/views/admin/statuses/show.html.haml b/app/views/admin/statuses/show.html.haml index 1ff4763158..7328eeb0a7 100644 --- a/app/views/admin/statuses/show.html.haml +++ b/app/views/admin/statuses/show.html.haml @@ -9,7 +9,7 @@ data: { confirm: t('admin.reports.are_you_sure') }, name: :report, type: :submit - = link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener noreferrer' + = link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener' %h3= t('admin.statuses.metadata') diff --git a/app/views/admin/tags/show.html.haml b/app/views/admin/tags/show.html.haml index 462ca312a0..0c8b2eaec0 100644 --- a/app/views/admin/tags/show.html.haml +++ b/app/views/admin/tags/show.html.haml @@ -6,7 +6,7 @@ .time-period = date_range(@time_period) - = link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener noreferrer' + = link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener' - if current_user.can?(:view_dashboard) .dashboard @@ -17,7 +17,7 @@ label: t('admin.trends.tags.dashboard.tag_accounts_measure'), measure: 'tag_accounts', params: { id: @tag.id }, - rel: 'noopener noreferrer', + rel: 'noopener', start_at: @time_period.first, target: '_blank' .dashboard__item diff --git a/app/views/admin/trends/statuses/_status.html.haml b/app/views/admin/trends/statuses/_status.html.haml index 09547ff036..aa09803ed5 100644 --- a/app/views/admin/trends/statuses/_status.html.haml +++ b/app/views/admin/trends/statuses/_status.html.haml @@ -6,7 +6,7 @@ .one-liner = admin_account_link_to status.account - = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener' do = one_line_preview(status) - status.ordered_media_attachments.each do |media_attachment| diff --git a/app/views/admin/trends/tags/_tag.html.haml b/app/views/admin/trends/tags/_tag.html.haml index e0f9f39e47..1686c46652 100644 --- a/app/views/admin/trends/tags/_tag.html.haml +++ b/app/views/admin/trends/tags/_tag.html.haml @@ -8,7 +8,7 @@ %br/ - = link_to tag_path(tag), target: '_blank', rel: 'noopener noreferrer' do + = link_to tag_path(tag), target: '_blank', rel: 'noopener' do = t('admin.trends.tags.used_by_over_week', count: tag.history.reduce(0) { |sum, day| sum + day.accounts }) - if tag.trendable? diff --git a/app/views/application/_card.html.haml b/app/views/application/_card.html.haml index ae74f1dc63..c28e18522c 100644 --- a/app/views/application/_card.html.haml +++ b/app/views/application/_card.html.haml @@ -2,7 +2,7 @@ - compact ||= false .card.h-card - = link_to account_url, target: '_blank', rel: 'noopener noreferrer' do + = link_to account_url, target: '_blank', rel: 'noopener' do - unless compact .card__img = image_tag account.header.url, alt: '' diff --git a/app/views/disputes/strikes/_card.html.haml b/app/views/disputes/strikes/_card.html.haml index 58965ad600..33e4099cf9 100644 --- a/app/views/disputes/strikes/_card.html.haml +++ b/app/views/disputes/strikes/_card.html.haml @@ -27,7 +27,7 @@ = material_symbol 'link' = media_attachment.file_file_name .strike-card__statuses-list__item__meta - = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener' do %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - unless status.application.nil? 路 diff --git a/app/views/filters/statuses/_status_filter.html.haml b/app/views/filters/statuses/_status_filter.html.haml index 3476869e60..9f4605a09c 100644 --- a/app/views/filters/statuses/_status_filter.html.haml +++ b/app/views/filters/statuses/_status_filter.html.haml @@ -19,11 +19,11 @@ = media_attachment.file_file_name .detailed-status__meta - = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'name-tag', target: '_blank', rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'name-tag', target: '_blank', rel: 'noopener' do = image_tag(status.account.avatar.url, width: 15, height: 15, alt: '', class: 'avatar') .username= status.account.acct 路 - = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener noreferrer' do + = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener' do %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - if status.edited? 路 diff --git a/app/views/oauth/authorized_applications/index.html.haml b/app/views/oauth/authorized_applications/index.html.haml index eb544d079b..3745ed219f 100644 --- a/app/views/oauth/authorized_applications/index.html.haml +++ b/app/views/oauth/authorized_applications/index.html.haml @@ -9,7 +9,7 @@ - @applications.each do |application| .applications-list__item{ id: dom_id(application) } - if application.website.present? - = link_to application.name, application.website, target: '_blank', rel: 'noopener noreferrer', class: 'announcements-list__item__title' + = link_to application.name, application.website, target: '_blank', rel: 'noopener', class: 'announcements-list__item__title' - else %strong.announcements-list__item__title = application.name diff --git a/app/views/redirects/show.html.haml b/app/views/redirects/show.html.haml index aa0db350a8..984a70624b 100644 --- a/app/views/redirects/show.html.haml +++ b/app/views/redirects/show.html.haml @@ -11,4 +11,4 @@ .redirect__message %h1= t('redirects.title', instance: site_hostname) %p= t('redirects.prompt') - %p= link_to @redirect_path, @redirect_path, rel: 'noreferrer noopener' + %p= link_to @redirect_path, @redirect_path, rel: 'noopener' diff --git a/config/environments/production.rb b/config/environments/production.rb index 6d4c30cd20..4b1d327d93 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -153,7 +153,7 @@ Rails.application.configure do 'X-Frame-Options' => 'DENY', 'X-Content-Type-Options' => 'nosniff', 'X-XSS-Protection' => '0', - 'Referrer-Policy' => 'same-origin', + 'Referrer-Policy' => ENV['ALLOW_REFERRER_ORIGIN'] == 'true' ? 'origin' : 'same-origin', } # TODO: Remove once devise-two-factor data migration complete diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index c264548eb5..36c11a8263 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -114,7 +114,7 @@ class Sanitize add_attributes: { 'a' => { - 'rel' => 'nofollow noopener noreferrer', + 'rel' => 'nofollow noopener', 'target' => '_blank', }, }, diff --git a/spec/lib/sanitize/config_spec.rb b/spec/lib/sanitize/config_spec.rb index b1cab85827..b4c849c427 100644 --- a/spec/lib/sanitize/config_spec.rb +++ b/spec/lib/sanitize/config_spec.rb @@ -39,15 +39,15 @@ RSpec.describe Sanitize::Config do end it 'keeps a with href' do - expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>' + expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener" target="_blank">Test</a>' end it 'keeps a with translate="no"' do - expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener noreferrer" target="_blank">Test</a>' + expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener" target="_blank">Test</a>' end it 'removes "translate" attribute with invalid value' do - expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>' + expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener" target="_blank">Test</a>' end it 'removes a with unparsable href' do @@ -55,7 +55,7 @@ RSpec.describe Sanitize::Config do end it 'keeps a with supported scheme and no host' do - expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener noreferrer" target="_blank">Test</a>' + expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener" target="_blank">Test</a>' end it 'sanitizes math to LaTeX' do