diff --git a/lib/philomena/users/ability.ex b/lib/philomena/users/ability.ex
index 527dea95..51eeac18 100644
--- a/lib/philomena/users/ability.ex
+++ b/lib/philomena/users/ability.ex
@@ -436,6 +436,14 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
       when action in [:show, :index],
       do: true
 
+  def can?(
+        %User{role_map: %{"Image" => %{"duplicate_access" => _}}},
+        action,
+        %Image{hidden_from_users: true, duplicate_id: duplicate_id}
+      )
+      when action in [:show, :index] and not is_nil(duplicate_id),
+      do: true
+
   def can?(_user, :show, %Tag{}), do: true
 
   # Comment on images where that is allowed
diff --git a/lib/philomena_web/templates/image/_image_meta.html.slime b/lib/philomena_web/templates/image/_image_meta.html.slime
index 23c88c19..2a81e03c 100644
--- a/lib/philomena_web/templates/image/_image_meta.html.slime
+++ b/lib/philomena_web/templates/image/_image_meta.html.slime
@@ -38,16 +38,18 @@
         i.fa.fa-sitemap>
         span.hide-limited-desktop.hide-mobile Related
     .stretched-mobile-links
-      a href="#{pretty_url(@image, false, false)}" rel="nofollow" title="View (tags in filename)"
+      - can_show = can?(@conn, :show, @image)
+
+      a href="#{pretty_url(@image, can_show, false, false)}" rel="nofollow" title="View (tags in filename)"
         i.fa.fa-eye>
         | View
-      a href="#{pretty_url(@image, true, false)}" rel="nofollow" title="View (no tags in filename)"
+      a href="#{pretty_url(@image, can_show, true, false)}" rel="nofollow" title="View (no tags in filename)"
         i.fa.fa-eye>
         | VS
-      a href="#{pretty_url(@image, false, true)}" rel="nofollow" title="Download (tags in filename)"
+      a href="#{pretty_url(@image, can_show, false, true)}" rel="nofollow" title="Download (tags in filename)"
         i.fa.fa-download>
         | Download
-      a href="#{pretty_url(@image, true, true)}" title="Download (no tags in filename)"
+      a href="#{pretty_url(@image, can_show, true, true)}" title="Download (no tags in filename)"
         i.fa.fa-download>
         | DS
   .image-metabar.flex.flex--wrap.block__header--user-credit.center--layout#extrameta
diff --git a/lib/philomena_web/templates/image/_image_target.html.slime b/lib/philomena_web/templates/image/_image_target.html.slime
index fba84b3a..0fe486dc 100644
--- a/lib/philomena_web/templates/image/_image_target.html.slime
+++ b/lib/philomena_web/templates/image/_image_target.html.slime
@@ -12,7 +12,7 @@
     ' .
 
   = if size == :full and not embed_display do
-    .image-target.hidden.image-show data-scaled=scaled_value(@conn.assigns.current_user) data-uris=Jason.encode!(thumb_urls(@image, can?(@conn, :hide, @image))) data-width=@image.image_width data-height=@image.image_height data-image-size=@image.image_size data-mime-type=@image.image_mime_type
+    .image-target.hidden.image-show data-scaled=scaled_value(@conn.assigns.current_user) data-uris=Jason.encode!(thumb_urls(@image, can?(@conn, :show, @image))) data-width=@image.image_width data-height=@image.image_height data-image-size=@image.image_size data-mime-type=@image.image_mime_type
       = if @image.image_mime_type == "video/webm" do
         video controls=true
       - else
diff --git a/lib/philomena_web/templates/image/deleted.html.slime b/lib/philomena_web/templates/image/deleted.html.slime
index fc425b36..b01fb656 100644
--- a/lib/philomena_web/templates/image/deleted.html.slime
+++ b/lib/philomena_web/templates/image/deleted.html.slime
@@ -32,7 +32,7 @@
       = link "rules of the site", to: "/pages/rules"
       ' . Other useful links can be found at the bottom of the page.
 
-= if can?(@conn, :hide, @image) do
+= if can?(@conn, :show, @image) do
   = render PhilomenaWeb.ImageView, "show.html", assigns
 - else
   p
diff --git a/lib/philomena_web/templates/image/show.html.slime b/lib/philomena_web/templates/image/show.html.slime
index 2c2a8f23..1c0789b4 100644
--- a/lib/philomena_web/templates/image/show.html.slime
+++ b/lib/philomena_web/templates/image/show.html.slime
@@ -19,7 +19,7 @@
     - @conn.assigns.current_ban ->
       = render PhilomenaWeb.BanView, "_ban_reason.html", conn: @conn
 
-    - @image.commenting_allowed ->
+    - can?(@conn, :create_comment, @image) ->
       = render PhilomenaWeb.Image.CommentView, "_form.html", image: @image, changeset: @comment_changeset, remote: true, conn: @conn
 
     - true ->
diff --git a/lib/philomena_web/views/admin/user_view.ex b/lib/philomena_web/views/admin/user_view.ex
index 19f33b48..68d8cd9c 100644
--- a/lib/philomena_web/views/admin/user_view.ex
+++ b/lib/philomena_web/views/admin/user_view.ex
@@ -58,6 +58,8 @@ defmodule PhilomenaWeb.Admin.UserView do
   def description("admin", "StaticPage"), do: "Manage static pages"
   def description("admin", "Image"), do: "Hard-delete images"
 
+  def description("duplicate_access", "Image"), do: "View duplicate images"
+
   def description(_name, _resource_type), do: "(unknown permission)"
 
   def filtered_roles(permission_set, roles) do
@@ -68,6 +70,7 @@ defmodule PhilomenaWeb.Admin.UserView do
 
   def general_permissions do
     [
+      ["duplicate_access", "Image"],
       ["batch_update", "Tag"]
     ]
   end
diff --git a/lib/philomena_web/views/api/json/image_view.ex b/lib/philomena_web/views/api/json/image_view.ex
index f72a676e..cc199b1a 100644
--- a/lib/philomena_web/views/api/json/image_view.ex
+++ b/lib/philomena_web/views/api/json/image_view.ex
@@ -17,81 +17,75 @@ defmodule PhilomenaWeb.Api.Json.ImageView do
     }
   end
 
-  def render("image.json", %{
-        image: %{hidden_from_users: true, duplicate_id: duplicate_id} = image
-      })
-      when not is_nil(duplicate_id) do
-    %{
-      id: image.id,
-      created_at: image.created_at,
-      updated_at: image.updated_at,
-      first_seen_at: image.first_seen_at,
-      duplicate_of: image.duplicate_id,
-      deletion_reason: nil,
-      hidden_from_users: true
-    }
-  end
+  def render("image.json", %{image: image} = assigns) do
+    user =
+      case assigns do
+        %{conn: %{assigns: %{current_user: current_user}}} -> current_user
+        _ -> nil
+      end
 
-  def render("image.json", %{image: %{hidden_from_users: true} = image}) do
-    %{
-      id: image.id,
-      created_at: image.created_at,
-      updated_at: image.updated_at,
-      first_seen_at: image.first_seen_at,
-      deletion_reason: image.deletion_reason,
-      duplicate_of: nil,
-      hidden_from_users: true
-    }
-  end
+    case Canada.Can.can?(user, :show, image) do
+      true ->
+        %{
+          id: image.id,
+          created_at: image.created_at,
+          updated_at: image.updated_at,
+          first_seen_at: image.first_seen_at,
+          width: image.image_width,
+          height: image.image_height,
+          mime_type: image.image_mime_type,
+          size: image.image_size,
+          orig_size: image.image_orig_size,
+          duration: image.image_duration,
+          animated: image.image_is_animated,
+          format: image.image_format,
+          aspect_ratio: image.image_aspect_ratio,
+          name: image.image_name,
+          sha512_hash: image.image_sha512_hash,
+          orig_sha512_hash: image.image_orig_sha512_hash,
+          tags: Enum.map(image.tags, & &1.name),
+          tag_ids: Enum.map(image.tags, & &1.id),
+          uploader: if(!!image.user and !image.anonymous, do: image.user.name),
+          uploader_id: if(!!image.user and !image.anonymous, do: image.user.id),
+          wilson_score: Philomena.Images.SearchIndex.wilson_score(image),
+          intensities: intensities(image),
+          score: image.score,
+          upvotes: image.upvotes_count,
+          downvotes: image.downvotes_count,
+          faves: image.faves_count,
+          comment_count: image.comments_count,
+          tag_count: length(image.tags),
+          description: image.description,
+          source_url:
+            if(Enum.count(image.sources) > 0, do: Enum.at(image.sources, 0).source, else: ""),
+          source_urls: Enum.map(image.sources, & &1.source),
+          view_url: ImageView.pretty_url(image, true, false, false),
+          representations: ImageView.thumb_urls(image, true),
+          thumbnails_generated: image.thumbnails_generated,
+          processed: image.processed,
+          deletion_reason: nil,
+          duplicate_of: image.duplicate_id,
+          hidden_from_users: image.hidden_from_users
+        }
+        |> Map.put(
+          :spoilered,
+          case assigns do
+            %{conn: conn} -> ImageView.filter_or_spoiler_hits?(conn, image)
+            _ -> false
+          end
+        )
 
-  def render("image.json", %{conn: conn, image: %{hidden_from_users: false} = image}) do
-    result = render_one(image, PhilomenaWeb.Api.Json.ImageView, "image.json", %{image: image})
-
-    Map.put(result, :spoilered, ImageView.filter_or_spoiler_hits?(conn, image))
-  end
-
-  def render("image.json", %{image: %{hidden_from_users: false} = image}) do
-    %{
-      id: image.id,
-      created_at: image.created_at,
-      updated_at: image.updated_at,
-      first_seen_at: image.first_seen_at,
-      width: image.image_width,
-      height: image.image_height,
-      mime_type: image.image_mime_type,
-      size: image.image_size,
-      orig_size: image.image_orig_size,
-      duration: image.image_duration,
-      animated: image.image_is_animated,
-      format: image.image_format,
-      aspect_ratio: image.image_aspect_ratio,
-      name: image.image_name,
-      sha512_hash: image.image_sha512_hash,
-      orig_sha512_hash: image.image_orig_sha512_hash,
-      tags: Enum.map(image.tags, & &1.name),
-      tag_ids: Enum.map(image.tags, & &1.id),
-      uploader: if(!!image.user and !image.anonymous, do: image.user.name),
-      uploader_id: if(!!image.user and !image.anonymous, do: image.user.id),
-      wilson_score: Philomena.Images.SearchIndex.wilson_score(image),
-      intensities: intensities(image),
-      score: image.score,
-      upvotes: image.upvotes_count,
-      downvotes: image.downvotes_count,
-      faves: image.faves_count,
-      comment_count: image.comments_count,
-      tag_count: length(image.tags),
-      description: image.description,
-      source_url:
-        if(Enum.count(image.sources) > 0, do: Enum.at(image.sources, 0).source, else: ""),
-      source_urls: Enum.map(image.sources, & &1.source),
-      view_url: ImageView.pretty_url(image, false, false),
-      representations: ImageView.thumb_urls(image, false),
-      thumbnails_generated: image.thumbnails_generated,
-      processed: image.processed,
-      deletion_reason: nil,
-      duplicate_of: nil,
-      hidden_from_users: false
-    }
+      false ->
+        %{
+          id: image.id,
+          created_at: image.created_at,
+          updated_at: image.updated_at,
+          first_seen_at: image.first_seen_at,
+          deletion_reason: image.deletion_reason,
+          duplicate_of: image.duplicate_id,
+          hidden_from_users: image.hidden_from_users
+        }
+    end
   end
 
   def render("error.json", %{changeset: changeset}) do
diff --git a/lib/philomena_web/views/image_view.ex b/lib/philomena_web/views/image_view.ex
index a10cad01..b795fec5 100644
--- a/lib/philomena_web/views/image_view.ex
+++ b/lib/philomena_web/views/image_view.ex
@@ -70,14 +70,8 @@ defmodule PhilomenaWeb.ImageView do
     |> Map.get(version_name, :full)
   end
 
-  defp append_full_url(urls, %{hidden_from_users: false} = image, _show_hidden),
-    do: Map.put(urls, :full, pretty_url(image, true, false))
-
-  defp append_full_url(urls, %{hidden_from_users: true} = image, true),
-    do: Map.put(urls, :full, thumb_url(image, true, :full))
-
-  defp append_full_url(urls, _image, _show_hidden),
-    do: urls
+  defp append_full_url(urls, image, show_hidden),
+    do: Map.put(urls, :full, pretty_url(image, show_hidden, true, false))
 
   defp append_gif_urls(urls, %{image_mime_type: "image/gif"} = image, show_hidden) do
     full_url = thumb_url(image, show_hidden, :full)
@@ -114,7 +108,10 @@ defmodule PhilomenaWeb.ImageView do
     "#{root}/#{year}/#{month}/#{day}/#{id_fragment}/#{name}.#{format}"
   end
 
-  def pretty_url(image, short, download) do
+  def pretty_url(%{hidden_from_users: true} = image, true, _short, _download),
+    do: thumb_url(image, true, :full)
+
+  def pretty_url(image, _show_hidden, short, download) do
     %{year: year, month: month, day: day} = image.created_at
     root = image_url_root()
 
diff --git a/priv/repo/seeds.json b/priv/repo/seeds.json
index 3c5f06d9..315cdd97 100644
--- a/priv/repo/seeds.json
+++ b/priv/repo/seeds.json
@@ -90,7 +90,8 @@
     {"name": "moderator", "resource_type": "Topic"},
     {"name": "admin", "resource_type": "Advert"},
     {"name": "admin", "resource_type": "StaticPage"},
-    {"name": "admin", "resource_type": "Image"}
+    {"name": "admin", "resource_type": "Image"},
+    {"name": "duplicate_access", "resource_type": "Image"}
   ],
   "pages": []
 }