diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb
index b9b75727dd9d21a14215a9508562e17d662db6f1..1dd7430e098295c88e0d5282dcd7bbe114f63aff 100644
--- a/app/controllers/admin/accounts_controller.rb
+++ b/app/controllers/admin/accounts_controller.rb
@@ -53,6 +53,13 @@ module Admin
       redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.destroyed_msg', username: @account.acct)
     end
 
+    def unsensitive
+      authorize @account, :unsensitive?
+      @account.unsensitize!
+      log_action :unsensitive, @account
+      redirect_to admin_account_path(@account.id)
+    end
+
     def unsilence
       authorize @account, :unsilence?
       @account.unsilence!
diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb
index 3af572f25ef1f8593ba19c92022b97985bb89a76..63cc521ed0119912d5f6b9149bb03a0b2b5c2470 100644
--- a/app/controllers/api/v1/admin/accounts_controller.rb
+++ b/app/controllers/api/v1/admin/accounts_controller.rb
@@ -22,6 +22,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController
     active
     pending
     disabled
+    sensitized
     silenced
     suspended
     username
@@ -68,6 +69,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController
     render json: @account, serializer: REST::Admin::AccountSerializer
   end
 
+  def unsensitive
+    authorize @account, :unsensitive?
+    @account.unsensitize!
+    log_action :unsensitive, @account
+    render json: @account, serializer: REST::Admin::AccountSerializer
+  end
+
   def unsilence
     authorize @account, :unsilence?
     @account.unsilence!
diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb
index a51597cf353e013c159ed61c0728c9d017f12150..adb7918c53fd14b867d5b958744f0c4173f17cc3 100644
--- a/app/helpers/statuses_helper.rb
+++ b/app/helpers/statuses_helper.rb
@@ -117,6 +117,14 @@ module StatusesHelper
     end
   end
 
+  def sensitized?(status, account)
+    if !account.nil? && account.id == status.account_id
+      status.sensitive
+    else
+      status.account.sensitized? || status.sensitive
+    end
+  end
+
   private
 
   def simplified_text(text)
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index f275feefc500e8af6c88944b813c701228440778..c77f237f9a77fac148384a5e368dd0968dbf5c2c 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -111,7 +111,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
         created_at: @object['published'],
         override_timestamps: @options[:override_timestamps],
         reply: @object['inReplyTo'].present?,
-        sensitive: @object['sensitive'] || false,
+        sensitive: @account.sensitized? || @object['sensitive'] || false,
         visibility: visibility_from_audience,
         thread: replied_to_status,
         conversation: conversation_from_uri(@object['conversation']),
diff --git a/app/models/account.rb b/app/models/account.rb
index 59d338f5af15e0a8314ba8394f463efe8f4a43a2..d2112a13df63598c1ea4bd8a51db782a042f8c7c 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -50,6 +50,7 @@
 #  avatar_storage_schema_version :integer
 #  header_storage_schema_version :integer
 #  devices_url                   :string
+#  sensitized_at                 :datetime
 #
 
 class Account < ApplicationRecord
@@ -92,6 +93,7 @@ class Account < ApplicationRecord
   scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
   scope :silenced, -> { where.not(silenced_at: nil) }
   scope :suspended, -> { where.not(suspended_at: nil) }
+  scope :sensitized, -> { where.not(sensitized_at: nil) }
   scope :without_suspended, -> { where(suspended_at: nil) }
   scope :without_silenced, -> { where(silenced_at: nil) }
   scope :recent, -> { reorder(id: :desc) }
@@ -234,6 +236,18 @@ class Account < ApplicationRecord
     end
   end
 
+  def sensitized?
+    sensitized_at.present?
+  end
+
+  def sensitize!(date = Time.now.utc)
+    update!(sensitized_at: date)
+  end
+
+  def unsensitize!
+    update!(sensitized_at: nil)
+  end
+
   def memorialize!
     update!(memorial: true)
   end
diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb
index 157e6c04d1eb39d41872f3c07f1054179c6d66af..5efc924d5f7ae36a7fb038ff4c2fbfe06a157416 100644
--- a/app/models/account_warning.rb
+++ b/app/models/account_warning.rb
@@ -13,7 +13,7 @@
 #
 
 class AccountWarning < ApplicationRecord
-  enum action: %i(none disable silence suspend), _suffix: :action
+  enum action: %i(none disable sensitive silence suspend), _suffix: :action
 
   belongs_to :account, inverse_of: :account_warnings
   belongs_to :target_account, class_name: 'Account', inverse_of: :targeted_account_warnings
diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb
index c4ac09520ef27556247eeb0681a8e718fc9bb889..11ce737f3e02d6e4b0550063db5c22eb97d723b8 100644
--- a/app/models/admin/account_action.rb
+++ b/app/models/admin/account_action.rb
@@ -8,6 +8,7 @@ class Admin::AccountAction
   TYPES = %w(
     none
     disable
+    sensitive
     silence
     suspend
   ).freeze
@@ -64,6 +65,8 @@ class Admin::AccountAction
     case type
     when 'disable'
       handle_disable!
+    when 'sensitive'
+      handle_sensitive!
     when 'silence'
       handle_silence!
     when 'suspend'
@@ -109,6 +112,12 @@ class Admin::AccountAction
     target_account.user&.disable!
   end
 
+  def handle_sensitive!
+    authorize(target_account, :sensitive?)
+    log_action(:sensitive, target_account)
+    target_account.sensitize!
+  end
+
   def handle_silence!
     authorize(target_account, :silence?)
     log_action(:silence, target_account)
diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb
index 0ba7e1609449eb9ccf433a4775120e24fb61eb88..3a1b67e06752c7c5f1235673fb04c7972a6e04a5 100644
--- a/app/models/admin/action_log_filter.rb
+++ b/app/models/admin/action_log_filter.rb
@@ -35,9 +35,11 @@ class Admin::ActionLogFilter
     reopen_report: { target_type: 'Report', action: 'reopen' }.freeze,
     reset_password_user: { target_type: 'User', action: 'reset_password' }.freeze,
     resolve_report: { target_type: 'Report', action: 'resolve' }.freeze,
+    sensitive_account: { target_type: 'Account', action: 'sensitive' }.freeze,
     silence_account: { target_type: 'Account', action: 'silence' }.freeze,
     suspend_account: { target_type: 'Account', action: 'suspend' }.freeze,
     unassigned_report: { target_type: 'Report', action: 'unassigned' }.freeze,
+    unsensitive_account: { target_type: 'Account', action: 'unsensitive' }.freeze,
     unsilence_account: { target_type: 'Account', action: 'unsilence' }.freeze,
     unsuspend_account: { target_type: 'Account', action: 'unsuspend' }.freeze,
     update_announcement: { target_type: 'Announcement', action: 'update' }.freeze,
diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb
index 1b105e92aa8e95097ed3673a2913ba99a993a1f3..679119075e15f54dac12686376211f16966ff5a7 100644
--- a/app/policies/account_policy.rb
+++ b/app/policies/account_policy.rb
@@ -25,6 +25,14 @@ class AccountPolicy < ApplicationPolicy
     staff?
   end
 
+  def sensitive?
+    staff? && !record.user&.staff?
+  end
+
+  def unsensitive?
+    staff?
+  end
+
   def silence?
     staff? && !record.user&.staff?
   end
diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb
index f26fd93a424f1ecb30f10f0e11ebbe880080b528..6f9e1ca639183282d9bfb0daa5a3365da1b339f7 100644
--- a/app/serializers/activitypub/note_serializer.rb
+++ b/app/serializers/activitypub/note_serializer.rb
@@ -95,6 +95,10 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
     ActivityPub::TagManager.instance.cc(object)
   end
 
+  def sensitive
+    object.account.sensitized? || object.sensitive
+  end
+
   def virtual_tags
     object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis
   end
diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb
index 0109de882bdc0021fdbeb9b9c86bd3b41981d602..bb6df90b7a61f53342506f92b7dd945177e940e2 100644
--- a/app/serializers/rest/status_serializer.rb
+++ b/app/serializers/rest/status_serializer.rb
@@ -58,6 +58,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
     end
   end
 
+  def sensitive
+    if current_user? && current_user.account_id == object.account_id
+      object.sensitive
+    else
+      object.account.sensitized? || object.sensitive
+    end
+  end
+
   def uri
     ActivityPub::TagManager.instance.uri_for(object)
   end
diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml
index f0a216f6b8f622ed7be2171caf3371ff3e8acc18..d5978eddd64a7a2ea5fa07786edb88e55e02574e 100644
--- a/app/views/admin/accounts/show.html.haml
+++ b/app/views/admin/accounts/show.html.haml
@@ -69,6 +69,8 @@
           = t('admin.accounts.confirming')
         - elsif @account.local? && !@account.user_approved?
           = t('admin.accounts.pending')
+        - elsif @account.sensitized?
+          = t('admin.accounts.sensitive')
         - else
           = t('admin.accounts.no_limits_imposed')
       .dashboard__counters__label= t 'admin.accounts.login_status'
@@ -192,6 +194,11 @@
           - else
             = link_to t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable'), class: 'button' if can?(:disable, @account.user)
 
+        - if @account.sensitized?
+          = link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsensitive, @account)
+        - elsif !@account.local? || @account.user_approved?
+          = link_to t('admin.accounts.sensitive'), new_admin_account_action_path(@account.id, type: 'sensitive'), class: 'button' if can?(:sensitive, @account)
+
         - if @account.silenced?
           = link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account)
         - elsif !@account.local? || @account.user_approved?
diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml
index b3e9c44fc8bdb3b7349398a4c4fb3ddf07087eba..a4dd8534fa56361ec9785c24cc2de808bdbb0aec 100644
--- a/app/views/statuses/_detailed_status.html.haml
+++ b/app/views/statuses/_detailed_status.html.haml
@@ -29,17 +29,17 @@
   - if !status.media_attachments.empty?
     - if status.media_attachments.first.video?
       - video = status.media_attachments.first
-      = react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: status.sensitive?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do
+      = react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 670, height: 380, detailed: true, inline: true, alt: video.description do
         = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
     - elsif status.media_attachments.first.audio?
       - audio = status.media_attachments.first
       = react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 670, height: 380, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do
         = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
     - else
-      = react_component :media_gallery, height: 380, sensitive: status.sensitive?, standalone: true, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
+      = react_component :media_gallery, height: 380, sensitive: sensitized?(status, current_account), standalone: true, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
         = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
   - elsif status.preview_card
-    = react_component :card, sensitive: status.sensitive?, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
+    = react_component :card, sensitive: sensitized?(status, current_account), 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
 
   .detailed-status__meta
     %data.dt-published{ value: status.created_at.to_time.iso8601 }
diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml
index 7408749cca35ee8dab055a13b022435757f3edb0..1921927005f77e5ec06f25a71dad8df5cc2fc544 100644
--- a/app/views/statuses/_simple_status.html.haml
+++ b/app/views/statuses/_simple_status.html.haml
@@ -35,17 +35,17 @@
   - if !status.media_attachments.empty?
     - if status.media_attachments.first.video?
       - video = status.media_attachments.first
-      = react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: status.sensitive?, width: 610, height: 343, inline: true, alt: video.description do
+      = react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 610, height: 343, inline: true, alt: video.description do
         = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
     - elsif status.media_attachments.first.audio?
       - audio = status.media_attachments.first
       = react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 610, height: 343, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do
         = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
     - else
-      = react_component :media_gallery, height: 343, sensitive: status.sensitive?, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
+      = react_component :media_gallery, height: 343, sensitive: sensitized?(status, current_account), autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
         = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
   - elsif status.preview_card
-    = react_component :card, sensitive: status.sensitive?, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
+    = react_component :card, sensitive: sensitized?(status, current_account), 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
 
   - if !status.in_reply_to_id.nil? && status.in_reply_to_account_id == status.account.id
     = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__content__read-more-button', target: stream_link_target, rel: 'noopener noreferrer' do
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 084006a2af1936aee54d0777bc15b77991c48a90..c962bc53202c45cd099c02e6cf644595485c8419 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -188,6 +188,8 @@ en:
       search: Search
       search_same_email_domain: Other users with the same e-mail domain
       search_same_ip: Other users with the same IP
+      sensitive: Sensitive
+      sensitized: marked as sensitive
       shared_inbox_url: Shared inbox URL
       show:
         created_reports: Made reports
@@ -202,6 +204,7 @@ en:
       time_in_queue: Waiting in queue %{time}
       title: Accounts
       unconfirmed_email: Unconfirmed email
+      undo_sensitized: Undo sensitive
       undo_silenced: Undo silence
       undo_suspension: Undo suspension
       unsilenced_msg: Successfully unlimited %{username}'s account
@@ -243,9 +246,11 @@ en:
         reopen_report: Reopen Report
         reset_password_user: Reset Password
         resolve_report: Resolve Report
+        sensitive_account: Mark the media in your account as sensitive
         silence_account: Silence Account
         suspend_account: Suspend Account
         unassigned_report: Unassign Report
+        unsensitive_account: Unmark the media in your account as sensitive
         unsilence_account: Unsilence Account
         unsuspend_account: Unsuspend Account
         update_announcement: Update Announcement
@@ -281,9 +286,11 @@ en:
         reopen_report: "%{name} reopened report %{target}"
         reset_password_user: "%{name} reset password of user %{target}"
         resolve_report: "%{name} resolved report %{target}"
+        sensitive_account: "%{name} marked %{target}'s media as sensitive"
         silence_account: "%{name} silenced %{target}'s account"
         suspend_account: "%{name} suspended %{target}'s account"
         unassigned_report: "%{name} unassigned report %{target}"
+        unsensitive_account: "%{name} unmarked %{target}'s media as sensitive"
         unsilence_account: "%{name} unsilenced %{target}'s account"
         unsuspend_account: "%{name} unsuspended %{target}'s account"
         update_announcement: "%{name} updated announcement %{target}"
@@ -1339,6 +1346,7 @@ en:
     warning:
       explanation:
         disable: You can no longer login to your account or use it in any other way, but your profile and other data remains intact.
+        sensitive: Your uploaded media files and linked media will be treated as sensitive.
         silence: You can still use your account but only people who are already following you will see your toots on this server, and you may be excluded from various public listings. However, others may still manually follow you.
         suspend: You can no longer use your account, and your profile and other data are no longer accessible. You can still login to request a backup of your data until the data is fully removed, but we will retain some data to prevent you from evading the suspension.
       get_in_touch: You can reply to this e-mail to get in touch with the staff of %{instance}.
@@ -1347,11 +1355,13 @@ en:
       subject:
         disable: Your account %{acct} has been frozen
         none: Warning for %{acct}
+        sensitive: Your account %{acct} posting media has been marked as sensitive
         silence: Your account %{acct} has been limited
         suspend: Your account %{acct} has been suspended
       title:
         disable: Account frozen
         none: Warning
+        sensitive: Your media has been marked as sensitive
         silence: Account limited
         suspend: Account suspended
     welcome:
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index fb6255546776a958d6a417f58dcd95b20f5f3cec..fd9ec9427becde8bc39dd4582b47f8579709db7d 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -172,6 +172,8 @@ ja:
       search: 検索
       search_same_email_domain: 同じドメインのメールアドレスを使用しているユーザー
       search_same_ip: 同じ IP のユーザーを検索
+      sensitive: 閲覧注意
+      sensitized: 閲覧注意済み
       shared_inbox_url: Shared inbox URL
       show:
         created_reports: このアカウントで作られた通報
@@ -184,6 +186,7 @@ ja:
       time_in_queue: "%{time} 待ち"
       title: アカウント
       unconfirmed_email: 確認待ちのメールアドレス
+      undo_sensitized: 閲覧注意から戻す
       undo_silenced: サイレンスから戻す
       undo_suspension: 停止から戻す
       unsubscribe: 購読の解除
@@ -220,9 +223,11 @@ ja:
         reopen_report: 通報を再度開く
         reset_password_user: パスワードをリセット
         resolve_report: 通報を解決済みにする
+        sensitive_account: アカウントのメディアを閲覧注意にマーク
         silence_account: アカウントをサイレンス
         suspend_account: アカウントを停止
         unassigned_report: 通報の担当を解除
+        unsensitive_account: アカウントのメディアの閲覧注意マークを解除
         unsilence_account: アカウントのサイレンスを解除
         unsuspend_account: アカウントの停止を解除
         update_announcement: お知らせを更新
@@ -256,9 +261,11 @@ ja:
         reopen_report: "%{name} さんが通報 %{target} を再び開きました"
         reset_password_user: "%{name} さんが %{target} さんのパスワードをリセットしました"
         resolve_report: "%{name} さんが通報 %{target} を解決済みにしました"
+        sensitive_account: "%{name} さんが %{target} さんのメディアを閲覧注意にマークしました"
         silence_account: "%{name} さんが %{target} さんをサイレンスにしました"
         suspend_account: "%{name} さんが %{target} さんを停止しました"
         unassigned_report: "%{name} さんが通報 %{target} の担当を外しました"
+        unsensitive_account: "%{name} さんが %{target} さんのメディアの閲覧注意を解除しました"
         unsilence_account: "%{name} さんが %{target} さんのサイレンスを解除しました"
         unsuspend_account: "%{name} さんが %{target} さんの停止を解除しました"
         update_announcement: "%{name} さんがお知らせ %{target} を更新しました"
@@ -1271,6 +1278,7 @@ ja:
     warning:
       explanation:
         disable: アカウントが凍結されている間、データはそのまま残りますが、凍結が解除されるまでは何の操作もできません。
+        sensitive: あなたのアップロードしたメディアファイルとリンク先のメディアは、閲覧注意として扱われます。
         silence: あなたのアカウントは制限されていますが、あなたをフォローしているユーザーのみ、このサーバー上の投稿を見ることができます。そしてあなたは様々な公開リストから除外されるかもしれません。ただし、他のユーザーは手動であなたをフォローすることができます。
         suspend: あなたのアカウントは停止されています。あなたの投稿とアップロードされたメディアファイルは、このサーバーとあなたのフォロワーが参加していたサーバーから完全に削除されました。
       get_in_touch: このメールに返信することで %{instance} のスタッフと連絡を取ることができます。
@@ -1279,11 +1287,13 @@ ja:
       subject:
         disable: あなたのアカウント %{acct} は凍結されました
         none: "%{acct} に対する警告"
+        sensitive: あなたのアカウント %{acct} の投稿メディアは閲覧注意とマークされました
         silence: あなたのアカウント %{acct} はサイレンスにされました
         suspend: あなたのアカウント %{acct} は停止されました
       title:
         disable: アカウントが凍結されました
         none: 警告
+        sensitive: あなたのメディアが閲覧注意とマークされました
         silence: アカウントがサイレンスにされました
         suspend: アカウントが停止されました
     welcome:
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index b694879535f81ee84f66a16908f84ab92e6e400d..46a4759a8564d589a81e7d61496d9a99237f8a8b 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -100,6 +100,7 @@ en:
         types:
           disable: Freeze
           none: Send a warning
+          sensitive: Sensitive
           silence: Limit
           suspend: Suspend
         warning_preset_id: Use a warning preset
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index bbc0b5fd77ead61493683745ff5d3c35bd24f964..00f469b870f9e6a103ce7885cdff152cbdbdd8b8 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -91,6 +91,7 @@ ja:
         types:
           disable: ログインを無効化
           none: 何もしない
+          sensitive: 閲覧注意
           silence: サイレンス
           suspend: 停止しアカウントのデータを恒久的に削除する
         warning_preset_id: プリセット警告文を使用
diff --git a/config/routes.rb b/config/routes.rb
index e0ef237233370f407d425c442cbb4e3f5136ad82..54c76799ca92cfea9fd6eb72a91b76d9e59d71a2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -236,6 +236,7 @@ Rails.application.routes.draw do
     resources :accounts, only: [:index, :show, :destroy] do
       member do
         post :enable
+        post :unsensitive
         post :unsilence
         post :unsuspend
         post :redownload
@@ -476,6 +477,7 @@ Rails.application.routes.draw do
         resources :accounts, only: [:index, :show, :destroy] do
           member do
             post :enable
+            post :unsensitive
             post :unsilence
             post :unsuspend
             post :approve
diff --git a/db/migrate/20200614002136_add_sensitized_to_accounts.rb b/db/migrate/20200614002136_add_sensitized_to_accounts.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bc2dfcb6363bad70f14d57d2b3ad5517cab85477
--- /dev/null
+++ b/db/migrate/20200614002136_add_sensitized_to_accounts.rb
@@ -0,0 +1,5 @@
+class AddSensitizedToAccounts < ActiveRecord::Migration[5.2]
+  def change
+    add_column :accounts, :sensitized_at, :datetime
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 262e25b3bab1a5593a30127876c87ca14994d45c..5ff6b6300638ee54812140ad032a649ae5d5b80f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -189,6 +189,7 @@ ActiveRecord::Schema.define(version: 2020_10_08_220312) do
     t.integer "avatar_storage_schema_version"
     t.integer "header_storage_schema_version"
     t.string "devices_url"
+    t.datetime "sensitized_at"
     t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
     t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
     t.index ["moved_to_account_id"], name: "index_accounts_on_moved_to_account_id"
diff --git a/spec/controllers/api/v1/admin/accounts_controller_spec.rb b/spec/controllers/api/v1/admin/accounts_controller_spec.rb
index f3f9946baac2dbb197586350c93ccc891d0a7710..89cadb222b8a97a862228d720633cd2c5c54a106 100644
--- a/spec/controllers/api/v1/admin/accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/accounts_controller_spec.rb
@@ -127,6 +127,24 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
     end
   end
 
+  describe 'POST #unsensitive' do
+    before do
+      account.touch(:sensitized_at)
+      post :unsensitive, params: { id: account.id }
+    end
+
+    it_behaves_like 'forbidden for wrong scope', 'write:statuses'
+    it_behaves_like 'forbidden for wrong role', 'user'
+
+    it 'returns http success' do
+      expect(response).to have_http_status(200)
+    end
+
+    it 'unsensitives account' do
+      expect(account.reload.sensitized?).to be false
+    end
+  end
+
   describe 'POST #unsilence' do
     before do
       account.touch(:silenced_at)
diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb
index 87fc285007867a129ec9a1baae59194cff9194e8..2366b9ca4af23c8dfb1c21b8411ce4217b329423 100644
--- a/spec/models/admin/account_action_spec.rb
+++ b/spec/models/admin/account_action_spec.rb
@@ -115,16 +115,16 @@ RSpec.describe Admin::AccountAction, type: :model do
     context 'account.local?' do
       let(:account) { Fabricate(:account, domain: nil) }
 
-      it 'returns ["none", "disable", "silence", "suspend"]' do
-        expect(subject).to eq %w(none disable silence suspend)
+      it 'returns ["none", "disable", "sensitive", "silence", "suspend"]' do
+        expect(subject).to eq %w(none disable sensitive silence suspend)
       end
     end
 
     context '!account.local?' do
       let(:account) { Fabricate(:account, domain: 'hoge.com') }
 
-      it 'returns ["silence", "suspend"]' do
-        expect(subject).to eq %w(silence suspend)
+      it 'returns ["sensitive", "silence", "suspend"]' do
+        expect(subject).to eq %w(sensitive silence suspend)
       end
     end
   end
diff --git a/spec/policies/account_policy_spec.rb b/spec/policies/account_policy_spec.rb
index 6648b0888bf6e830379875285f7699de23e4aeaf..d27e9d5b07e161296629ebdfd050d5e18942cfea 100644
--- a/spec/policies/account_policy_spec.rb
+++ b/spec/policies/account_policy_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe AccountPolicy do
   let(:admin)   { Fabricate(:user, admin: true).account }
   let(:john)    { Fabricate(:user).account }
 
-  permissions :index?, :show?, :unsuspend?, :unsilence?, :remove_avatar?, :remove_header? do
+  permissions :index?, :show?, :unsuspend?, :unsensitive?, :unsilence?, :remove_avatar?, :remove_header? do
     context 'staff' do
       it 'permits' do
         expect(subject).to permit(admin)